remstart ============================================================== = Title : DBC Challenge - under water Create Fish Mesh = Author : latch = Date : 01/15/2008 = Update : 01/17/2008 = Version: .03 ============================================================== Comments This is an example of how to build a mesh triangle by triangle without using memblocks. The function make_fish() will create a mesh that is supposed to look like a cute little fishy! For moveable fins and tail I just added a few primatives. the parameters are: make_fish(obj,size#,tiers) obj == the object number the fish will be size# == the x size of the body (not including tail) tiers == tiers^2 * 2 = number of polys (triangles) The minimum tiers is 4. Going above ten is not a great idea. I tried to use a very basic method of creating 2 grids - front and back, and then just pinching the ends together, separating the middle area (z) and then plotting the x and y with a bit of skewing on the y for the head and tail. There are better ways to do this for a shape rounded like a fish, like multiple ellipse shaped rings, but I wanted to keep the math as basic as possible for the demo. I did use a parabola for the head, and that's about as complex as the math got! The size of the function is due to the drawing of the triangles and limbs. The math to place the points is the smallest part. Building each model can be slow, but if a single model is built, it can be converted into a mesh and copies from it will be made much faster using MAKE OBJECT. ============================================================== remend rem ============================================================= rem = SET UP DISPLAY rem ============================================================= autocam off set display mode 800,600,32 sync on sync rate 60 rem ============================================================= rem = MAIN rem ============================================================= gosub _init position camera 0,0,-100 direction=1 do turn object left fish1,.3 turn object left fish2,.3 turn object left fish3,.3 ang#=wrapvalue(ang#+direction) if ang# = 6 then direction=-1 if ang# = 354 then direction=1 rotate limb fish1,1,limb angle x(fish1,1),wrapvalue(ang#*2),limb angle z(fish1,1) rotate limb fish2,1,limb angle x(fish2,1),ang#,limb angle z(fish2,1) rotate limb fish3,1,limb angle x(fish3,1),ang#,limb angle z(fish3,1) sync loop end rem ============================================================= rem = SUBROUTINES - PROCEDURES rem ============================================================= _init: rem fish fish1=1 fish2=2 fish3=3 fish4=4 rem textures gosub _textures rem make fish make_fish(fish1,40.0,4) texture object fish1,fish1 position object fish1,-30,0,0 make_fish(fish2,40.0,7) texture object fish2,fish2 position object fish2,30,0,0 make_fish(fish3,40.0,10) texture object fish3,fish3 position object fish3,0,-30,0 return `----------------------------------------------------------------- _textures: cls 0 ink rgb(255,0,0),0 dot 0,0 dot 0,1 get image fish1,0,0,2,2 cls 0 ink rgb(255,255,0),0 dot 0,0 dot 1,0 get image fish2,0,0,2,2 cls 0 ink rgb(0,255,0),0 dot 1,0 dot 1,1 get image fish3,0,0,2,2 return rem ============================================================= rem = FUNCTIONS rem ============================================================= function make_fish(obj,size#,tiers) rem make sure the minimum is 4x4 if tiers < 4 then tiers = 4 rem set up vertice plotting variables xinc#=size#/tiers yinc#=xinc#/3 zinc#=size#/12.0 tailx#=size#/4.0 taily#=((tiers-1)/2.0)*yinc# mid=(tiers-1)/2 rem array to hold points dim verts#((tiers^2)*2,2) rem go through x and y positions and calculate points for triangles for y=0 to tiers-1 for x=0 to tiers-1 rem v=vertices for front rem v2=vertices for back so we only have to run through one set of points v=x+(y*tiers) v2=v+tiers^2 rem front side rem check if we are at the tail if x=tiers-1 verts#(v,0)=(x*xinc#)+tailx# verts#(v,1)=taily# else rem check if we are at the head if x <= mid-1 rem upper parabola for the top of the head rem change the head size by changing 3.5 in (x*xinc#/3.5) if y > mid verts#(v,1)=taily#+sqrt(4*(y*yinc#/2)*(x*xinc#/3.5)) verts#(v,0)=x*xinc#/1.5 endif rem plot the lower parabola for the bottom of the head if y <= mid verts#(v,1)=taily#-sqrt(4*((taily#-y)*yinc#/2)*(x*xinc#/3.5)) verts#(v,0)=x*xinc#/1.5 endif else rem default x and y verts#(v,0)=x*xinc# verts#(v,1)=y*yinc# endif endif rem z values. The logic checks if we are at any edge of the grid rem and if so, it sets z=0 effectively "pinching" the ends closed rem if we are not at an edge, the -1.0 pushed the z value outwards rem towards the viewer (-z) by zinc# verts#(v,2)=-1.0*(zinc#*((y!0) & (y!tiers-1) & (x!0) & (x!tiers-1))) rem backside rem same x and y values, and opposite z values from front grid verts#(v2,0)=verts#(v,0) verts#(v2,1)=verts#(v,1) verts#(v2,2)=0.0-verts#(v,2) next x next y rem make triangles tri=obj lmb=0 for y=0 to tiers-2 for x=0 to tiers-2 v=x+(y*tiers) v2=v+tiers^2 rem triangle 1 x1#=verts#(v,0) y1#=verts#(v,1) z1#=verts#(v,2) x2#=verts#(v+tiers,0) y2#=verts#(v+tiers,1) z2#=verts#(v+tiers,2) x3#=verts#(v+tiers+1,0) y3#=verts#(v+tiers+1,1) z3#=verts#(v+tiers+1,2) rem this check is here to make sure we don't overwrite rem the object we are assigning to the fish since we reuse rem and delete the same object and mesh over and over rem to manage overhead as we go while object exist(tri)=1 inc tri endwhile make object triangle tri,x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3# rem the first triangle is the root object of the mesh initially rem so we don't want to turn it into a limb if v<>0 make mesh from object tri,tri inc lmb add limb obj,lmb,tri delete object tri delete mesh tri endif rem triangle 2 x1#=verts#(v+tiers+1,0) y1#=verts#(v+tiers+1,1) z1#=verts#(v+tiers+1,2) x2#=verts#(v+1,0) y2#=verts#(v+1,1) z2#=verts#(v+1,2) x3#=verts#(v,0) y3#=verts#(v,1) z3#=verts#(v,2) rem if we successfully created the first triangle, we rem want to make sure to skip that as an object to rem manipulate while object exist(tri)=1 inc tri endwhile make object triangle tri,x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3# inc lmb make mesh from object tri,tri add limb obj,lmb,tri delete object tri delete mesh tri rem back rem triangle 1 x1#=verts#(v2,0) y1#=verts#(v2,1) z1#=verts#(v2,2) x2#=verts#(v2+tiers,0) y2#=verts#(v2+tiers,1) z2#=verts#(v2+tiers,2) x3#=verts#(v2+tiers+1,0) y3#=verts#(v2+tiers+1,1) z3#=verts#(v2+tiers+1,2) make object triangle tri,x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3# inc lmb make mesh from object tri,tri add limb obj,lmb,tri delete object tri delete mesh tri rem triangle 2 x1#=verts#(v2+tiers+1,0) y1#=verts#(v2+tiers+1,1) z1#=verts#(v2+tiers+1,2) x2#=verts#(v2+1,0) y2#=verts#(v2+1,1) z2#=verts#(v2+1,2) x3#=verts#(v2,0) y3#=verts#(v2,1) z3#=verts#(v2,2) make object triangle tri,x1#,y1#,z1#,x2#,y2#,z2#,x3#,y3#,z3# inc lmb make mesh from object tri,tri add limb obj,lmb,tri delete object tri delete mesh tri next x next y rem make a whole mesh of the body to eliminate the hundreds of limbs rem just created make mesh from object obj,obj delete object obj make object obj,obj,0 delete mesh obj rem reset limb count lmb=0 rem add a tail tail=obj+1 while object exist(tail) inc tail endwhile make object cone tail,size#/2.0 rem set tail pivot position object tail,0,-1.0*object size y(tail)/2,0 scale object tail,100,100,10 make mesh from object tail,tail delete object tail inc lmb add limb obj,lmb,tail offset limb obj,lmb,size#/1.2,taily#,0 rotate limb obj,lmb,0,0,90 delete mesh tail rem top fin make object box tail,size#/4,size#/4,zinc#/8 make mesh from object tail,tail delete object tail inc lmb add limb obj,lmb,tail offset limb obj,lmb,size#/2,taily#*1.8,0 rotate limb obj,lmb,0,0,38 rem left fin rem set pivot make object tail,tail,0 position object tail,object size x(tail)/2,0,0 rotate object tail,0,30,45 delete mesh tail make mesh from object tail,tail delete object tail inc lmb add limb obj,lmb,tail offset limb obj,lmb,size#/4,taily#,zinc#*-1.5 scale limb obj,lmb,70,70,70 rem right fin inc lmb add limb obj,lmb,tail rotate limb obj,lmb,180,0,0 offset limb obj,lmb,size#/3,taily#,zinc#*1.5 scale limb obj,lmb,70,70,70 delete mesh tail rem turn culling off because individual triangles only have one direction rem for their normals no matter how they are rotated as a limb after rem creting them as a mesh. Otherwise, there will be holes in the mesh set object obj,1,1,0 endfunction