POV-Ray : Newsgroups : povray.text.scene-files : "Twisted Lathe" Source Code Server Time
23 Dec 2024 22:08:11 EST (-0500)
  "Twisted Lathe" Source Code (Message 1 to 3 of 3)  
From: Tor Olav Kristensen
Subject: "Twisted Lathe" Source Code
Date: 12 Jun 2000 10:26:48
Message: <3944F334.E80285DD@hotmail.com>
Below is the source code for an image I posted 4. June to the
povray.binaries.images news group.

The last macros may be a little non intuitive to use and I'm
working on them to make them easier to use.

Note that many of the macros below are "work in progress" and 
therefore I haven't yet optimized them for speed or compactness.

Tor Olav


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

#version 3.1;
#include "colors.inc"

global_settings { ambient_light 1.2 }

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// First some "standard" geometry macros

// Returns projection of vector in direction of other vector
#macro vproject(UU, VV)

  (VV*vdot(UU, VV)/vdot(VV, VV))

#end // macro vproject


// Point To Plane
// Returns projection of point to plane
#macro pt2pl(pPoint, pPlane, vPlane)

  (pPoint - vproject(pPoint - pPlane, vPlane))

#end // macro pt2pl


// Point To Line
// Returns projection of point to line
#macro pt2ln(pPoint, pLine, vLine) 

  (pLine + vproject(pPoint - pLine, vLine))

#end // macro pt2ln


// Line To Plane
// Returns intersection of line and plane
#macro ln2pl(pLine, vLine, pPlane, vPlane)

  (pLine + vLine*vdot(pPlane - pLine, vPlane)/vdot(vLine, vPlane))

#end // macro ln2pl


// Plane To Plane
// Calculates line in intersection of two planes
#macro pl2pl(pPlane1, vPlane1, pPlane2, vPlane2, pLine, vLine)

  #declare vLine = vcross(vPlane1, vPlane2);
  #local vInPlane2 = vcross(vLine, vPlane2);
  #declare pLine = ln2pl(pPlane2, vInPlane2, pPlane1, vPlane1);

#end // macro pl2pl


// Returns object tilted in direction of vector
#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

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Some macros to generate lathes from arrays of 2D-points

#macro InsertPoints(PointArray)

  #local NrOfPoints = dimension_size(PointArray, 1);
  #local PtCnt = 0;

  #while (PtCnt < NrOfPoints)
    PointArray[PtCnt],
    #local PtCnt = PtCnt + 1;
  #end // while

#end // macro InsertPoints 


#macro LinearLathe(PointArray)

  lathe {
    linear_spline
    dimension_size(PointArray, 1) + 1,
    InsertPoints(PointArray)
    PointArray[0]
  }

#end // macro LinearLathe


#macro QuadraticLathe(PointArray)

  lathe {
    quadratic_spline
    dimension_size(PointArray, 1) + 2,
    InsertPoints(PointArray)
    PointArray[0],
    PointArray[1]
  }

#end // macro QuadraticLathe


#macro CubicLathe(PointArray)

  lathe {
    cubic_spline
    dimension_size(PointArray, 1) + 3,
    InsertPoints(PointArray)
    PointArray[0],
    PointArray[1],
    PointArray[2]
  }

#end // macro CubicLathe 

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// A macro to generate array of 2D-points that can be used 
// to make torus-like lathes where the minor radius varies
// according to a "wave function", which is declared later.

#macro CalcLatheTorus(PointArray, Angle, 
                      MajorRadius, MinorRadius, ModRadius)

  #local NrOfPts = dimension_size(PointArray, 1);
  #local dPhi = 2*pi/NrOfPts;
  #local PtCnt = 0;
  #while (PtCnt < NrOfPts)
    #local Phi = PtCnt*dPhi;
    #local WaveRadius =  ModRadius*WaveFunction(Phi);
    #declare PointArray[PtCnt] = MajorRadius*u + 
                                 (MinorRadius + WaveRadius)*
                                 <cos(Angle), sin(Angle)>;
    #local PtCnt = PtCnt + 1;
    #local Angle = Angle + dPhi;
  #end

#end // macro CalcLatheTorus 

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// And then the macros that generates all the 
// different lathe segments and assembles them.

#macro v2Dir(v2D, vBasis1, vBasis2)

  (v2D.u*vnormalize(vBasis1) + v2D.v*vnormalize(vBasis2))

#end // macro v2Dir


