// Persistence of Vision Ray Tracer Scene Description File // File: Bezier.inc // Vers: 3.1 // Desc: Bezier Spline Macro Include File // Date: 11-11-99 First made into .inc file // 11-15-99 Started the smooth triangle connection bewtween two splines // 11-15-99 Started the Radius Change feature // 11-17-99 Managed to fix problems with ConnectSmooth, so all the // Triangles should show up now // 12-28-99 Made DrawStrand Macro // 01-17-00 Made ConnectStrandToSpline Macro // 01-19-00 Deleted ConnectStrandToSpline Macro due to memory issues // 02-11-00 Added MoveSpline, ReverseSpline, RotateSpline, and ScaleSpline // Auth: Josh English #declare HelloBezier = true; // Set Defaults #declare ShowTangents = false; #declare FullCurve = true; #declare NumberofPoints = 20; #declare AccelerationDegree = 1; #declare BezTex = texture { pigment { red 1 } finish { phong 1 } } #declare BezRad = 0.1; #declare BezThing = sphere { <0,0,0> BezRad texture { BezTex } } #declare NoShadow = true; #declare CapSpline = false; // Autopoint takes a point and it's contol, and creates a new control point // in the opposite direction, the lenght is scaled by a factor of d #macro Autopoint(a,b,d) #local newpoint = a - d*(b - a); newpoint; #end // Square creates two triangles that connect four points #macro Square(A,B,C,D) union { triangle { A, B, C } triangle { D, C, A } texture { BezTex } } #end // CheckDefaults will fill out anything not specified by the user #macro CheckDefaults() #ifndef (ShowTangents) #declare ShowTangents = false; #end #ifndef (FullCurve) #declare FullCurve = false; #end #ifndef (NumberofPoints) #declare NumberofPoints = 20; #end #ifndef (AccelerationDegree) #declare AccelerationDegree = 1; #end #ifndef (BezTex) #declare BezTex = texture { pigment { red 1 } finish { phong 1 } } #end #ifndef (BezRad) #declare BezRad = 0.1; #end #ifndef (BezThing) #declare BezThing = sphere { <0,0,0> BezRad texture { BezTex } } #end #ifndef (NoShadow) #declare NoShadow = true; #end #end // Also need a method of taking a spline and a normalized number and return // a place on the spline #macro ReturnPosition(id,num) // CheckDefaults() #local d = pow(num,AccelerationDegree); #local m = 1 - d; #local this = id[0]*pow(m,3) + id[1]*d*3*pow(m,2) + id[2]*3*pow(d,2)*m + id[3]*pow(d,3); this #end // DrawSpline takes an array identifier and #macro DrawSpline(id) #declare BezThing = sphere { <0,0,0> BezRad texture { BezTex } } #local c = 0; #while ( c < 1 ) #local temp = ReturnPosition(id,c); // Find the Next Point on the spline #local next = ReturnPosition(id,(c+1/NumberofPoints)); #if (FullCurve) #if ( c < 1 ) cylinder { temp, next BezRad texture { BezTex } #if(NoShadow) no_shadow #end } #end #end // Find the proper transformation for the thing #local nx = vnormalize(next - temp); #local nz = vnormalize(vcross(nx,y)); #local ny = vcross(nz,nx); #local nz = vnormalize(vcross(nx,ny)); object{ BezThing #if(NoShadow) no_shadow #end matrix texture { BezTex }} #declare c = c + (1/NumberofPoints); #end #if (ShowTangents) cylinder { id[0],id[1] BezRad*0.75 pigment { rgb 1 } no_shadow} cylinder { id[2],id[3] BezRad*0.75 pigment { rgb 1 } no_shadow} #end #if (CapSpline) object { BezThing texture { BezTex } translate id[3] } #end #end // DrawPartialSpline takes an array identifier and #macro DrawPartialSpline(id,lim) CheckDefaults() #local c = 0; #while ( c < lim ) #local temp = ReturnPosition(id,c); // Find the Next Point on the spline #local next = ReturnPosition(id,(c+1/NumberofPoints)); #if (FullCurve) #if ( c < 1 ) cylinder { temp, next BezRad texture { BezTex } #if(NoShadow) no_shadow #end } #end #end // Find the proper transformation for the thing // Thing should be oriented towards +x #local nx = vnormalize(next - temp); #local nz = vnormalize(vcross(nx,y)); #local ny = vcross(nz,nx); #local nz = vnormalize(vcross(nx,ny)); object{ BezThing #if(NoShadow) no_shadow #end matrix } #declare c = c + (1/NumberofPoints); #end #if (ShowTangents) cylinder { id[0],id[1] BezRad*0.75 pigment { rgb 1 } no_shadow} cylinder { id[2],id[3] BezRad*0.75 pigment { rgb 1 } no_shadow} #end #end // SplineLength returns a rough estimate of the length of the spline #macro SplineLength(id) #local c = 0; #declare len = 0; #while ( c < 1 ) #local temp = ReturnPosition(id,c); #local next = ReturnPosition(id,(c + 0.05)); #declare len = len + vlength(next-temp); #declare c = c + 0.05; #end len #end // BridgeSpline takes an array identifier and #macro BridgeSplines(id1,id2) CheckDefaults() #local c = 0; #while ( c < 1 ) #local t1 = ReturnPosition(id1,c); #local t2 = ReturnPosition(id2,c); // Find the Next Point on the spline #local n1 = ReturnPosition(id1,(c+1/NumberofPoints)); #local n2 = ReturnPosition(id2,(c+1/NumberofPoints)); #if (FullCurve) #if ( (c+1/NumberofPoints) < 1 ) cylinder { t1, n1 BezRad texture { BezTex } #if(NoShadow) no_shadow #end } cylinder { t2, n2 BezRad texture { BezTex } #if(NoShadow) no_shadow #end } #end #end // Find the proper transformation for the thing #local nx = vnormalize(next - temp); #local nz = vnormalize(vcross(nx,y)); #local ny = vcross(nz,nx); object{ BezThing #if(NoShadow) no_shadow #end matrix } cylinder ( t1,t2 BezRad*0.75 texture { BezTex ) no_shadow } #declare c = c + (1/NumberofPoints); #end #if (ShowTangents) cylinder { id[0],id[1] BezRad pigment { rgb 1 } no_shadow} cylinder { id[2],id[3] BezRad pigment { rgb 1 } no_shadow} #end #end #macro Connect(SP,SR,EP,ER) #local D=vlength(EP-SP); #local Rd=SR-ER; #local D2=sqrt(abs(D*D-Rd*Rd)); cone { SP+(EP-SP)/D*Rd*(SR)/D,(SR)*D2/D,EP+(EP-SP)/D*Rd*(ER)/D,(ER)*D2/D } #end // DrawTail deals with a start radius and an end radius #macro DrawTail(id) CheckDefaults() #ifndef (StartRadius) #declare StartRadius = 1; #end #ifndef (EndRadius) #declare EndRadius = 0.1; #end #local c = 0; #while ( c < 1 ) #local temp = ReturnPosition(id,c); #local t_rad = StartRadius + (c * (EndRadius - StartRadius)); // Find the Next Point on the spline #local next = ReturnPosition(id,(c+1/NumberofPoints)); #local n_rad = StartRadius + ((c+1/NumberofPoints) * (EndRadius - StartRadius)); #if (FullCurve) #if ( (c+1/NumberofPoints) < 1 ) object { Connect(temp,t_rad,next,n_rad) texture { BezTex } } #end #end // Find the proper transformation for the thing #local nx = vnormalize(next - temp); #local nz = vnormalize(vcross(nx,y)); #local ny = vcross(nz,nx); sphere { 0,1 scale t_rad texture { BezTex } matrix } #declare c = c + (1/NumberofPoints); #end #if (ShowTangents) cylinder { id[0],id[1] BezRad pigment { rgb 1 } no_shadow} cylinder { id[2],id[3] BezRad pigment { rgb 1 } no_shadow} #end #end // Need a way to automatically crate a new spline from an old one with // a smooth connection // new[0] = old[3] // new[1] = autopoint(old[3],old[2],1) // new[2] and new[3] are customizable // Method for connecting two splines with triangles, kind of a bicubic patch // Thing without the control points #macro ConnectSplines(id1,id2) CheckDefaults() mesh { #local c = 0; #while ( c < 1 ) #local p1 = ReturnPosition(id1,c); #local p2 = ReturnPosition(id1,(c+1/NumberofPoints)); #local p3 = ReturnPosition(id2,c); #local p4 = ReturnPosition(id2,(c+1/NumberofPoints)); //Square (p1,p2,p4,p3) triangle { p1,p2,p3 } triangle { p2,p4,p3 } #declare c = c + (1/NumberofPoints); #end texture { BezTex } } // end mesh #end //#include "MyMacs.inc" #macro ConnectSmooth(id1,id2) CheckDefaults() mesh { #local c = 0; #while (c < 1) // Get Positions for First Spline #local ac = ReturnPosition(id1,c); #local an = ReturnPosition(id1,(c+(1/NumberofPoints))); #local aq = ReturnPosition(id1,(c+(2/NumberofPoints))); #local ap = ReturnPosition(id1,(c-(1/NumberofPoints))); // Get Position for Second Spline #local bc = ReturnPosition(id2,c); #local bn = ReturnPosition(id2,(c+(1/NumberofPoints))); #local bq = ReturnPosition(id2,(c+(2/NumberofPoints))); #local bp = ReturnPosition(id2,(c-(1/NumberofPoints))); // Find six normals #declare n1 = vnormalize(vcross((bc-bp),(ap-bp))); #declare n2 = vnormalize(vcross((bn-bc),(ac-bc))); #declare n3 = vnormalize(vcross((ac-an),(bn-an))); #declare n4 = vnormalize(vcross((ac-an),(bn-an))); #declare n5 = vnormalize(vcross((bq-bn),(an-bn))); #declare n6 = vnormalize(vcross((an-aq),(bq-aq))); // Now find the four local normals that are the average of three // triangle normals each #declare acn = vnormalize((n2 + n3 + n4)/3); #declare ann = vnormalize((n4 + n5 + n6)/3); #declare bcn = vnormalize((n1 + n2 + n3)/3); #declare bnn = vnormalize((n3 + n4 + n5)/3); // Draw the two smooth triangles smooth_triangle { ac acn bc bcn bn bnn } smooth_triangle { ac acn an ann bn bnn } #declare c = c + (1/NumberofPoints); #end texture { BezTex } } #end #macro CheckStrandDefaults() #ifndef (NumberCorrection) #declare NumberCorrection = 2; #end #ifndef (NoRotations) #declare NoRotations = 1; #end #ifndef (OutRadius) #declare OutRadius = 0.5; #end #ifndef (RotationOffset) #declare RotationOffset = 0; #end #ifndef (RadMin) #declare RadMin = 0; #end #ifndef (RadMax) #declare RadMax = 1; #end #ifndef (RadialMethod) #declare RadialMethod = 0; #end #end // Drawstrand #macro DrawStrand(id) CheckDefaults() CheckStrandDefaults() #declare NumberofPoints = int(NumberofPoints * NumberCorrection); #local c = 0; #while ( c < 1 ) #local c1 = c + 1/NumberofPoints; // Find the Current Point and the Next Point #local temp = ReturnPosition(id,c); #local next = ReturnPosition(id,c1); // Find the rotation around the spline of the current and next points #local currentRotation = (360*c*NoRotations) + RotationOffset; #local nextRotation = (360*c1*NoRotations) + RotationOffset; // Find the current radius and next radius based on the Method #switch(RadialMethod) #case(1) // Linear Method #local RadRange = RadMax - RadMin; #local currentRadius = RadMin + (c*RadRange); #local nextRadius = RadMin + (c1*RadRange); #break; #case(2) // Sine Method #local RadRange = RadMax - RadMin; #local currentRadius = ( sin(c * pi)*RadRange) + RadMin; #local nextRadius = ( sin(c1 * pi)*RadRange) + RadMin; #break; #else // constant method #local currentRadius = OutRadius; #local nextRadius = OutRadius; #end #local FirstPos = vrotate(<0,0,currentRadius>,); #local SecondPos = vrotate(,); // Find the proper transformation for the thing #local nx = vnormalize(next - temp); #local nz = vnormalize(vcross(nx,y)); #local ny = vcross(nz,nx); object{ merge { sphere { FirstPos, BezRad } cylinder { FirstPos, SecondPos, BezRad } texture { BezTex } } #if(NoShadow) no_shadow #end matrix } #declare c = c1; #end #end // Added 2-11-2000 #macro MoveSpline(Spl,vct) array [4] { Spl[0] + vct, Spl[1] + vct, Spl[2] + vct, Spl[3] + vct } #end #macro ReverseSpline(Spl) array [4] { Spl[3] Spl[2] Spl[1] Spl[0] } #end #macro RotateSpline (Spl,vct) array [4] { vrotate(Spl[0],vct), vrotate(Spl[1],vct), vrotate(Spl[2],vct), vrotate(Spl[3],vct) } #end #macro ScaleSpline(Spl,vct) array [4] { Spl[0]*vct, Spl[1]*vct, Spl[2]*vct, Spl[3]*vct } #end // 2-14-2000 #macro BezPatch(S1,C1,C2,S2) #declare cnt = 0; #declare stp = 0.05; #declare NumberofPoints = 20; #while(cnt < 1 ) #local nxt = cnt + 1/NumberofPoints; #local t0 = ReturnPosition(S1,cnt); #local t1 = ReturnPosition(C1,cnt); #local t2 = ReturnPosition(C2,cnt); #local t3 = ReturnPosition(S2,cnt); #local n0 = ReturnPosition(S1,nxt); #local n1 = ReturnPosition(C1,nxt); #local n2 = ReturnPosition(C2,nxt); #local n3 = ReturnPosition(S2,nxt); #declare Temp = array [4] { t0, t1, t2, t3 } #declare Next = array [4] { n0, n1, n2, n3 } ConnectSmooth(Temp,Next) #declare cnt = nxt; #end #end #macro BezFrame(S1,C1,C2,S2) #local tempCurve = FullCurve; #local FullCurve = true; DrawSpline(S1) // DrawSpline(C1) // DrawSpline(C2) DrawSpline(S2) #declare cnt = 0; #declare stp = 0.05; #while(cnt <= 1 ) #local nxt = cnt + 0.333; #local t0 = ReturnPosition(S1,cnt); #local t1 = ReturnPosition(C1,cnt); #local t2 = ReturnPosition(C2,cnt); #local t3 = ReturnPosition(S2,cnt); #declare Temp = array [4] { t0, t1, t2, t3 } DrawSpline(Temp) #declare cnt = nxt; #end #local FullCurve = tempCurve; #end // 02-21-2000 #macro BezPatch2(S1,C1,C2,S2) bicubic_patch { type 1 flatness 0.1 u_steps 3 // # of triangles to subdivide (1-5) v_steps 3 // # of triangles to subdivide (1-5) ReturnPosition(S1,0) ReturnPosition(S1,0.333) ReturnPosition(S1,0.6667) ReturnPosition(S1,1) ReturnPosition(C1,0) ReturnPosition(C1,0.333) ReturnPosition(C1,0.6667) ReturnPosition(C1,1) ReturnPosition(C2,0) ReturnPosition(C2,0.333) ReturnPosition(C2,0.6667) ReturnPosition(C2,1) ReturnPosition(S2,0) ReturnPosition(S2,0.333) ReturnPosition(S2,0.6667) ReturnPosition(S2,1) texture { BezTex } } #end