123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- Namespace mojo3d
- Private
- Function Editing:Bool()
-
- Return Scene.GetCurrent().Editing
- End
- Function AddInstance( instance:Mesh,ctor:String,args:Variant[] )
-
- Local scene:=Scene.GetCurrent()
-
- If scene?.Editing scene.Jsonifier.AddInstance( instance,ctor,args )
- End
- Struct TerrainData
-
- Field heightMap:Pixmap
- Field bounds:Boxf
- Field width:Int
- Field depth:Int
- Field iscale:Float
- Field jscale:Float
-
- Method GetPosition:Vec3f( i:Int,j:Int )
-
- Local x:=i*iscale
- Local z:=j*jscale
-
- Local y:=heightMap.PixelPtr( i,j )[0]/255.0
-
- Return New Vec3f( x,y,z ) * bounds.Size + bounds.min
- End
- Method GetTexCoord0:Vec2f( i:Int,j:Int )
-
- Return New Vec2f( i*iscale,j*jscale )
- End
-
- Method GetNormal:Vec3f( i:Int,j:Int )
-
- Local v0:=GetPosition( i,j )
- Local v1:=GetPosition( i,Min( j+1,depth-1 ) )
- Local v2:=GetPosition( Min( i+1,width-1 ),j )
- Local v3:=GetPosition( i,Max( j-1,0 ) )
- Local v4:=GetPosition( Max( i-1,0 ),j )
-
- Local n0:=(v1-v0).Cross(v2-v0).Normalize()
- Local n1:=(v2-v0).Cross(v3-v0).Normalize()
- Local n2:=(v3-v0).Cross(v4-v0).Normalize()
- Local n3:=(v4-v0).Cross(v1-v0).Normalize()
-
- Local n:=(n0+n1+n2+n3).Normalize()
-
- ' If (i&15)=0 And (j&15)=0 print "n="+v
-
- ' DebugAssert( n.y>0 )
-
- Return n
- End
- End
- Public
- #rem monkeydoc Extension methods for creating meshes.
- #end
- Class Mesh Extension
-
- Function CreateRect:Mesh( rect:Rectf )
- Local mesh:=New Mesh(
- New Vertex3f[](
- New Vertex3f( rect.min.x,rect.max.y,0 ),
- New Vertex3f( rect.max.x,rect.max.y,0 ),
- New Vertex3f( rect.max.x,rect.min.y,0 ),
- New Vertex3f( rect.min.x,rect.min.y,0 ) ),
- New UInt[](
- 0,1,2,
- 0,2,3 ) )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateRect",New Variant[]( rect ) )
-
- mesh.UpdateTangents()
-
- Return mesh
- End
- Function CreateBox:Mesh( box:Boxf,xsegs:Int=1,ysegs:Int=1,zsegs:Int=1 )
-
- Local vertices:=New Vertex3f[ ((ysegs+1)*(xsegs+1) + (zsegs+1)*(xsegs+1) + (ysegs+1)*(zsegs+1))*2 ],vp:=vertices.Data
-
- For Local q:=-1 To 1 Step 2
- For Local y:=0 To ysegs
- For Local x:=0 To xsegs
- Local vx:=box.Width*x/xsegs+box.min.x
- Local vy:=box.Height*y/ysegs+box.min.y
- vp[0]=New Vertex3f( vx,vy,q>0 ? box.max.z Else box.min.z, Float(x)/xsegs,Float(y)/ysegs, 0,0,q )
- vp+=1
- Next
- Next
- For Local z:=0 To zsegs
- For Local x:=0 To xsegs
- Local vx:=box.Width*x/xsegs+box.min.x
- Local vz:=box.Depth*z/zsegs+box.min.z
- vp[0]=New Vertex3f( vx,q>0 ? box.max.y Else box.min.y,vz, Float(x)/xsegs,Float(z)/zsegs, 0,q,0 )
- vp+=1
- Next
- Next
- For Local y:=0 To ysegs
- For Local z:=0 To zsegs
- Local vy:=box.Height*y/ysegs+box.min.y
- Local vz:=box.Depth*z/zsegs+box.min.z
- vp[0]=New Vertex3f( q>0 ? box.max.x Else box.min.x,vy,vz, Float(z)/zsegs,Float(y)/ysegs, q,0,0 )
- vp+=1
- Next
- Next
- Next
-
- Local indices:=New UInt[ (ysegs*xsegs + zsegs*xsegs + ysegs*zsegs) * 12 ],ip:=indices.Data,v0:=0
-
- For Local i:=0 To 1
- For Local y:=0 Until ysegs
- For Local x:=0 Until xsegs
- ip[0]=v0 ; ip[1+i]=v0+xsegs+2 ; ip[2-i]=v0+1
- ip[3]=v0 ; ip[4+i]=v0+xsegs+1 ; ip[5-i]=v0+xsegs+2
- ip+=6
- v0+=1
- Next
- v0+=1
- Next
- v0+=xsegs+1
- For Local z:=0 Until zsegs
- For Local x:=0 Until xsegs
- ip[0]=v0 ; ip[1+i]=v0+1 ; ip[2-i]=v0+xsegs+2
- ip[3]=v0 ; ip[4+i]=v0+xsegs+2 ; ip[5-i]=v0+xsegs+1
- ip+=6
- v0+=1
- Next
- v0+=1
- Next
- v0+=xsegs+1
- For Local y:=0 Until ysegs
- For Local z:=0 Until zsegs
- ip[0]=v0 ; ip[1+i]=v0+1 ; ip[2-i]=v0+zsegs+2
- ip[3]=v0 ; ip[4+i]=v0+zsegs+2 ; ip[5-i]=v0+zsegs+1
- ip+=6
- v0+=1
- Next
- v0+=1
- Next
- v0+=zsegs+1
- Next
-
- Local mesh:=New Mesh( vertices,indices )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateBox",New Variant[]( box,xsegs,ysegs,zsegs ) )
-
- mesh.UpdateTangents()
-
- Return mesh
- End
- Function CreateSphere:Mesh( radius:float,hsegs:Int=24,vsegs:Int=12 )
-
- Local vertices:=New Stack<Vertex3f>
-
- For Local i:=0 Until hsegs
- vertices.Push( New Vertex3f( 0,radius,0, (i+.5)/hsegs,0 ) )
- Next
-
- For Local i:=1 Until vsegs
- Local pitch:=i*Pi/vsegs-Pi/2
- For Local j:=0 To hsegs
- Local yaw:=(j Mod hsegs)*TwoPi/hsegs
- Local p:=Mat3f.Rotation( pitch,yaw,0 ).k * radius
- vertices.Push( New Vertex3f( p.x,p.y,p.z, Float(j)/hsegs,Float(i)/vsegs ) )
- Next
- Next
-
- For Local i:=0 Until hsegs
- vertices.Push( New Vertex3f( 0,-radius,0, (i+.5)/hsegs,1 ) )
- Next
-
- Local indices:=New Stack<UInt>
-
- For Local i:=0 Until hsegs
- indices.AddAll( New UInt[]( i,i+hsegs+1,i+hsegs ) )
- Next
-
- For Local i:=1 Until vsegs-1
- For Local j:=0 Until hsegs
- Local v0:=i*(hsegs+1)+j-1
- indices.AddAll( New UInt[]( v0,v0+1,v0+hsegs+2 ) )
- indices.AddAll( New UInt[]( v0,v0+hsegs+2,v0+hsegs+1 ) )
- Next
- Next
-
- For Local i:=0 Until hsegs
- Local v0:=(hsegs+1)*(vsegs-1)+i-1
- indices.AddAll( New UInt[]( v0,v0+1,v0+hsegs+1 ) )
- Next
-
- Local vdata:=vertices.Data
- For Local i:=0 Until vertices.Length
- vdata[i].normal=vdata[i].position.Normalize()
- Next
-
- Local mesh:=New Mesh( vertices.ToArray(),indices.ToArray() )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateSphere",New Variant[]( radius,hsegs,vsegs ) )
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- Function CreateTorus:Mesh( outerRadius:Float,innerRadius:Float,outerSegs:Int=24,innerSegs:Int=12 )
-
- Local vertices:=New Vertex3f[ (outerSegs+1)*(innerSegs+1) ],vp:=vertices.Data
-
- For Local outer:=0 To outerSegs
-
- Local sweep:=Mat3f.Yaw( outer*TwoPi/outerSegs )
-
- For Local inner:=0 To innerSegs
-
- Local an:=inner*TwoPi/innerSegs
-
- Local cos:=Cos( an ),sin:=Sin( an )
-
- Local p:=sweep * New Vec3f( cos * innerRadius + outerRadius,sin * innerRadius,0 )
- Local t:=New Vec2f( Float(inner)/innerSegs,Float(outer)/outerSegs )
- Local n:=sweep * New Vec3f( cos,sin,0 )
-
- Local v:=New Vertex3f( p,t,n )
-
- vp[0]=v
- vp+=1
- Next
-
- Next
-
- Local indices:=New UInt[ outerSegs*innerSegs*6 ],ip:=indices.Data
-
- For Local outer:=0 Until outerSegs
-
- Local v0:=outer * (innerSegs+1)
-
- For Local inner:=0 Until innerSegs
-
- ip[0]=v0+innerSegs+1
- ip[2]=v0+innerSegs+2
- ip[1]=v0+1
-
- ip[3]=v0+innerSegs+1
- ip[5]=v0+1
- ip[4]=v0
-
- ip+=6
- v0+=1
-
- Next
- Next
-
- Local mesh:=New Mesh( vertices,indices )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateTorus",New Variant[]( outerRadius,innerRadius,outerSegs,innerSegs ) )
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- Function CreateCylinder:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
-
- Local hlength:=length/2
-
- Local vertices:=New Stack<Vertex3f>
- Local triangles:=New Stack<UInt>
-
- 'tube
- For Local i:=0 To segs
- Local yaw:=(i Mod segs) * TwoPi / segs
- Local v:=New Vec3f( Cos( yaw ) * radius,hlength,Sin( yaw )* radius )
- Local n:=New Vec3f( v.x,0,v.z ).Normalize()
- Local tc:=New Vec2f( Float(i)/segs,0 )
- vertices.Add( New Vertex3f( v,tc,n ) )
- v.y=-v.y
- tc.y=1
- vertices.Add( New Vertex3f( v,tc,n ) )
- Next
- For Local i:=0 Until segs
- triangles.Add( i*2 ) ; triangles.Add( i*2+2 ) ; triangles.Add( i*2+3 )
- triangles.Add( i*2 ) ; triangles.Add( i*2+3 ) ; triangles.Add( i*2+1 )
- Next
-
- 'caps
- Local v0:=vertices.Length
- For Local i:=0 Until segs
- Local yaw:=i * TwoPi / segs
- Local v:=New Vec3f( Cos( yaw ) * radius,hlength,Sin( yaw ) * radius )
- Local n:=New Vec3f( 0,1,0 )
- Local tc:=New Vec2f( v.x*.5+.5,v.z*.5+.5 )
- vertices.Add( New Vertex3f( v,tc,n ) )
- v.y=-v.y
- n.y=-n.y
- vertices.Add( New Vertex3f( v,tc,n ) )
- Next
- For Local i:=1 Until segs-1
- triangles.Add( v0 ) ; triangles.Add( v0+(i+1)*2 ) ; triangles.Add( v0+i*2 )
- triangles.Add( v0+1 ) ; triangles.Add( v0+i*2+1 ) ; triangles.Add( v0+(i+1)*2+1 )
- Next
-
- Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCylinder",New Variant[]( radius,length,axis,segs ) )
-
- Select axis
- Case Axis.X
- mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
- Case Axis.Z
- mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
- End
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- Function CreateCapsule:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
-
- Const HalfPi:=Pi/2
-
- Local vertices:=New Stack<Vertex3f>
- Local triangles:=New Stack<UInt>
-
- Local t0:=HalfPi/radius/(length+HalfPi/radius)
-
- Local hlength:=length/2
-
- 'Top hemisphere
- '
- For Local i:=0 Until segs
- vertices.Add( New Vertex3f( 0,hlength+radius,0, (i+.5)/segs,0, 0,1,0 ) )
- Next
- For Local j:=1 To segs
- Local pitch:=j*Pi/(segs*2)-HalfPi
- For Local i:=0 To segs
- Local yaw:=(i Mod segs) * TwoPi / segs
- Local n:=Mat3f.Rotation( pitch,yaw,0 ).k
- Local v:=n*radius
- v.y+=hlength
- vertices.Add( New Vertex3f( v.x,v.y,v.z, Float(i)/Float(segs),Float(j)/Float(segs)*2*t0, n.x,n.y,n.z ) )
- Next
- Next
- For Local i:=0 Until segs
- triangles.Add( i ) ; triangles.Add( i+segs+1 ) ; triangles.Add( i+segs )
- Next
- For Local j:=1 Until segs
- For Local i:=0 Until segs
- Local t:=j*(segs+1)+i-1
- triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
- triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
- Next
- Next
- Local v0:=vertices.Length
-
- For Local j:=segs Until segs*2
- Local pitch:=j*Pi/(segs*2)-HalfPi
- For Local i:=0 To segs
- Local yaw:=(i Mod segs) * TwoPi / segs
- Local n:=Mat3f.Rotation( pitch,yaw,0 ).k
- Local v:=n*radius
- v.y-=hlength
- vertices.Add( New Vertex3f( v.x,v.y,v.z, Float(i)/Float(segs),(Float(j)/Float(segs*2)-.5)*2*t0, n.x,n.y,n.z ) )
- Next
- Next
- For Local i:=0 Until segs
- vertices.Add( New Vertex3f( 0,-hlength-radius,0, (i+.5)/segs,1, 0,-1,0 ) )
- Next
- For Local j:=0 Until segs-1
- For Local i:=0 Until segs
- Local t:=j*(segs+1)+i+v0
- triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
- triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
- Next
- Next
-
- For Local i:=0 Until segs
- Local t:=(segs+1)*(segs-1)+i+v0
- triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+1 )
- Next
-
- ' Join 2 bits together...
- '
- For Local i:=0 Until segs
- Local t:=segs*(segs+1)-1+i
- triangles.Add( t ) ; triangles.Add( t+1 ) ; triangles.Add( t+segs+2 )
- triangles.Add( t ) ; triangles.Add( t+segs+2 ) ; triangles.Add( t+segs+1 )
- Next
-
- Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCapsule",New Variant[]( radius,length,axis,segs ) )
-
- Select axis
- Case Axis.X
- mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
- Case Axis.Z
- mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
- End
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- Function CreateCone:Mesh( radius:Float,length:Float,axis:Axis,segs:Int )
-
- Local hlength:=length/2
-
- Local vertices:=New Stack<Vertex3f>
- Local triangles:=New Stack<UInt>
-
- For Local i:=0 Until segs
- vertices.Add( New Vertex3f( 0,hlength,0, (i+.5)/segs,0, 0,1,0 ) )
- Next
- For Local i:=0 To segs
- Local yaw:=(i Mod segs) * TwoPi/segs
- Local n:=New Vec3f( Cos( yaw ),0,Sin( yaw ) )
- Local v:=New Vec3f( n.x*radius,-hlength,n.z*radius )
- Local tc:=New Vec2f( Float(i)/segs,1 )
- vertices.Add( new Vertex3f( v,tc,n ) )
- Next
- For Local i:=0 Until segs
- triangles.Add( i ) ; triangles.Add( i+segs+1 ) ; triangles.Add( i+segs )
- Next
-
- 'cap
- Local v0:=vertices.Length
- For Local i:=0 Until segs
- Local yaw:=i * TwoPi / segs
- Local n:=New Vec3f( Cos( yaw ),0,Sin( yaw ) )
- Local v:=New Vec3f( n.x*radius,-hlength,n.z*radius )
- Local tc:=New Vec2f( n.x*.5+.5,n.z*.5+.5 )
- vertices.Add( new Vertex3f( v,tc,n ) )
- Next
- For Local i:=1 Until segs-1
- triangles.Add( v0 ) ; triangles.Add( v0+i ) ; triangles.Add( v0+i+1 )
- Next
-
- Local mesh:=New Mesh( vertices.ToArray(),triangles.ToArray() )
-
- If Editing() AddInstance( mesh,"mojo3d.Mesh.CreateCone",New Variant[]( radius,length,axis,segs ) )
-
- Select axis
- Case Axis.X
- mesh.TransformVertices( New AffineMat4f( 0,1,0, 1,0,0, 0,0,1, 0,0,0 ) )
- Case Axis.Z
- mesh.TransformVertices( New AffineMat4f( 1,0,0, 0,0,1, 0,-1,0, 0,0,0 ) )
- End
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- Function CreateTerrain:Mesh( heightMap:Pixmap,bounds:Boxf )
- Local width:=heightMap.Width
- Local depth:=heightMap.Height
-
- Local data:TerrainData
- data.heightMap=heightMap
- data.bounds=bounds
- data.width=width
- data.depth=depth
- data.iscale=1.0/(width-1)
- data.jscale=1.0/(depth-1)
-
- Local vertices:=New Vertex3f[ width*depth ]
-
- For Local j:=0 Until depth
- Local vp:=vertices.Data+j*width
- For Local i:=0 Until width
- vp[i].position=data.GetPosition( i,j )
- vp[i].texCoord0=data.GetTexCoord0( i,j )
- vp[i].normal=data.GetNormal( i,j )
- Next
- Next
-
- Local indices:=New UInt[ (width-1)*(depth-1)*6 ]
-
- local ip:=indices.Data
-
- For Local j:=0 Until depth-1
- Local v0:=j*width
- For Local i:=0 Until width-1
- ip[0]=v0+i ; ip[1]=v0+i+1+width ; ip[2]=v0+i+1
- ip[3]=v0+i ; ip[4]=v0+i+width ; ip[5]=v0+i+1+width
- ip+=6
- Next
- Next
-
- Local mesh:=New Mesh( vertices,indices )
-
- mesh.UpdateTangents()
-
- Return mesh
- End
-
- End
- #rem monkeydoc Extension methods for creating models.
- #end
- Class Model Extension
-
- Function CreateBox:Model( box:Boxf,xsegs:Int,ysegs:Int,zsegs:Int,material:Material,parent:Entity=Null )
-
- Local mesh:=mojo3d.Mesh.CreateBox( box,xsegs,ysegs,zsegs )
-
- Local model:=New Model( mesh,material,parent )
-
- Return model
- End
-
- Function CreateSphere:Model( radius:Float,hsegs:Int,vsegs:Int,material:Material,parent:Entity=Null )
-
- Local mesh:=mojo3d.Mesh.CreateSphere( radius,hsegs,vsegs )
-
- Local model:=New Model( mesh,material,parent )
- Return model
- End
-
- Function CreateTorus:Model( outerRadius:Float,innerRadius:Float,outerSegs:Int,innerSegs:Int,material:Material,parent:Entity=Null )
-
- Local mesh:=mojo3d.Mesh.CreateTorus( outerRadius,innerRadius,outerSegs,innerSegs )
-
- Local model:=New Model( mesh,material,parent )
-
- Return model
- End
-
- Function CreateCylinder:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
-
- Local mesh:=mojo3d.Mesh.CreateCylinder( radius,length,axis,segs )
-
- Local model:=New Model( mesh,material,parent )
- Return model
- End
-
- Function CreateCapsule:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
-
- Local mesh:=mojo3d.Mesh.CreateCapsule( radius,length,axis,segs )
-
- Local model:=New Model( mesh,material,parent )
- Return model
- End
-
- Function CreateCone:Model( radius:Float,length:Float,axis:Axis,segs:Int,material:Material,parent:Entity=null )
-
- Local mesh:=mojo3d.Mesh.CreateCone( radius,length,axis,segs )
-
- Local model:=New Model( mesh,material,parent )
- Return model
- End
-
- Function CreateTerrain:Model( heightMap:Pixmap,bounds:Boxf,material:Material,parent:Entity=Null )
-
- Local mesh:=mojo3d.Mesh.CreateTerrain( heightMap,bounds )
-
- Local model:=New Model( mesh,material,parent )
- Return model
- End
-
- End
|