|
 |
"koppi" <jak### [at] gmail com> wrote:
> "Leroy" <whe### [at] gmail com> wrote:
> > I was wondering how you place the dominoes. I use a spline for placement. I
> > have my dominoes placed 2 pov units apart. That because I don't use true physics
> > to move the dominoes.
>
> Archimedean spiral calculation is used to create the control points [1]:
>
> [... line 47]:
> local angle = (i - 1) * 0.09
> local radius = 5 + angle * 0.95
> cp = {
> x = math.cos(angle) * radius,
> y = y_pos,
> z = math.sin(angle) * radius,
> }
> [...]
>
I basically did the same but written in POV3.7.
> The control points are then fed to the Catmull-Rom spline function [2] with the
> tension parameter set to 0.5.
>
> > Noticed that your dominoes have different spacing, they got tighter toward the
> > center.
>
> I would like to have equal spacing between the dominoes, but I do not know how
> to calculate that, do you have an idea?
>
I'm a little late on this one, as you already have a better way than I have. I
wrote the spline starting from the outside in like normal. Then translated all
the control points so the outer point was <0,0,0>. That because these spirals
where made to be part of a bigger Field of dominoes and also be able to use a
spiral over & over & .....
I use this spline to hunt down each domino point that was 2 pov units from the
last domino placed. I started at 0 +some very small number (.0001 I think) then
keep adding that small value until I got vlength(Oldpoint,Newpoint) =2. The only
problem was at the very end when the search point goes out of range. So I put a
Stop Gap if the search counter got to big.(.1 is to big) not very efficient.
> > Your physics engine did a good job of dropping them. I also like the
> > wiggle the engine gave to the already down dominoes.
>
> I have been experimenting with different parameters for the friction,
> restitution, linear and angular damping of the dominoes, currently using:
>
> friction = 0.01
> restitution = 0.01
> damp_lin = 0.5
> damp_ang = 0.01
>
> Kind regards,
> koppi
>
> --
> [1]
>
https://github.com/bullet-physics-playground/bpp/blob/b558bdf8e8ab23a1438d0162d40c7f0029eb3efd/demo/basic/11-domino.l
ua
>
> [2]
>
https://github.com/bullet-physics-playground/bpp/blob/b558bdf8e8ab23a1438d0162d40c7f0029eb3efd/demo/module/spline.lua
#L
> 134
Have Fun!
Post a reply to this message
|
 |
|
 |
