![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
It does sound interesting, but also a little above
my head at the moment... Nontheless, thanks
for link, perhaps I can make something of it when
having more time to spend on it...
Regards,
Tim
--
Tim Nikias v2.0
Homepage: http://www.digitaltwilight.de/no_lights
> This looked promising, if you're willing to puzzle through it:
>
> http://www.cis.upenn.edu/~badler/gmod/0528a.pdf
>
>
---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.501 / Virus Database: 299 - Release Date: 14.07.2003
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
On Sat, 19 Jul 2003 00:46:01 +0200, Tim Nikias v2.0 <tim### [at] gmx de>
wrote:
> Anyone got any reference links I could begin with?
Here's a fairly nice, easy-to-understand one:
http://freespace.virgin.net/hugo.elias/models/m_ik.htm
I recommend checking out the rest of his site as well,
if you're not already familiar with it. Lots of nice
stuff there.
-Johannes
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <3f192104$1@news.povray.org>, tim### [at] gmx de says...
> It does sound interesting, but also a little above
> my head at the moment... Nontheless, thanks
> for link, perhaps I can make something of it when
> having more time to spend on it...
>
Simplest definition is that Inverse Kinematics uses some sort of nesting
of objects. In SDL this is easy:
union {
Object1
Object {
Object2
rotate <x2,y2,z2>
}
rotate <x1,y1,z1>
}
Rotating by x1, y1, z1 will automatically move both objects, while x2,
y2, z2 only move the nested one. The trick here is positioning. Each
objects rotation 'must' be at the origin (or specifically the point
around which you want to rotate it). Thus for a cylinder you want to
position the end you want to be the 'center' so it is at <0,0,0>. Example
(ignoring any syntax errors I made... lol):
#declare x1 = 0; //Segment 1 (upper arm perhaps?)
#declare y1 = 0;
#declare z1 = 0;
#declare x2 = 0; //Segment 2 and joint (lower arm)
#declare y2 = 90;
#declare z2 = 0;
union {
cylinder{<0,0,0>,<1,1,1>,2} //First segment.
union {
sphere {<0,0,0),2} //Joint
cylinder {<0,0,0>,<1,1,1>,2} //Second Segment.
rotate <x2 ,y2, z2> //Rotate them around 0,0,0 'first' to position.
translate <1,1,1> //Move them to the end of the first segment.
}
rotate <x1,y1,z1> //Rotate the first 'and' linked second segment.
translate ... //Move to where ever you need the entire chain.
}
For a complex object like a robot you would start with some the fingers
and work backward toward the body, attaching each new part to it in this
way, by first rotating it to the direction you want it pointed, then
moving it to the correct place in relation to the next object. As long as
all objects are properly nested, moving the torso of the robot will also
move the arms and legs, but rotating the left arm will only effect the
lower arm, the hand, fingers and what ever else is attached to that chain
of objects. The critical thing is as I said, to make sure that the point
you want the object to move around 'starts' at the center of the
rendering world, before you move it. Then it is just a matter of changing
the rotation of each of these objects to put them where you need them.
Then all you do is change the values of the variable you used and
everything will move properly.
It is really quite simple, but definitely easier in the SDL than other
programs. Trying to do the same thing in a modeller is a pain, since
unless it specifically supports Inverse Kinematics or 'IK chains' getting
all the objects tied together properly and working can be a pain. It is
much easier to fix something when you can specifically define the order
rotation and translation happen, than to fiddle with a modeller that may
force a specific order on those actions.
The Raytracing Worlds book on POV-Ray had an explanation of how all this
worked, going through the process step by step. However, I think it was a
tutorial on using Moray to construct it. Moray has built in features to
limit the amount and direction you can rotate stuff, so you won't rotate
the arm into the middle of the body and stuff like that. In the SDL you
have to be a bit more careful.
--
void main () {
call functional_code()
else
call crash_windows();
}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
"Patrick Elliott" <sha### [at] hotmail com> wrote in message
news:MPG.19836835a2284e4b98983c@news.povray.org...
> In article <3f192104$1@news.povray.org>, tim### [at] gmx de says...
> > It does sound interesting, but also a little above
> > my head at the moment... Nontheless, thanks
> > for link, perhaps I can make something of it when
> > having more time to spend on it...
> >
>
> Simplest definition is that Inverse Kinematics uses some sort of nesting
> of objects. In SDL this is easy:
>
> union {
> Object1
> Object {
> Object2
> rotate <x2,y2,z2>
> }
> rotate <x1,y1,z1>
> }
>
An array-based approach works too.
#declare ataObjs = array[8] { ataBase, ataSectB, ataSectM, ataSectM,
ataSectM, ataSectH, ataHandL, ataHandR }
#declare ataLens = array[8] { atabHgtB, atasH, atasH, atasH, atasH, atasH,
0, 0 }
#declare atArmAng = array[1][3]
#declare atArmAng[0][0] = array[7] { <-40, 20,-35>, x*26, x*30 , x*28, x*33,
x* 5,-x*10 }
#declare atArmAng[0][1] = array[7] { < 10, 70, 5>, x* 6, x* 4 , x* 8, x*13,
x*10,-x*20 }
#declare atArmAng[0][2] = array[7] { <- 3,-90,-15>, x*10, x* 8 , x*14, x*11,
x*15,-x*30 }
#declare ataMoves = array[7]
#macro ManipArm(Objects, Lengths, Joints, Moves)
#local aSiz = dimension_size(Joints,1);
#debug concat(str(aSiz,0,0), " objects.\n")
#local ps = 0;
#while (ps<aSiz)
#local rt = ps;
#declare Moves[ps] = transform {
#while (rt>=0)
rotate Joints[rt]
translate y*Lengths[rt]
#local rt = rt - 1;
#end
}
#local ps = ps + 1;
#end
union {
#set ps = 0;
object { Objects[ps] }
#while (ps<aSiz)
#local ps = ps + 1;
object { Objects[ps] transform { Moves[ps-1] } }
#end
}
#end
#macro atArm(obn, arn) object { ManipArm(ataObjs, ataLens,
atArmAng[obn][arn], ataMoves) } #end
The idea is to set up the transforms for each object first so that nesting
becomes unnecessary:
If you want the object definitions check out my "Manipulator arm" thread.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <3f1bbad4@news.povray.org>, dar### [at] earthlink net says...
>
> "Patrick Elliott" <sha### [at] hotmail com> wrote in message
> news:MPG.19836835a2284e4b98983c@news.povray.org...
> > In article <3f192104$1@news.povray.org>, tim### [at] gmx de says...
> > > It does sound interesting, but also a little above
> > > my head at the moment... Nontheless, thanks
> > > for link, perhaps I can make something of it when
> > > having more time to spend on it...
> > >
> >
> > Simplest definition is that Inverse Kinematics uses some sort of nesting
> > of objects. In SDL this is easy:
> >
> > union {
> > Object1
> > Object {
> > Object2
> > rotate <x2,y2,z2>
> > }
> > rotate <x1,y1,z1>
> > }
> >
> An array-based approach works too.
>
> #declare ataObjs = array[8] { ataBase, ataSectB, ataSectM, ataSectM,
> ataSectM, ataSectH, ataHandL, ataHandR }
> #declare ataLens = array[8] { atabHgtB, atasH, atasH, atasH, atasH, atasH,
> 0, 0 }
> #declare atArmAng = array[1][3]
> #declare atArmAng[0][0] = array[7] { <-40, 20,-35>, x*26, x*30 , x*28, x*33,
> x* 5,-x*10 }
> #declare atArmAng[0][1] = array[7] { < 10, 70, 5>, x* 6, x* 4 , x* 8, x*13,
> x*10,-x*20 }
> #declare atArmAng[0][2] = array[7] { <- 3,-90,-15>, x*10, x* 8 , x*14, x*11,
> x*15,-x*30 }
> #declare ataMoves = array[7]
>
> #macro ManipArm(Objects, Lengths, Joints, Moves)
> #local aSiz = dimension_size(Joints,1);
> #debug concat(str(aSiz,0,0), " objects.\n")
> #local ps = 0;
> #while (ps<aSiz)
> #local rt = ps;
> #declare Moves[ps] = transform {
> #while (rt>=0)
> rotate Joints[rt]
> translate y*Lengths[rt]
> #local rt = rt - 1;
> #end
> }
> #local ps = ps + 1;
> #end
> union {
> #set ps = 0;
> object { Objects[ps] }
> #while (ps<aSiz)
> #local ps = ps + 1;
> object { Objects[ps] transform { Moves[ps-1] } }
> #end
> }
> #end
>
> #macro atArm(obn, arn) object { ManipArm(ataObjs, ataLens,
> atArmAng[obn][arn], ataMoves) } #end
>
> The idea is to set up the transforms for each object first so that nesting
> becomes unnecessary:
>
> If you want the object definitions check out my "Manipulator arm" thread.
>
Yes, such an approach 'is' possible, but far more complex, especially for
very complex mechanisms. Nesting has the advantage of providing a clear
structure for the objects relationships within the SDL code itself. You
can see immediately where you screwed something up by incorrectly nesting
it. Using an array system requires, for one thing keeping track of the
current position of 'both' ends, since sub objects do not automatically
move to match to position and location of their parent in such a system.
It isn't something I would attempt to make adjustments to by hand. ;)
--
void main () {
call functional_code()
else
call crash_windows();
}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> > An array-based approach works too.
> >
> > #declare ataObjs = array[8] { ataBase, ataSectB, ataSectM, ataSectM,
> > ataSectM, ataSectH, ataHandL, ataHandR }
> > #declare ataLens = array[8] { atabHgtB, atasH, atasH, atasH, atasH,
atasH,
> > 0, 0 }
> > #declare atArmAng = array[1][3]
> > #declare atArmAng[0][0] = array[7] { <-40, 20,-35>, x*26, x*30 , x*28,
x*33,
> > x* 5,-x*10 }
> > #declare atArmAng[0][1] = array[7] { < 10, 70, 5>, x* 6, x* 4 , x* 8,
x*13,
> > x*10,-x*20 }
> > #declare atArmAng[0][2] = array[7] { <- 3,-90,-15>, x*10, x* 8 , x*14,
x*11,
> > x*15,-x*30 }
> > #declare ataMoves = array[7]
> >
> > #macro ManipArm(Objects, Lengths, Joints, Moves)
> > #local aSiz = dimension_size(Joints,1);
> > #debug concat(str(aSiz,0,0), " objects.\n")
> > #local ps = 0;
> > #while (ps<aSiz)
> > #local rt = ps;
> > #declare Moves[ps] = transform {
> > #while (rt>=0)
> > rotate Joints[rt]
> > translate y*Lengths[rt]
> > #local rt = rt - 1;
> > #end
> > }
> > #local ps = ps + 1;
> > #end
> > union {
> > #set ps = 0;
> > object { Objects[ps] }
> > #while (ps<aSiz)
> > #local ps = ps + 1;
> > object { Objects[ps] transform { Moves[ps-1] } }
> > #end
> > }
> > #end
> >
> > #macro atArm(obn, arn) object { ManipArm(ataObjs, ataLens,
> > atArmAng[obn][arn], ataMoves) } #end
> >
> > The idea is to set up the transforms for each object first so that
nesting
> > becomes unnecessary:
> >
> > If you want the object definitions check out my "Manipulator arm"
thread.
> >
>
> Yes, such an approach 'is' possible, but far more complex, especially for
> very complex mechanisms. Nesting has the advantage of providing a clear
> structure for the objects relationships within the SDL code itself. You
> can see immediately where you screwed something up by incorrectly nesting
> it. Using an array system requires, for one thing keeping track of the
> current position of 'both' ends, since sub objects do not automatically
> move to match to position and location of their parent in such a system.
> It isn't something I would attempt to make adjustments to by hand. ;)
>
What the ataLens array does is position each object onto the meeting point
of its parent. This only has to be done when (re)designing the object. The
ataArmAng array "poses" the structure. The ManipArm macro takes the
individual positioning and posing transforms and combines them in reverse
order. My macro is a bit basic in that it assumes the connecting sections
pile up vertically. ataLens could just as easily contain 3D vectors,
matrices, or transforms.
In your nested structure you still have to pose each item and position it
onto the end of its parent. The result is an object which you then
transform again, etc. All I did was use a macro to combine the transforms
in ataLens into a single transform in ataMoves for each arm segment. You
don't have to "make adjustments by hand"-- the ManipArm macro makes them for
you. The posing transforms need to be watched in both systems, however.
The issue I have with nesting comes from what I suspect are limits within
POV-Ray on the number of nested levels you can have. It's not that nesting
is inherently wrong; it actually works for simple models. But heaven help
you if you want to build a millipede using nesting.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
In article <3f1d8d00@news.povray.org>, dar### [at] earthlink net says...
> In your nested structure you still have to pose each item and position it
> onto the end of its parent. The result is an object which you then
> transform again, etc. All I did was use a macro to combine the transforms
> in ataLens into a single transform in ataMoves for each arm segment. You
> don't have to "make adjustments by hand"-- the ManipArm macro makes them for
> you. The posing transforms need to be watched in both systems, however.
>
Yes, but you can just as easily use an array to keep track of each
rotation. However, in both cases you end up having to remember 'which'
set up data belong to what item in such a case. Unless you have an
external program that shows and and keep track of all these, you are
better off having all leg motions in one array, arm motions in another,
etc. If everything is stored this way you have a big bloody mess,
especially if you drop the project for a few months and then come back
and realize you haven't a clue what belongs where or why. ;) Maybe
something in between would work better.
> The issue I have with nesting comes from what I suspect are limits within
> POV-Ray on the number of nested levels you can have. It's not that nesting
> is inherently wrong; it actually works for simple models. But heaven help
> you if you want to build a millipede using nesting.
>
Not necessarily.. I think it is 'levels' of nesting that are an issue,
not the total objects you nest. For a millipede you are looking at
roughly 4 layers for the legs and a body segment. If the body itself is a
spline, then you could use a surface trace or some other method to locate
each pair of legs (which makes it exactly 4 levels, not including extra
segments for antennae). Unless you are a total fool, you end up with a
nesting level of no more than 4-5 levels maximum. I frankly can't think
of anything that should require extreme amounts of nesting (though this
won't stop someone from doing it). At worst you might have some object
you don't want to move, but still be attached to a level above and that
would add an extra sub group at 'that' nesting level. I could be wrong
about how the limit works. But one thing I do know, it is a bad idea to u
unnecessarily complicate a model by dumping the whole thing into an array
where the most someone, who doesn't have graph paper and lots of
patience, can say is 'well that object is located somewhere in the
model...'. lol
--
void main () {
call functional_code()
else
call crash_windows();
}
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
> I think it is 'levels' of nesting that are an issue
I've tried 1500 nested rhombododecahedrons: it works, but took
over 20 minutes of parsing time at 1 GHz because *all* objects
nested so far have to be transformed at every level, making the
time required for transformations proportional to the square of
the levels (when objects of comparable complexity at every level
are nested). 50 rhombododecahedrons take only 1 second, so very
complicated robot arms or even chains are easily possible with
the nesting method.
Sputnik
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Hi Tim Nikias v2.0, you recently wrote in povray.advanced-users:
> Anyone got any reference links I could begin with?
I don't have the link, but Game Developer Magazine had an excellent
series (with basic source code) that illustrated the concepts very
nicely.... try www.gdmag.com and see if you can find it....
- Lutz
email : lut### [at] stmuc com
Web : http://www.stmuc.com/moray
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
We did that with the rings animation (job 1) on the Internet Movie Project
(www.imp.org)
this method is very simple to get interesting results
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |