POV-Ray : Newsgroups : povray.advanced-users : Boneheaded 3D trig question Server Time
26 Nov 2024 09:21:03 EST (-0500)
  Boneheaded 3D trig question (Message 1 to 3 of 3)  
From: Rick Gutleber
Subject: Boneheaded 3D trig question
Date: 12 Sep 2000 12:25:18
Message: <39be58ee@news.povray.org>
I've got a simple question that's bugged me for years.  The answer's got to
be simple, but I just can't figure it out.

I'm writing a C++ program to programmatically generate a Christmas tree and
I'm trying to put needles on the branches.  I have the start and end point
of the branch so I figured I would create the needles as if the branch
started at the origin and pointed straight up and then just translate and
rotate the union of the resulting needles so they actually appear on the
branch in the scene.  This translatation/rotation can occur in my C++ code
or the generated POV script, whichever is easier.

I've got an arbitary unit vector that reflects the orientation of the branch
(from VNormalize( ) in POV, or the good old Pythagorean distance function in
my C++ code), how do I turn that into an equivalent rotate < x, y, z >
statement so the needles end up on the branch?  I'm sure it's just the right
combination of atan( ) calls, but the details elude my addled brain.

Thanks for the help!

Rick
ric### [at] hiscom


Post a reply to this message

From: Tor Olav Kristensen
Subject: Re: Boneheaded 3D trig question
Date: 12 Sep 2000 16:35:17
Message: <39BE923A.4ED69247@online.no>
Rick Gutleber wrote:

> I've got a simple question that's bugged me for years.  The answer's got to
> be simple, but I just can't figure it out.
>
> I'm writing a C++ program to programmatically generate a Christmas tree and
> I'm trying to put needles on the branches.  I have the start and end point
> of the branch so I figured I would create the needles as if the branch
> started at the origin and pointed straight up and then just translate and
> rotate the union of the resulting needles so they actually appear on the
> branch in the scene.  This translatation/rotation can occur in my C++ code
> or the generated POV script, whichever is easier.
>
> I've got an arbitary unit vector that reflects the orientation of the branch
> (from VNormalize( ) in POV, or the good old Pythagorean distance function in
> my C++ code), how do I turn that into an equivalent rotate < x, y, z >
> statement so the needles end up on the branch?  I'm sure it's just the right
> combination of atan( ) calls, but the details elude my addled brain.

If I have understood your problem correctly, then
you only need rotations around two axes to do this.

See POV-code below for some of my suggestions.


Tor Olav
--
mailto:tor### [at] hotmailcom
http://www.crosswinds.net/~tok/tokrays.html

P.S:
In POV-script YOU don't need to Pythagoras' formula
to calculate the distance between two points.
You can find it this way:

#declare Distance = vlength(PointB - PointA);

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#declare AnyThing = cylinder { 0*y, 6*y, 1 }
#declare vOrientation = <1, -2, -1>;
#declare vPosition = <2, 1, -1>;


// You can find the angles like this:
#declare AngleX = acos(vOrientation.x/vlength(vOrientation*<1, 0, 1>));
#declare AngleY = acos(vOrientation.y/vlength(vOrientation));

/*
// Or like this:
#declare AngleX = acos(vnormalize((x + z)*vOrientation).x);
#declare AngleY = acos(vnormalize(vOrientation).y);
*/


// If the vector vOrientation points "downwards" then make the
// rotation go the other way around the Y-axis
#if (vOrientation.z < 0)
  #declare AngleX = -AngleX;
#end // if


// Now "tilt" the object
#declare TiltedThing =
object {
  AnyThing
  rotate  degrees(AngleX)*y
  rotate -degrees(AngleY)*z
  rotate -degrees(AngleX)*y
}


// Then put it in place and give it a pigment
object {
  TiltedThing
  translate vPosition
  pigment { color <1, 0, 0> }
}

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
/*
// Or you can make a macro for it like I did:
#macro Tilt(Thing, Vector)

  #local xAngle = (Vector.z < 0 ? -1 : 1)*
                  degrees(acos(vnormalize((x + z)*Vector).x));
  #local yAngle = degrees(acos(vnormalize(Vector).y));

  object {
    Thing
    rotate  xAngle*y
    rotate -yAngle*z
    rotate -xAngle*y
  }

#end // macro Tilt


object {
  Tilt(AnyThing, vOrientation)
  pigment { color <0, 1, 0> }
  translate vPosition
}
*/
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Or you can calculate a matrix for the complete  transformation
// and then apply that matrix to the object once.
// John VanSickle's Reorient macro does that (and more) for
// the rotational part of such a transformation.
// See: http://users.erols.com/vansickl/macs.htm
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7


Post a reply to this message

From: Geoff Wedig
Subject: Re: Boneheaded 3D trig question
Date: 13 Sep 2000 08:30:58
Message: <39bf7382@news.povray.org>
Rick Gutleber <ric### [at] hiscom> wrote:
> I've got a simple question that's bugged me for years.  The answer's got to
> be simple, but I just can't figure it out.

> I'm writing a C++ program to programmatically generate a Christmas tree and
> I'm trying to put needles on the branches.  I have the start and end point
> of the branch so I figured I would create the needles as if the branch
> started at the origin and pointed straight up and then just translate and
> rotate the union of the resulting needles so they actually appear on the
> branch in the scene.  This translatation/rotation can occur in my C++ code
> or the generated POV script, whichever is easier.

> I've got an arbitary unit vector that reflects the orientation of the branch
> (from VNormalize( ) in POV, or the good old Pythagorean distance function in
> my C++ code), how do I turn that into an equivalent rotate < x, y, z >
> statement so the needles end up on the branch?  I'm sure it's just the right
> combination of atan( ) calls, but the details elude my addled brain.

> Thanks for the help!

I've found the following two macros to be of great help:

#macro vector_rotation(vect)
  #local AngleX = degrees(atan2(vect.z, vlength(<vect.x,vect.y,0>)));
  #if (vect.y>0.0001)
    #local AngleZ = degrees(atan2(-vect.x,vect.y));
  #end
  #if (vect.y<-.0001)
    #local AngleZ = degrees(atan2(-vect.x,vect.y));
  #end
  #if (vect.y<= 0.0001 & vect.y >=-.0001)
    #if (vect.x>0)
      #local AngleZ=-90;
    #else
      #local AngleZ=90;
    #end
  #end
  
  (<AngleX, 0, AngleZ>)

#end                   

#macro reverse_rotate(point, rot)

  vrotate(vrotate(vrotate(point,-rot * z), -rot * y), -rot * x)

#end

The first, given a vector, returns a rotation that will turn a <0,n,0>
vector into it.  Note that it is only one solution.  There are an infinite
number of solutions.  A rotate y previous to the rotate x can be used to
turn the vector about its axis if necessary (I've been meaning to change
this so it uses a <1,0,0> vector and returns a <0, x, y> rotation, so I can
rotate about the x freely, but I've just never found the time.

The second, given a point and a rotation does the *opposite* rotation on it. 
This is useful for when you've got a point you must have the object touch,
but you've constructed the object with a different rotation.  This returns
the point in the initial reference frame that the object must touch. (Note,
you can either use this once, print the result and modify the object
accordingly, or you can just let POV do the work.  The former is faster, but
more work for you)

Geoff


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.