//========================================= // ExtrudeSpline : Spline extrusion macro //----------------------------------------- // Extrudes a "shape" along "path" splines // ----------------------------------------- // Made for Persistence of vision 3.6 // ========================================= // Copyright 1999-2004 Gilles Tran http://www.oyonale.com // ----------------------------------------- // This work is licensed under the Creative Commons Attribution License. // To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/ // or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. // You are free: // - to copy, distribute, display, and perform the work // - to make derivative works // - to make commercial use of the work // Under the following conditions: // - Attribution. You must give the original author credit. // - For any reuse or distribution, you must make clear to others the license terms of this work. // - Any of these conditions can be waived if you get permission from the copyright holder. // Your fair use and other rights are in no way affected by the above. // ========================================== // ExtrudeSpline // ----------------------------------------- // ExtrudeSpline extrudes a spline shape along a spline path // nI = number of shape steps // nJ = nombre of path steps // the more steps the smoother it is (and the longer it takes to parse) // // arrI = shape spline // arrJ = path spline // These are cubic splines : this means that the 1rst and last points are // control points only and will not appear // The spline itself goes from point 2 to point n-1 // If these points are identical, the shape is closed // For a closed shape to be seamless, point 1 should be equal to point n-2 // and point 3 should be equal to point n // doSmooth : true smooths the triangles, false otherwise // doTest : true creates a test dummy object // doFile : true creates a file // fname : file name (mandatory even if doFile=false) // Requires the MakePoint and the SplinePoint macros // // usage : object{ExtrudeSpline(nseg,nseg,Shape,Path,doSmooth,doTest,doFile,fname) texture{pigment{Red} finish {phong 1}}} //----------------------------------------- #macro ExtrudeSpline(nI,nJ,arrI,arrJ,doSmooth,doTest,doFile,fname) #local nP=nI*nJ; #local P = array[nP] // Points #local kJ=dimension_size(arrI,1); // If the shape is closed, the seam will be smoothed too #if (vlength(arrI[1]-arrI[kJ-2])=0) #local IsClosed=true; #else #local IsClosed=false;#end //----------------------------------------- // Fills the P array of points //----------------------------------------- #warning concat("calculates the positions of ",str(nP,0,0)," points\n") #local q = 0; #while (q0)#if (vlength(P[q]-P[q-1])>0) cylinder{P[q],P[q-1],0.1} #end #end #local q=q+1; #end } #else //----------------------------------------- // If doTest=false, writes a mesh //----------------------------------------- // smoothing if doSmooth = true //----------------------------------------- #if (doSmooth=true) #warning "calculates the normals\n" #local N = array[nP] // Normals #local q=0; #while (q; #local k=0; #if (V5>-1 & V8>-1) #local N[q]=N[q]+vcross(P[V4]-P[V5],P[V8]-P[V4]);#local k=k+1;#end #if (V2>-1 & V5>-1) #local N[q]=N[q]+vcross(P[V4]-P[V2],P[V5]-P[V4]);#local k=k+1;#end #if (V1>-1 & V2>-1) #local N[q]=N[q]+vcross(P[V4]-P[V1],P[V2]-P[V4]);#local k=k+1;#end #if (V0>-1 & V1>-1) #local N[q]=N[q]+vcross(P[V4]-P[V0],P[V1]-P[V4]);#local k=k+1;#end #if (V3>-1 & V0>-1) #local N[q]=N[q]+vcross(P[V4]-P[V3],P[V0]-P[V4]);#local k=k+1;#end #if (V6>-1 & V3>-1) #local N[q]=N[q]+vcross(P[V4]-P[V6],P[V3]-P[V4]);#local k=k+1;#end #if (V7>-1 & V6>-1) #local N[q]=N[q]+vcross(P[V4]-P[V7],P[V6]-P[V4]);#local k=k+1;#end #if (V8>-1 & V7>-1) #local N[q]=N[q]+vcross(P[V4]-P[V8],P[V7]-P[V4]);#local k=k+1;#end #local N[q]=N[q]/k; #local q=q+1; #end #end //----------------------------------------- // writes the triangles //----------------------------------------- mesh{ #warning "writes the triangles\n" #if (doFile=true) #warning concat(fname," mesh file creation starts\n") #fopen filehandle fname write // creates the mesh #write(filehandle,"mesh{\n") #end #local q=0; #while (q<(nI*(nJ-1)-1)) #local i=mod(q,nI);#local j=(q-i)/nI; #if (i ,<",N[q].x,",",N[q].y,",",N[q].z,">,<",P[q+1].x,",",P[q+1].y,",",P[q+1].z,">,<",N[q+1].x,",",N[q+1].y,",",N[q+1].z,">,<",P[q+nI+1].x,",",P[q+nI+1].y,",",P[q+nI+1].z,">,<",N[q+nI+1].x,",",N[q+nI+1].y,",",N[q+nI+1].z,">}\n") #write(filehandle,"smooth_triangle{<",P[q].x,",",P[q].y,",",P[q].z,">,<",N[q].x,",",N[q].y,",",N[q].z,">,<",P[q+nI].x,",",P[q+nI].y,",",P[q+nI].z,">,<",N[q+nI].x,",",N[q+nI].y,",",N[q+nI].z,">,<",P[q+nI+1].x,",",P[q+nI+1].y,",",P[q+nI+1].z,">,<",N[q+nI+1].x,",",N[q+nI+1].y,",",N[q+nI+1].z,">}\n") #end smooth_triangle{P[q],N[q],P[q+1],N[q+1],P[q+nI+1],N[q+nI+1]} smooth_triangle{P[q],N[q],P[q+nI],N[q+nI],P[q+nI+1],N[q+nI+1]} #else #if (doFile=true) #write(filehandle,"triangle{<",P[q].x,",",P[q].y,",",P[q].z,">,<",P[q+1].x,",",P[q+1].y,",",P[q+1].z,">,<",P[q+nI+1].x,",",P[q+nI+1].y,",",P[q+nI+1].z,">}\n") #write(filehandle,"triangle{<",P[q].x,",",P[q].y,",",P[q].z,">,<",P[q+nI].x,",",P[q+nI].y,",",P[q+nI].z,">,<",P[q+nI+1].x,",",P[q+nI+1].y,",",P[q+nI+1].z,">}\n") #end triangle{P[q],P[q+1],P[q+nI+1]} triangle{P[q],P[q+nI],P[q+nI+1]} #end #end #local q=q+1; #end #if (doFile=true) #write (filehandle,"}\n") #fclose filehandle #warning concat(fname," file created\n") #end #warning concat(str(2*q,0,0)," triangles created\n") } #end #end //----------------------------------------- // end de la macro makeMesh //----------------------------------------- //========================================= // MakePoint //----------------------------------------- // this macro returns the position in space of a point // according to the i (shape) and j (path) steps //----------------------------------------- #macro MakePoint(i,j,nI,nJ,arrI,arrJ) #local tti=i/(nI-1); #local ttj=j/(nJ-1); #local ttj2=(j + 1)/(nJ-1); //#local r=0.2*(sin(5*pi*ttj)*0.3+1.9); #local P1=SplinePoint(arrJ,ttj) #local P2=SplinePoint(arrJ,ttj2) #local yV1=vnormalize(P2-P1); #local xV1=vnormalize(vcross(yV1,z)); #local zV1=vcross(xV1,yV1); #local vectorShape=SplinePoint(arrI,tti) //#local vectorShape = r*vectorShape; #local answer=; answer; #end //----------------------------------------- // end of MakePoint //----------------------------------------- //========================================= // SplinePoint macro by Steve Sloan //----------------------------------------- // This macro read a point array "P" and a value "oldt" between 0 and 1 // and returns a point vector that corresponds // to the position of oldt on the P spline //----------------------------------------- #macro SplinePoint(P,oldt) #local n = dimension_size(P,1); #local n = n - 1; #if (oldt<1) #local segment = int(oldt*(n - 2)) + 1; #local i = segment + 2; #local c = array[4] #local c[0] = -P[i-3] + 3*P[i-2] - 3*P[i-1] + P[i]; #local c[1] = 2*P[i-3] - 5*P[i-2] + 4*P[i-1] - P[i]; #local c[2] = -P[i-3] + P[i-1]; #local c[3] = 2*P[i-2]; #local t1 = oldt*(n - 2) - segment + 1; #local t2 = t1*t1; #local t3 = t2*t1; #local answer = 0.5*(c[0]*t3 + c[1]*t2 + c[2]*t1 + c[3]); #else #if (oldt>1) #local answer=P[n]; #else #local answer=P[n-1]; #end #end answer; #end //======================================= // Examples //----------------------------------------- #include "colors.inc" #declare PdV=<0, 0.1 , -45>; #declare PdA=<0,0,0>; camera {location PdV direction 1.5*z up y right 4*x/3 look_at PdA} light_source{PdV color White*0.2 shadowless} light_source{<130,40,-200> color White*2} #declare nseg=30; // number of segments ; the higher the smoother #declare doSmooth=true; // true to smooth the triangles #declare doTest=false; // true to see a skeleton #declare doFile=false; // true creates a file #declare fname="mesh1.inc" // file name (mandatory even if doFile=false) #declare Path = array[9] {<-20,-3,-4>,<-15,-1,-5>,<-10,1,2>,<-5,2,0>,<0,2,2>,<5,-1,4>,<10,-2,0>,<15,0,-1>,<20,0,0>} // closed shape, pipe-like #declare Shape = array[7] {<3,0,0>,<0,0,-2>,<-3,0,0>,<0,0,3>,<3,0,0>,<0,0,-2>,<-3,0,0>} // open shape drape-like //#declare Shape = array[7] {<-20,0,0>,<-10,0,-2>,<-2,0,-4>,<0,0,-1>,<4,0,-4>,<10,0,-2>,<20,0,0>} object{ExtrudeSpline(nseg,nseg,Shape,Path,doSmooth,doTest,doFile,fname) texture{pigment{Red} finish {phong 1}}} //object{#include "mesh1.inc" texture{pigment{Green} finish {phong 1}}}