POV-Ray : Newsgroups : povray.advanced-users : Simple one Server Time
28 Jul 2024 08:26:28 EDT (-0400)
  Simple one (Message 1 to 9 of 9)  
From: Orchid XP v2
Subject: Simple one
Date: 11 Mar 2006 15:54:40
Message: <44133910@news.povray.org>
OK, this is going to take somebody about 3 seconds to answer I would 
think...

I have an object who's surface normal is +Y. I need to rotate it in such 
a way that its surface normal becomes equal to a user-supplied vector. 
How do I figure out the necessary angles?


Post a reply to this message

From: Orchid XP v2
Subject: Re: Simple one
Date: 11 Mar 2006 16:10:09
Message: <44133cb1$1@news.povray.org>
> OK, this is going to take somebody about 3 seconds to answer I would 
> think...
> 
> I have an object who's surface normal is +Y. I need to rotate it in such 
> a way that its surface normal becomes equal to a user-supplied vector. 
> How do I figure out the necessary angles?

By a process of elimination, I eventually managed to puzzle out 
something that works...

#declare O = object {with surface normal = +y};
#declare K = <what you want the surface normal to become>;

object
{
   O

   rotate x*atan2(K.y, K.z)
   rotate z*atan2(K.x, K.y)
}


Oh, except that that won't *really* work, because it seems atan2() spits 
out a fatal parse error if the first argument is 0. (!!) Thanks. That's 
really helpful to me. [sigh] So what you *really* have to do is this:

object
{
   O

   #if (K.y != 0) rotate x*atan2(K.y, K.z) #end
   #if (K.x != 0) rotate z*atan2(K.x, K.y) #end
}

...just in case anybody else wanted to know.


Post a reply to this message

From: Orchid XP v2
Subject: Re: Simple one
Date: 11 Mar 2006 16:37:42
Message: <44134326$1@news.povray.org>
> #declare O = object {with surface normal = +y};
> #declare K = <what you want the surface normal to become>;
> 
> object
> {
>   O
> 
>   rotate x*atan2(K.y, K.z)
>   rotate z*atan2(K.x, K.y)
> }

Hang it all... that doesn't actually work at all! >_<

My brain hurts...


Post a reply to this message

From: Chris B
Subject: Re: Simple one
Date: 11 Mar 2006 18:55:28
Message: <44136370$1@news.povray.org>
"Orchid XP v2" <voi### [at] devnull> wrote in message 
news:44133910@news.povray.org...
> OK, this is going to take somebody about 3 seconds to answer I would 
> think...
>
> I have an object who's surface normal is +Y. I need to rotate it in such a 
> way that its surface normal becomes equal to a user-supplied vector. How 
> do I figure out the necessary angles?

Unless you actually need to know the angles you can reorient an object 
without knowing them by using Point_At_Trans(YAxis) or Reorient_Trans(Axis1, 
Axis2) from transforms.inc.

These both rotate the object around an axis perpendicular to the plane that 
both the initial vector and the final vector lie on.

It may be that you will need to orient the object by rotating around 
specific axes, (for example a field gun would need to first be rotated 
around a vertical axis, then around a horizontal axis) then it gets a bit 
more complicated. You'll need to start projecting your 'user-supplied' 
vector back onto a plane that is perpendicular to the first axis of 
rotation. In the field gun example above you would need to project your 
'user-supplied' axis onto the horizontal plane to obtain a vector that you 
can use with Point_At_Trans or Reorient_Trans for your first rotation. 
Projecting the vector onto the horizontal plane is easy because you just set 
the Y component of the vector to 0. If your first rotation is not around x, 
y or z, you may need to use VProject_Plane to obtain a vector for the first 
rotation.

If you really have to know the angles then you need VAngle (or VAngleD for 
working in degrees) to compute the angle between two vectors.

Regards,
Chris B.


Post a reply to this message

From: Sebastian H 
Subject: Re: Simple one
Date: 12 Mar 2006 06:24:59
Message: <4414050b$1@news.povray.org>
Orchid XP v2 wrote:
> OK, this is going to take somebody about 3 seconds to answer I would 
> think...
> 
> I have an object who's surface normal is +Y. I need to rotate it in such 
> a way that its surface normal becomes equal to a user-supplied vector. 
> How do I figure out the necessary angles?

