POV-Ray : Newsgroups : moray.win : Local coordinates? : Re: Local coordinates? Server Time
5 Jul 2024 06:45:34 EDT (-0400)
  Re: Local coordinates?  
From: Tor Olav Kristensen
Date: 6 Dec 2001 18:59:39
Message: <3C1003DE.BE8FBDCE@hotmail.com>
"Timothy R. Cook" wrote:
> 
> Is there a way to rotate an object around its local coordinate
> axes?  What I have is this:
> 
> Box
> scale  [ 34.000  10.000  60.000]
> rotate [  5.000 -53.975   0.000]
> transl [-44.000  21.000  -8.000]
>   local coords
> scale  [  1.000   1.000   1.000]
> rotate [  0.000   0.000   0.000]
> transl [ -1.000   1.000   0.000]
> 
> I am trying to make it intersect points
>      A [-32.000   0.000  76.000]
>      B [-88.000  16.000 -40.000]
>      C [  0.000  26.000  24.000]
> to difference it from an object.  I have it rotated to where
> I want it XY, but when I try rotating it around its Z axis,
> it rotates around the WORLD axis, not its own, and the local
> coordinate rotation just shears the box at whatever angle,
> not at all what I want.
> 
> So, what do I do to get the effect I want?  If I need to
> rotate it on the real-world axes, what formulas do I use
> to figure out all 3 angles at the same time?


I saw this post at the news web-pages at the POV-
Ray server (messages digest) and then made a
script file in order to try to solve your problem.

