|
|
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
|
|