You can rotate the +y vector around an other vector which
not neccessarily must be a basis vector (means x,y,z).

For this we need the angle between the old and the new
vector. It can be calculated with the following expression.

#declare old_vector = <0,1,0>;
#declare new_vector = <1234,1234,1234>;

#declare angle_cos = 
vdot(y,new_vector)/(vlength(old_vector)*vlength(new_vector));

#declare angle=acos(angle_cos);

Note that if old and new vector have a length of 1.0
the division by their length is not necessary in angle_cos.
This is because the dot product between two vector actually returns
vdot(v1,v2) = vlength(v1)*vlength(v2)*cos(angle_between_the_vectors)

Ok, now we have the angle. What now is needed is the axis
to rotate around. It can be determined by the following expression.

#declare rot_axis = vnormalize(vcross(old_vector, new_vector));

Which returns a vector perpendicular to both input vectors.
The vnormalize is required unless the input vectors have
a peculiar relation to each other which in general is not the case.

To rotate the old vector into the new one we now can
do this.

#declare new_vector_rotated = vaxis_rotate(old_vector, rot_axis, angle);

Now new_vector_rotated and new_vector should point into the same
direction. But new_vector_rotated will have the length of old_vector.

If an object must be rotated the macro
Axis_Rotate_Trans(rot_axis, angle) from transforms.inc can be used.

This way it is a bit harder compared to the one from Chris.
The problem with the rotation above is that it rotates
the y-vector into the correct direction but the orientation
of the x- and the z-vector after the rotation are somewhat arbitrary
(of course they're not but we did not specify them).
If you want to transform a whole basis system (e.g x,y,z) to
a new one, which would include specific x- and z-axis alignment
as well, you should consider to take a look at matrices.

Sebastian


Post a reply to this message

From: Orchid XP v2
Subject: Re: Simple one
Date: 12 Mar 2006 06:41:35
Message: <441408ef$1@news.povray.org>
>>OK, this is going to take somebody about 3 seconds to answer I would 
>>think...
>>
>>I have an object who's surface normal is +Y. I need to rotate it in such a 
>>way that its surface normal becomes equal to a user-supplied vector. How 
>>do I figure out the necessary angles?
> 
> 
> Unless you actually need to know the angles you can reorient an object 
> without knowing them by using Point_At_Trans(YAxis) or Reorient_Trans(Axis1, 
> Axis2) from transforms.inc.
> 
> These both rotate the object around an axis perpendicular to the plane that 
> both the initial vector and the final vector lie on.

Right. That should work...


Post a reply to this message

From: Orchid XP v2
Subject: Still dead
Date: 12 Mar 2006 06:54:54
Message: <44140c0e$1@news.povray.org>
Arrrrghhh!! >_<

It so *nearly* works it's driving me insane... It *almost* works, but 
it's still broken!

OK, can *anybody* figure out why the hell this doesn't work?

#include "transforms.inc"

#macro BuildPoly(Points, Faces, Radius)
   union
   {
     // Wireframe / rounded edges
     #local lp = 0;
     #while(lp < dimension_size(Faces, 1))
       #local A = Points[Faces[lp][0]];

       #local LP = 1;
       #while(LP<dimension_size(Faces, 2))
         #local B = Points[Faces[lp][LP]];

         sphere {A, Radius}
         cylinder {A, B, Radius}

         #local A = B;

         #local LP = LP + 1;
       #end

       #local A = Points[Faces[lp][0]];

       sphere {B, Radius}
       cylinder {A, B, Radius}

       #local lp = lp + 1;
     #end

     // Faces
     #local lp = 0;
     #while(lp < dimension_size(Faces, 1))
       #local A = Points[Faces[lp][0]];
       #local B = Points[Faces[lp][1]];
       #local C = Points[Faces[lp][2]];

       #local AB = B - A;
       #local AC = C - A;
       #local Axis0 = vnormalize(vcross(AB, AC));
       #local Displ = vdot(Axis0, A);

       #local Axis1 = vnormalize(AB);
       #local Axis2 = vcross(Axis1, Axis0);

       prism
       {
         linear_spline
         linear_sweep
         -Radius, +Radius, dimension_size(Faces, 2),

         #local LP = 0;
         #while(LP < dimension_size(Faces, 2))
           #local P = Points[Faces[lp][LP]];
           #local Q = <vdot(Axis1, P), vdot(Axis2, P)>;

           Q

           #local LP = LP + 1;
         #end

         translate +y*Displ

         rotate 180*y

         Point_At_Trans(Axis0)
       }

       #local lp = lp + 1;
     #end
   }
#end

#local CaseP = array[8]
{
   <-2, -1, -1>, <-1, -1, +1>, <-1, +1, -1>, <-1, +1, +1>,
   <+1, -1, -1>, <+1, -1, +1>, <+1, +1, -1>, <+1, +1, +1>
}

#local CaseF = array[6][4]
{
   {0, 1, 3, 2},
   {0, 4, 5, 1},
   {0, 4, 6, 2},
   {7, 6, 4, 5},
   {7, 3, 2, 6},
   {7, 3, 1, 5}
}

object
{
   BuildPoly(CaseP, CaseF, 0.05)
   rotate -40*y
   texture {pigment {colour red 1}}
}

camera
{
   location <0, +3, -3>
   look_at 0
}

light_source {<0, +3, -3>, colour rgb 1}


Post a reply to this message

From: Chris B
Subject: Re: Still dead
Date: 12 Mar 2006 12:30:01
Message: <44145a99@news.povray.org>
"Orchid XP v2" <voi### [at] devnull> wrote in message 
news:44140c0e$1@news.povray.org...
> Arrrrghhh!! >_<
>
> It so *nearly* works it's driving me insane... It *almost* works, but it's 
> still broken!
>

Hi again,
Define 'works'. ;-)