Unfortunately I realized too late that this was a
moray-related question. =(

But I'll post the code anyway in case anyone is
interested.


Tor Olav


// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Copyright 2001 by Tor Olav Kristensen
// Email: tor### [at] hotmailcom
// http://www.crosswinds.net/~tok
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

#version 3.5;

#include "colors.inc"

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// The camera equipment

camera {
  location <-50, -10, 300>
  look_at <0, 0, 0>
}

light_source {
  <-1, -1, 1>*1000
  color White
  shadowless
}

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Some useful macros

#macro AxisRotateMatrix(vAxis, Angle)

  #local Phi = radians(Angle);
  #local Cos = cos(Phi);
  #local Sin = sin(Phi);
  #local vL = vnormalize(vAxis);
  #local vM = vL*(1 - Cos);

  matrix <
    vM.x*vL.x +      Cos, vM.y*vL.x + vL.z*Sin, vM.z*vL.x - vL.y*Sin,
    vM.x*vL.y - vL.z*Sin, vM.y*vL.y +      Cos, vM.z*vL.y + vL.x*Sin,
    vM.x*vL.z + vL.y*Sin, vM.y*vL.z - vL.x*Sin, vM.z*vL.z +      Cos,
                       0,                    0,                    0
  >

#end // macro AxisRotateMatrix


#macro ReorientMatrix(vAxis1, vAxis2)

  #local v1 = vnormalize(vAxis1);
  #local v2 = vnormalize(vAxis2);
  #local vU = vcross(v1, v2);
  #local Dot = vdot(v1, v2);
  #local v0 = vnormalize(vU);
  #local vW = (1 - Dot)*v0;
  #local vA = v0.x*vW;
  #local vB = v0.y*vW;
  #local vC = v0.z*vW;

  matrix <
    vA.x + Dot,  vA.y + vU.z, vA.z - vU.y,
    vB.x - vU.z, vB.y + Dot,  vB.z + vU.x,
    vC.x + vU.y, vC.y - vU.x, vC.z + Dot,
    0,                0,                0
  >

#end // macro ReorientMatrix


#macro vTransform(v0, Transform)

  #local Fn = function { transform { Transform } }

  Fn(v0.x, v0.y, v0.z)

#end // macro vTransform

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Now work with the problem (as I understood it)

// Deifne a box
#declare InitialBox = box { -<2, 0.1, 1.5>, <2, 0.1, 1.5> }

// And it's centre
#local pCtr = <0, 0, 0>;

// Decide how to transform it in world coordinates
#declare WorldTrans =
transform {
  scale  <34.000, 10.000, 60.000>
  rotate <5.000, -53.975, 0.000>
  translate <-44.000,  21.000,  -8.000>
}

// DoItToIt
#declare OnceTransformedBox =
object {
  InitialBox
  transform { WorldTrans }
}

// Decide how to transform it locally
#declare LocalTrans =
transform {
  scale  <1, 1, 1>
  rotate <0, 0, 0>
  translate <-1, 1, 0>
}

// DoItToIt
#declare TwiceTransformedBox =
object {
  OnceTransformedBox
  transform { WorldTrans inverse }
  transform { LocalTrans }
  transform { WorldTrans }
}

// Uncomment to see it now:
//object { TwiceTransformedBox pigment { color White } }

// Calculate the complete transformation it has gone through
// until now:
#declare TotalTrans = transform { LocalTrans WorldTrans }

// Find it's new centre and which direction it's y-axis is pointing:
#declare pNewCtr =
vTransform(pCtr, transform { TotalTrans });

#declare vNewY =
vTransform(pCtr + y, transform { TotalTrans }) - pNewCtr;

// Now that we know it's new centre and y-axis we can forget all
// about the transformations it has gone through up til now.

// The next task is to make the transformed box "intersect" with
// these three points:

#declare pA = <-32,  76,  0>;
#declare pB = <-88, -40, 16>;
#declare pC = <  0,  24, 26>;

// Show the points
sphere { pA, 5 pigment { color Cyan*2 } }
sphere { pB, 5 pigment { color Magenta*2 } }
sphere { pC, 5 pigment { color Yellow*2 } }

// Find two non paralell vectors for the plane they lie within:
#declare vCA = pA - pC;
#declare vCB = pB - pC;

// Note that although vCA and vCB seems to be perpendicular,
// they are not. I.e.: vdot(vCA, vCB) != 0

// And a normal vector for that plane:
#declare vUp = vcross(vCA, vCB);

// Also find a point that lies in the middle of these
// three points:
#declare pMid = (pA + pB + pC)/3;


// Then calculate the complete transform needed to make the box
// "intersect" with the three spheres:
#declare IsecPtsTrans =
transform {
  translate -pNewCtr
  ReorientMatrix(vNewY, vUp)
//  AxisRotateMatrix(vUp, 45)
  translate pMid  
}
// If the box is to be rotated within the plane that the three
// spheres lie in, then uncomment the line above. 


// Transform it to it's final position and show it:
object {
  TwiceTransformedBox
  transform { IsecPtsTrans }
  pigment { color Yellow }
}
 
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

/*
// Uncomment this region if you want to see the new local axes
// for the box in its final state.

// Finding its new (now old) x and z axes in the same way as we
// found the y axis above:

#declare vNewX =
vTransform(pCtr + x, transform { TotalTrans }) - pNewCtr;

#declare vNewZ =
vTransform(pCtr + z, transform { TotalTrans }) - pNewCtr;

// Calculate were its final centre is:
#declare pFinalCtr =
vTransform(pNewCtr, transform { IsecPtsTrans });

// And the direction of its final local x, y, z axes:
#declare vFinalX =
vTransform(pNewCtr + vNewX, transform { IsecPtsTrans }) - pFinalCtr;

#declare vFinalY =
vTransform(pNewCtr + vNewY, transform { IsecPtsTrans }) - pFinalCtr;

#declare vFinalZ =
vTransform(pNewCtr + vNewZ, transform { IsecPtsTrans }) - pFinalCtr;

// Maybe we want to specify a length for the axes ?
//#declare vFinalX = 60*vnormalize(vFinalX);
//#declare vFinalY = 60*vnormalize(vFinalY);
//#declare vFinalZ = 60*vnormalize(vFinalZ);


// A simple macro to show an axis

#macro Axis(v0, pCenter, Radius, Colour)

  union {
    sphere { -v0, Radius }
    cylinder { -v0, v0, Radius }
    sphere {  v0, Radius }
    translate pCenter
    pigment { color Colour }
  }

#end // macro Axis

// Show them
Axis(vFinalX, pFinalCtr, 2, Red)
Axis(vFinalY, pFinalCtr, 2, Green)
Axis(vFinalZ, pFinalCtr, 2, Blue)
*/

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

// If we hadn't done all the world and local transformations to
// the box, then these few lines of code would have done something
// similar to it as the code above. (One of the sides of the box
// would even be aligned with two of the spheres.)


#declare vPlY = vnormalize(vUp);
#declare vPlZ = vnormalize(vcross(vCB, vPlY));
#declare vPlX = vcross(vPlY, vPlZ);

#declare OneSingleTrans =
transform {
  matrix <
    vPlX.x, vPlX.y, vPlX.z,
    vPlY.x, vPlY.y, vPlY.z,
    vPlZ.x, vPlZ.y, vPlZ.z,
         0,      0,      0
  >
}


// Uncomment to see the effect:
/*
object {
  InitialBox // box { -<2, 0.1, 1.5>, <2, 0.1, 1.5> }
  scale <34, 10, 60> // It's very small so scale it
  transform OneSingleTrans
//  AxisRotateMatrix(vPlY, 45)
  translate pMid
  pigment { color Orange + White }
}
*/


// Also have a look at this:
// (Lines up the edges along the spheres.)
/*
object {
  InitialBox // box { -<2, 0.1, 1.5>, <2, 0.1, 1.5> }
  scale <34, 10, 60>
  transform OneSingleTrans
  translate pC + 2*34*vPlX + 0.1*10*vPlY + 1.5*60*vPlZ
  pigment { color Orange + Yellow }
}
*/


// And this:
// (Same result as from the one above.)
/*
object {
  box { <0, 0, 0>, 2*<2, 0.1, 1.5> }
  scale <34, 10, 60>
  transform OneSingleTrans
  translate pC
  pigment { color Orange + Red }
}
*/

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

/*
// Finally:
// If vCA and vCB had been perpendicular to each other, this
// would have been a quite nice solution to the problem:
// (The box made from the code below is a little bit skewed.)

#declare vPlZ = vCA;
#declare vPlX = vCB;
#declare vPlY = 4*vnormalize(vcross(vCA, vCB));

object {
  box { <0, 0, 0>, <1, 1, 1> }
  matrix <
    vPlX.x, vPlX.y, vPlX.z,
    vPlY.x, vPlY.y, vPlY.z,
    vPlZ.x, vPlZ.y, vPlZ.z,
      pC.x,   pC.y,   pC.z
  >
  pigment { color Grey }
}
*/

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


Post a reply to this message

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