#macro New3DCoord(LatheArray, PointArray, pRef, vSd, vFw)

  #local NrOfPts = dimension_size(PointArray, 1);

  #local Cnt = 0;
  #while (Cnt < NrOfPts)
    #declare PointArray[Cnt] = pRef + v2Dir(LatheArray[Cnt], vSd, vFw);
    #local Cnt = Cnt + 1;
  #end // while

#end // macro NewCoord


#macro Lathe2DCoord(pSwp, pLine, vLine)
  
  #local pHit = pt2ln(pSwp, pLine, vLine);
  #local vForw = pHit - pLine;
  #local vSide = pSwp - pHit;
  #local Sign = (vdot(vForw, vLine) < 0 ? -1 : 1);

  <vlength(vSide), Sign*vlength(vForw)>

#end // macro Lathe2DCoord


#macro ShiftLathe(LatheType, PointArray, pRef, 
                  pPlane1, vPlane1, 
                  pPlane2, vPlane2)

  #local pLine = <0, 0, 0>;
  #local vLine = <0, 0, 0>;
  pl2pl(pPlane1, vPlane1, pPlane2, vPlane2, pLine, vLine)
  #declare pRef = pt2ln(pRef, pLine, vLine);
  #local vFw = vnormalize(vLine);
  #local vSd = vnormalize(vcross(vPlane2, vFw));
  #local NrOfPts = dimension_size(PointArray, 1);
  #local LatheArray = array[NrOfPts]
  #local Cnt = 0;
  #while (Cnt < NrOfPts)
    #local LatheArray[Cnt] = Lathe2DCoord(PointArray[Cnt], pRef, vFw);
    #declare PointArray[Cnt] = pRef + v2Dir(LatheArray[Cnt], vSd, vFw);
    #local Cnt = Cnt + 1;
  #end // while
  New3DCoord(LatheArray, PointArray, pRef, vSd, vFw)

  #switch (LatheType)
    #case (1)
      #local Lathe = LinearLathe(LatheArray)
      #break
    #case (2)
      #local Lathe = QuadraticLathe(LatheArray)
      #break
    #case (3)
      #local Lathe = CubicLathe(LatheArray)
      #break
    #else
      #debug "Macro ShiftLathe: Wrong lathe type"
  #end

  intersection {
    Tilt(Lathe, vFw)
    plane { -vPlane1, 0 } // Look here to learn how to select "signs"
    plane {  vPlane2, 0 } // for the plane normals in the plane array.
    translate pRef
  }

#end // macro ShiftLathe


#macro LatheSway(LatheArray, pRef, PlaneArray, LatheType)

  #local PointArray = array [dimension_size(LatheArray, 1)]
  #local vFw = vnormalize(vcross(PlArray[0][1], PlArray[1][1]));
  #local vSd = vnormalize(vcross(vFw, PlArray[0][1]));
  New3DCoord(LatheArray, PointArray, pRef, vSd, vFw)

  merge {
    #declare PlCnt = 1;
    #while (PlCnt < dimension_size(PlArray, 1))
      ShiftLathe(LatheType, PointArray, pRef, 
                 PlArray[PlCnt - 1][0], PlArray[PlCnt - 1][1],
                 PlArray[PlCnt - 0][0], PlArray[PlCnt - 0][1])
      #declare PlCnt = PlCnt + 1;
    #end // while
  }
  
#end // macro LatheSway

// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
// Now have fun.
 
#macro WaveFunction(Phi)

  (2/3*cos(4*Phi) - 1/3*sin(6*Phi - pi/2))

#end // macro WaveFunction


#declare LathePoints = array[96]
CalcLatheTorus(LathePoints, pi/2, 12, 2, 8)


/*
#macro WaveFunction(Phi)

  cos(6*Phi)

#end // macro WaveFunction


#declare LathePoints = array[72]
CalcLatheTorus(LathePoints, pi/12, 10, 6, 1)
*/


// The planes below:
// plane { PlArray[n][1], 0 translate PlArray[n][0] }
//
// Note: Changing the "sign" of each normal vector
//       gives different CSG-results
#declare PlArray =
array[6][2] {
  { < 20,  0,   0>, <-2,  1,  0> },
  { <  0,  0, -10>, < 0,  1,  1> },
  { <-20,  0,   0>, <-2, -1,  0> },
  { <  0, 20,   0>, < 0,  1,  0> },
  { <  0, 24,   0>, < 0,  1, -3> },
  { <  0, 40,   0>, < 0,  1,  0> }
}