"koppi" <jak### [at] gmail com> wrote:
> "Leroy" <whe### [at] gmail com> wrote:
> > I was wondering how you place the dominoes. I use a spline for placement. I
> > have my dominoes placed 2 pov units apart. That because I don't use true physics
> > to move the dominoes.
>
> Archimedean spiral calculation is used to create the control points [1]:
>
> [... line 47]:
> local angle = (i - 1) * 0.09
> local radius = 5 + angle * 0.95
> cp = {
> x = math.cos(angle) * radius,
> y = y_pos,
> z = math.sin(angle) * radius,
> }
> [...]
>
> The control points are then fed to the Catmull-Rom spline function [2] with the
> tension parameter set to 0.5.
>
> > Noticed that your dominoes have different spacing, they got tighter toward the
> > center.
>
> I would like to have equal spacing between the dominoes, but I do not know how
> to calculate that, do you have an idea?
> ...
Below is an example in POV-Ray SDL that places dominoes at a fixed
distance from each other along an Archimedean spiral (without using
splines).
A Newton-Raphson solver macro is used to find the placement points
analytically for high precision.
The dominoes are also oriented by a Frenet-Serret frame so that they
always face the same side forward along the spiral.
--
Tor Olav
http://subcube.com
https://github.com/t-o-k
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
#version 3.7;
global_settings {
assumed_gamma 1
ambient_light color rgb 0.2*<1, 1, 1>
}
#include "colors.inc"
#declare tau = 2*pi;
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Newton-Raphson macro to find the root of a function.
// Used in this example to find the angle (Theta) that
// corresponds to a given arc length.
#macro NewtonRaphson(Fn, DerFn, EstimatedRoot, Tolerance, MaxIter)
#local Nil = 1e-12;
#local EstRoot = EstimatedRoot;
#if (Tolerance <= 0)
#local Tolerance = 1e-6;
#end // if
#local I = 0;
#local Continue = true;
#while (Continue)
#local DerVal = DerFn(EstRoot);
#local UseableTangent = (Nil < abs(DerVal));
#if (UseableTangent)
#local CloserRoot = EstRoot - Fn(EstRoot)/DerVal;
#local Delta = abs(CloserRoot - EstRoot);
#local EstRoot = CloserRoot;
#local I = I + 1;
#local Continue = ((Tolerance < Delta) & (I < MaxIter));
#else
#local Continue = false;
#end // if
#end // while
EstRoot
#end // macro NewtonRaphson
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Archimedes spiral (radius = g * th)
// _g: Growth rate (how fast the spiral spreads outward).
// The radius increases by _g*tau mm per full revolution.
// _th: Rotation angle in radians.
// Position functions (calculates x and z from polar coordinates)
// <x, 0, z> are the cartesian coordinates for a point on the
// spiral at angle _th.
#declare FnX = function(_g, _th) { _g*_th*cos(_th) };
#declare FnZ = function(_g, _th) { _g*_th*sin(_th) };
// First derivatives of the functions (velocity),
// used to determine the tangent vector/direction of the curve.
#declare DerFnX = function(_g, _th) { _g*(cos(_th) - _th*sin(_th)) };
#declare DerFnZ = function(_g, _th) { _g*(sin(_th) + _th*cos(_th)) };
/*
Arc length function: Calculates the distance traveled along the spiral.
_g: Growth rate (how fast the spiral spreads outward).
_th: Final angle in radians (the angle the spiral has passed through).
*/
/*
#declare ArcLengthFn =
function(_g, _th) {
_g/2*(
_th*sqrt(1 + pow(_th, 2)) +
ln(_th + sqrt(1 + pow(_th, 2)))
)
}
;
#declare Asinh(_th) =
function(_th) {
ln(_th + sqrt(1 + pow(_th, 2)))
}
;
*/
// Calculates the total distance traveled along the spiral curve,
// from the center to point the final angle.
#declare ArcLengthFn =
function(_g, _th) {
_g/2*(_th*sqrt(1 + pow(_th, 2)) + asinh(_th))
}
;
// The first derivative of the arc length function:
#declare DerArcLengthFn =
function(_g, _th) {
_g*sqrt(1 + pow(_th, 2))
}
;
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Domino piece geometry (L x W x T: 48mm x 24mm x 10mm)
// Oriented so it stands on the xz plane, growing in y.
#declare DominoPiece =
union {
// Centered at origin
box {
-<12, 24, 5>, +<12, 24, 5>
pigment { color White }
}
// Direction markers for debugging the matrix orientation:
cylinder {
+12*x, +16*x, 2 // Local +x (Normal)
pigment { color Red }
}
cylinder {
+24*y, +28*y, 2 // Local +y (Binormal)
pigment { color Green }
}
cylinder {
+5*z, +9*z, 2 // Local +z (Tangent)
pigment { color Blue }
}
// Move bottom of piece to y = 0
translate +24*y
}
#declare NoOfPoints = 300; // Also the number of dominoes.
#declare GrowthRate = 60/tau; // mm/radian
// The radial distance between centerlines of successive
// windings (the pitch) will be 60mm.
// Distance between centers of dominoes along the spiral path.
#declare StepLength = 25; // mm
// Calculate angles (Thetas) for each domino using numerical inversion.
#debug "\n"
#declare Thetas = array[NoOfPoints];
#declare Thetas[0] = 0;
#for (I, 1, NoOfPoints - 1)
#declare TargetLength = I*StepLength;
#declare Thetas[I] =
NewtonRaphson(
function(_th) {
ArcLengthFn(GrowthRate, _th) - TargetLength
},
function(_th) {
DerArcLengthFn(GrowthRate, _th)
},
Thetas[I-1], // Use previous angle as start estimate
1e-6,
10
)
;
#declare AchievedLength = ArcLengthFn(GrowthRate, Thetas[I]);
#debug str(AchievedLength - TargetLength, 0, 14)
#debug "\n"
#end // for
#debug "\n"
// Define specific instances of the functions
// for the chosen growth rate
#declare X_Fn = function(_th) { FnX(GrowthRate, _th) };
#declare Z_Fn = function(_th) { FnZ(GrowthRate, _th) };
#declare DerX_Fn = function(_th) { DerFnX(GrowthRate, _th) };
#declare DerZ_Fn = function(_th) { DerFnZ(GrowthRate, _th) };
/*
pP: Position on spiral
vT: Tangent vector (Forward direction)
vB: Binormal vector (Up direction)
vN: Normal vector (Side direction, perpendicular to curve)
*/
// Render the dominoes
union {
#declare vB = vnormalize(<0, 1, 0>); // = <0, 1, 0>
// Start at 1 to skip the domino piece in the center
#for (I, 1, NoOfPoints - 1)
#declare Th = Thetas[I];
#declare pP = <X_Fn(Th), 0, Z_Fn(Th)>;
#declare vT = vnormalize(<DerX_Fn(Th), 0, DerZ_Fn(Th)>);
#declare vN = vcross(vB, vT);
object {
DominoPiece
matrix <
vN.x, vN.y, vN.z, // Maps local x to Side
vB.x, vB.y, vB.z, // Maps local y to Up
vT.x, vT.y, vT.z, // Maps local z to Forward
pP.x, pP.y, pP.z // Translates to spiral position
>
}
#end // for
}
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
sky_sphere { pigment { color Gray } }
// A checkered floor plane to provide visual context and shadows
plane {
y, 0 // The ground plane at y = 0
pigment {
checker
color 0.05*White // Dark squares
color 0.60*White // Light squares
scale 60 // Each square matches the pitch of the spiral (60mm)
}
}
light_source {
100*<6, 14, 3>
color White
}
#declare AspectRatio = image_width/image_height;
camera {
orthographic
location +1000*y
right +900*AspectRatio*x
up +900*z
direction -y
}
/*
camera {
location 120*<+1, +3, -5>
look_at 100*< 0, -1, 0>
}
*/
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
Post a reply to this message
|
 |