You are passing a set of points and a set of references to those points to 
your routine (Similar to the way VRML defines shapes - maybe a coincidence).

Can I assume you were intending to get a closed 3D shape out of this?
If I understand your SDL and your intentions correctly you are happy with 
the edges, but you are not happy with the left-most surface when you set the 
first point to <-2,-1,-1>, because 3 of the points of the surface touch the 
corner points of the shape, but the fourth point (in this case the point 
with index 2, which is the 3rd one in your list) doesn't.

For each face, your SDL uses 2D components of 4 points to generate a flat 
prism object that lies parallel to the XZ plane, then you re-orient it based 
upon vectors defined using only the first 3 of the 4 points. Because the 
fourth point 3D that you pass into the routine doesn't lie on the same plane 
as the first 3 3D points you pass into the routine, your surface ends up 
sticking up in the air and doesn't stand a chance of touching the fourth 
point.

To move forward you will need to decide what sort of shape you would expect 
to generate for 4 points that don't lie in the same plane and generate that 
shape instead of the prism object (maybe a mesh or mesh2 object). Otherwise 
you may just wish to adjust your points so that each set of 4 points lies on 
a plane.

Regards,
Chris B.


Post a reply to this message

From: Orchid XP v2
Subject: Re: Still dead
Date: 13 Mar 2006 15:15:59
Message: <4415d2ff$1@news.povray.org>
> For each face, your SDL uses 2D components of 4 points to generate a flat 
> prism object that lies parallel to the XZ plane, then you re-orient it based 
> upon vectors defined using only the first 3 of the 4 points. Because the 
> fourth point 3D that you pass into the routine doesn't lie on the same plane 
> as the first 3 3D points you pass into the routine, your surface ends up 
> sticking up in the air and doesn't stand a chance of touching the fourth 
> point.

*slaps head repeatedly*

Duh!

Of *course* it's not gonna work with a non-plannar surface...! >_<

God, sometimes I think I should just go crawl into a hole somewhere...

OK, now let's see what happens if I feed it some coordinates which 
actually describe a feasible polyhedron...


Post a reply to this message

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