// Just a quick and dirty way to select a
// first reference point in the first plane
#declare pFirstRef = pt2pl(<2, 2, 2>, PlArray[0][0], PlArray[0][1]);
// Could also have written
//#declare pFirstRef = <17.2, -5.6, 2.0>;


#declare Sway = LatheSway(LathePoints, pFirstRef, PlArray, 3)


// Then use symmetry to cheat a little bit
union {
  object {
    Sway
    translate -40*y
  }
  object {
    Sway
    translate -40*y
    scale <1, -1, 1>
  }
  rotate 90*x
  pigment { color Red }
}


// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7
/*
// A much simpler lathe shape in the XZ-plane
// Use other camera position to view

#macro WaveFunction(Phi)

  0

#end // macro WaveFunction


#declare LathePoints = array[5]
CalcLatheTorus(LathePoints, pi/10, 24, 6, 0)


// Example of manually entered array of 2D-points for lathe:
//#declare LathePoints = 
//array[4] {
//  <24, 0> + 4*<1, 0>,
//  <24, 0> + 4*<0, 1>,
//  <24, 0> - 4*<1, 0>,
//  <24, 0> - 4*<0, 1>
//}


#declare PlArray =
array[9][2] {
  {  20*x,  x },
  {  20*z,  z },
  {  20*x, -x },
  {  20*z, -z },
  { -20*x, -x },
  { -20*z, -z },
  { -20*x,  x },
  { -20*z,  z },
  {  20*x,  x }
}


#declare pFirstRef = 18*(x + z);

#declare SimpleSway = LatheSway(LathePoints, pFirstRef, PlArray, 2)

object {
  SimpleSway
//  rotate 45*y
  translate 20*y
  pigment { color Cyan }
}
*/
// ===== 1 ======= 2 ======= 3 ======= 4 ======= 5 ======= 6 ======= 7

sky_sphere { pigment { color Grey } }

#declare AreaLight =
light_source { 
  100*y, 
  color White
  area_light 10*x, 10*z, 3, 3
  jitter
}

Tilt(AreaLight, <-1, sqrt(2), 1>)
Tilt(AreaLight, -y)

#declare CameraPos = 60*<-2, 0.4, 0.6>;
//#declare CameraPos = 60*<-2, 1, 0.6>;
//#declare CameraPos = 70*<0, 2, -1/100>;

//light_source { CameraPos color 0.7*White  } 

camera {
  location CameraPos
  look_at <0, -10, 0>
}

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


Post a reply to this message

From: Christoph Hormann
Subject: Re: "Twisted Lathe" Source Code
Date: 12 Jun 2000 12:35:58
Message: <3945116E.181BD6AE@gmx.de>
Wow! that's much math :-) great work indeed!

Needs some time to look through your code, but it seems very usable. 
Some practical explanations for usage would be nice of course, but as
you said, it is work in progress.  

I'm curious how it looks like with some uv-mapped textures...

Christoph

Tor Olav Kristensen wrote:
> 
> Below is the source code for an image I posted 4. June to the
> povray.binaries.images news group.
> 
> The last macros may be a little non intuitive to use and I'm
> working on them to make them easier to use.
> 
> Note that many of the macros below are "work in progress" and
> therefore I haven't yet optimized them for speed or compactness.
> 
> Tor Olav

[...]

--
Christoph Hormann <chr### [at] gmxde>
Homepage: http://www.schunter.etc.tu-bs.de/~chris/


Post a reply to this message

From: Tor Olav Kristensen
Subject: Re: "Twisted Lathe" Source Code
Date: 13 Jun 2000 16:14:19
Message: <394695BC.51145FD2@online.no>
Christoph Hormann wrote:

> Wow! that's much math :-) great work indeed!

Thank you.


> Needs some time to look through your code, but it seems very usable.
> Some practical explanations for usage would be nice of course, but as
> you said, it is work in progress.

I have included another simpler "twisted lathe" within the code.
If one un-comments it and draws the planes for this in 2D (XZ-plane)
on a piece of paper (with arrows for the normals), one might get a clue
on how to select the planes.

I'll be off-line and away from POV-Ray for some days now :(
so I'm not able to make examples and write explanations on how to
use my code. Sorry.

My employer sends me away to work on a new project for a while.
But I'll see if I can find time to explain more when I return.


> I'm curious how it looks like with some uv-mapped textures...

Please show me if you find out !
(I do not know how uv-mapped textures looks like.)


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


Post a reply to this message

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