fast....
While linepick checks against every collide-able entity and the raypick I'm using in coldet only checks against 1 mesh its of such a magnitude faster its *well* worth using.
I dont envy simon his task at writing a linepick function, its just the sort of stuff I loath! I'm in no way criticizing his fine work, but here's why I implemented coldet
I wanted to align 30-40 entities so they aligned to the patch of a landscape they were over, my first approach used 3 linepicks per entity. Just in linepicks alone it was taking almost 60th of a second!
The landscape mesh I was testing against was 3,000 or so poly's and was the only "active" collidable, even with different setting on octtree didnt improve it
I added the model raypick to some previous coldet work I'd done over a year ago and it worked first time, which is always nice!
I made 250 tests against the terrain mesh and used less the 15-20% cpu time!
heres how to add it to your own miniB3D project
grab coldet from sourceforge, (I used the cvs version)
in src/sysdep.h add
#define GCC
add a new file called glue.cpp in the src directory
in the main coldet directory make a file called coldet.bmx
and finally heres a simple example that positions a sprite on a terrain mesh directly below the camera raytest.bmx
While purists will shriek at the idea of using C++ source code I think this would be ideal as a support lib, and it could always be ported to max, all said and done theres plenty of C++ in brl.mod/* and pub.mod/* for them to port too...
Not all of coldet is wrapped, but enough to do mesh<>mesh and ray<>mesh collisions
While linepick checks against every collide-able entity and the raypick I'm using in coldet only checks against 1 mesh its of such a magnitude faster its *well* worth using.
I dont envy simon his task at writing a linepick function, its just the sort of stuff I loath! I'm in no way criticizing his fine work, but here's why I implemented coldet
I wanted to align 30-40 entities so they aligned to the patch of a landscape they were over, my first approach used 3 linepicks per entity. Just in linepicks alone it was taking almost 60th of a second!
The landscape mesh I was testing against was 3,000 or so poly's and was the only "active" collidable, even with different setting on octtree didnt improve it
I added the model raypick to some previous coldet work I'd done over a year ago and it worked first time, which is always nice!
I made 250 tests against the terrain mesh and used less the 15-20% cpu time!
heres how to add it to your own miniB3D project
grab coldet from sourceforge, (I used the cvs version)
in src/sysdep.h add
#define GCC
add a new file called glue.cpp in the src directory
#include "coldet.h" extern "C" CollisionModel3D* newmodel(){ CollisionModel3D* model = newCollisionModel3D(); return model; } extern "C" void modeladdtri(CollisionModel3D* m,float x1,float y1,float z1,float x2,float y2,float z2,float x3,float y3,float z3){ m->addTriangle(x1,y1,z1,x2,y2,z2,x3,y3,z3); } extern "C" void makefinal(CollisionModel3D* m){ m->finalize(); } extern "C" void modelSetTransform(CollisionModel3D* m,float* tm){ m->setTransform(tm); } extern "C" bool havecollided(CollisionModel3D* m1,CollisionModel3D* m2){ return m1->collision (m2); } extern "C" void freeModel(CollisionModel3D * m){ delete m ; } extern "C" bool rayHit(CollisionModel3D * m , float ox , float oy , float oz , float dx , float dy , float dz , bool closest , float segmin=0.0f, float segmax = 3.4e+38F) { float o[3] ; float d[3] ; o[0]=ox; o[1]=oy; o[2]=oz; d[0]=dx; d[1]=dy; d[2]=dz; return m->rayCollision(o,d,closest,segmin,segmax); } extern "C" void getCollisionPoint (CollisionModel3D * m,float p[3] , bool ModelSpace = true ) { m->getCollisionPoint(p,ModelSpace); }
in the main coldet directory make a file called coldet.bmx
Import "src/glue.cpp" Import "src/tritri.c" Import "src/box.cpp" Import "src/box_bld.cpp" Import "src/coldet.cpp" Import "src/coldet_bld.cpp" Import "src/math3d.cpp" Import "src/mytritri.cpp" Import "src/sysdep.cpp" Import sidesign.minib3d Extern "C" Function newmodel:Byte Ptr() Function modeladdtri(m:Byte Ptr,vx1:Float,vy1:Float,vz1:Float,vx2:Float,vy2:Float,vz2:Float,vx3:Float,vy3:Float,vz3:Float) Function makefinal(m:Byte Ptr) Function modelSetTransform(colmodel:Byte Ptr,mat:Float Ptr) Function havecollided:Int(m1:Byte Ptr , m2:Byte Ptr) Function freeModel(m:Byte Ptr) Function rayHit:Byte(m:Byte Ptr , .. ox:Float , oy:Float , oz:Float , .. dx:Float , dy:Float , dz:Float , .. closest:Byte=False , .. segmin:Float=0.0, .. segmax:Float = 3.4 * (10 ^ 38) ) Function getCollisionPoint (colmodel:Byte Ptr,p:Float Ptr , ModelSpace:Byte = True ) EndExtern ' NB this will only work for mesh's made from triangles! Function addCollisionTrisFromMesh(colmodel:Byte Ptr,mesh:Tmesh) Local polys:TPolygon[]=TPolygon.MeshToPolygons(mesh) For Local p:TPolygon = EachIn polys modeladdtri(colmodel,p.verts[0].x,p.verts[0].y,p.verts[0].z,p.verts[1].x,p.verts[1].y,p.verts[1].z,p.verts[2].x,p.verts[2].y,p.verts[2].z) Next End Function
and finally heres a simple example that positions a sprite on a terrain mesh directly below the camera raytest.bmx
SuperStrict Import sidesign.minib3d Import "/your/path/to/coldet/coldet.bmx" Local width:Int=640,height:Int=480,depth:Int=16,mode:Int=0 Local hwidth:Int=width/2,hheight:Int=height/2 Graphics3D width,height,depth,mode 'create sky sphere Global sky:Tmesh=CreateSphere(32) Global tex:TTexture=LoadTexture( "cloudy_noon2.jpg" ) EntityTexture sky,tex ScaleEntity sky,1000,1000,1000 EntityFX sky,1 FlipMesh sky Global marker:Tsprite=LoadSprite("cursor.png") positionentity marker,0,10,0 Global camera:Tcamera=CreateCamera() camera.cameraclscolor 255,128,64 CameraClsMode camera,False,True PositionEntity camera,0,8.2,0 camera.camerazoom 1.25 camera.camerarange .1,2001 MoveMouse 320,240 HideMouse Global ground:Tmesh = LoadMesh("land3.b3d") Local br:Tbrush=CreateBrush() BrushShininess(br,0) Local tx:Ttexture=LoadTexture("grass.jpg") BrushTexture br,tx paintentity ground , br Global colModel:Byte Ptr=newmodel() ' NB this will only work for mesh's made from triangles! addCollisionTrisFromMesh(colmodel,ground) makefinal(colmodel) Global light:Tlight=CreateLight(2) PositionEntity light,0,50,0 LightColor light,25,25,25 AmbientLight 0,0,0 While Not KeyDown(KEY_ESCAPE) Local x_speed#,y_speed# x_speed=((MouseX()-320)-x_speed)/6+x_speed y_speed=((MouseY()-240)-y_speed)/6+y_speed MoveMouse 320,240 TurnEntity camera,0,-x_speed,0 'turn player Left/Right TurnEntity camera,-y_speed,0,0 'tilt camera ' Const spd:Float=0.15 If KeyDown(KEY_PAGEUP) Then camera.moveEntity(0,+spd,0) If KeyDown(KEY_PAGEDOWN) Then camera.moveEntity(0,-spd,0) If KeyDown(KEY_UP) Then camera.moveEntity(0,0,+spd) If KeyDown(KEY_DOWN) Then camera.moveEntity(0,0,-spd) If KeyDown(KEY_left) Then camera.moveEntity(-spd,0,0) If KeyDown(KEY_right) Then camera.moveEntity( + spd , 0 , 0) If rayHit(colmodel , entityx(camera) , entityy(camera) , entityz(camera) , 0 , - 1 , 0) Then Local pos:Float[3] getCollisionPoint(colModel , Varptr pos[0]) ' terrain is a 0,0,0 for no translation needed positionentity marker,pos[0],pos[1],pos[2] EndIf UpdateWorld RenderWorld Flip Wend freeModel(colModel)
While purists will shriek at the idea of using C++ source code I think this would be ideal as a support lib, and it could always be ported to max, all said and done theres plenty of C++ in brl.mod/* and pub.mod/* for them to port too...
Not all of coldet is wrapped, but enough to do mesh<>mesh and ray<>mesh collisions