The Amiga Boing ball, bouncing inside the 3D axis box, driven from the server.
Each timer tick sends only the transformations of the ball and its shadow. The ball also carries a trajectory, set with REveTrans::SetMotion(), which the client extrapolates between updates. The shadow carries none and steps to each new position. Run with a long period, e.g. boing(500), to see the difference. Select the ball to edit its REveSMorph parameters while it bounces. The Motion panel of the viewer's editor sets the update and redraw rates and switches the extrapolation off.
#include <chrono>
const Float_t kBX = 40, kBY = 30, kBZ = 40;
class Boinger :
public TTimer {
std::chrono::steady_clock::time_point fLast{std::chrono::steady_clock::now()};
std::chrono::steady_clock::time_point fT0{std::chrono::steady_clock::now()};
int fSent{0};
static constexpr Double_t kSpinRate = 2.4;
{
};
linear(fX, fVx, kBX - kR);
linear(fZ, fVz, kBZ - kR);
if (disc < 0)
continue;
}
}
{
}
}
public:
int GetSent() const { return fSent; }
{
++fSent;
auto now = std::chrono::steady_clock::now();
Double_t dt = std::chrono::duration<double>(now - fLast).count();
fLast = now;
if (dt > 0.1)
dt = 0.1;
if (fSent % 100 == 0) {
Double_t el = std::chrono::duration<double>(now - fT0).count();
::Info(
"boing",
"%d ticks, %.1f/s over %.1f s", fSent, fSent / el, el);
}
Bounce(fX, fVx, kBX - kR);
Bounce(fY, fVy, kBY - kR);
Bounce(fZ, fVz, kBZ - kR);
}
Double_t e2[3] = { -st * cs, ct * cs, sn };
Double_t e3[3] = { st * sn, -ct * sn, cs };
t.SetBaseVec(1, kR * e1[0], kR * e1[1], kR * e1[2]);
t.SetBaseVec(2, kR * e2[0], kR * e2[1], kR * e2[2]);
t.SetBaseVec(3, kR * e3[0], kR * e3[1], kR * e3[2]);
t.SetPos(fX, fY, fZ);
fBall->SetTransMatrix(t.Array());
fBall->RefMainTrans().SetMotion(vel, acc, spin_axis, kSpinRate, TimeToNextBounce());
sh.SetBaseVec(1, 0, 0.02 * kR, 0);
sh.SetBaseVec(2, s, 0, 0);
sh.SetBaseVec(3, 0, 0, s);
sh.SetPos(fX, -kBY + 0.02 * kR, fZ);
fShadow->SetTransMatrix(sh.Array());
}
};
void boing(
Long_t period_ms = 40)
{
auto eveMng = REveManager::Create();
eveMng->AllowMultipleRemoteConnections(false, false);
auto viewer = eveMng->GetDefaultViewer();
viewer->SetAxesType(REveViewer::kAxesEdge);
viewer->SetAxesUpAxis(1);
viewer->SetAxesBBox(-kBX, -kBY, -kBZ, kBX, kBY, kBZ);
auto scene = eveMng->GetEventScene();
ball->SetTLevel(32);
ball->SetPLevel(48);
ball->SetTexture("checker_8.png");
ball->SetPickable(
kTRUE);
ball->SetRadius(kR);
scene->AddElement(ball);
shadow->SetTLevel(6);
shadow->SetPLevel(32);
shadow->SetThetaMax(0.5);
shadow->SetMainTransparency(20);
scene->AddElement(shadow);
eveMng->Show();
(new Boinger(ball, shadow, period_ms))->TurnOn();
}
bool Bool_t
Boolean (0=false, 1=true) (bool)
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
float Float_t
Float 4 bytes (float)
double Double_t
Double 8 bytes.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
RAII guard for locking Eve manager (ctor) and processing changes (dtor).
A parametric, texture-mapped surface of spherical topology: a sphere that can be twisted,...
REveTrans is a 4x4 transformation matrix for homogeneous coordinates stored internally in a column-ma...
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Handles synchronous and a-synchronous timer events.
void Reset()
Reset the timer.
Bool_t Notify() override
Notify when timer times out.
Namespace for ROOT features in testing.
constexpr Double_t PiOver2()
Double_t Sqrt(Double_t x)
Returns the square root of x.
Short_t Min(Short_t a, Short_t b)
Returns the smallest of a and b.
Double_t Cos(Double_t)
Returns the cosine of an angle of x radians.
Double_t Sin(Double_t)
Returns the sine of an angle of x radians.
Short_t Abs(Short_t d)
Returns the absolute value of parameter Short_t d.