I recommend using this method rather than .X or .b3d, because you get direct access to all the information the editor saves. Entity properties are stored in the entity name. You can use KeyValue$(entity,keyname$) to retrieve keyvalues. For example, KeyValue$(entity,"classname") might return "light".
If Windowed3D() Graphics3D 640,480,16,2 Else Graphics 640,480,16,1 SetBuffer BackBuffer() cam=CreateCamera() CameraRange cam,1,10000 TurnEntity cam,0,35,0 MoveEntity cam,0,200,-1500 CameraZoom cam,1.5 CreateLight() map=LoadCSM("..\..\maps\bedroom.csm",CurrentDir()+"..\..\textures") While Not KeyHit(1) RotateEntity map,0,MilliSecs()/100.0,0 RenderWorld Flip Wend End ;================================================= ;================================================= Function LoadCSM(file$,texturepath$="") f=ReadFile(file) If Not f Return ChangeDir FileDir(file) lightmapbank=CreateBank() texturebank=CreateBank() ;Version version=ReadInt(f) If version<>4 CloseFile f Return EndIf map=CreatePivot() ;Groups DebugLog groupcount+" groups" groupcount=ReadInt(f) For n=1 To groupcount flags=ReadInt(f) group=ReadInt(f) Properties$=readstringn(f) r=ReadInt(f) g=ReadInt(f) b=ReadInt(f) Next ;Lightmaps lightmapcount=ReadInt(f) DebugLog lightmapcount+" lightmaps" For n=1 To lightmapcount w=ReadInt(f) h=ReadInt(f) texture=CreateTexture(w,h) TextureCoords texture,1 ResizeBank lightmapbank,BankSize(lightmapbank)+4 PokeInt lightmapbank,BankSize(lightmapbank)-4,texture LockBuffer TextureBuffer(texture) For ty=0 To h-1 For tx=0 To w-1 hue=ReadInt(f) WritePixelFast tx,ty,hue,TextureBuffer(texture) Next Next UnlockBuffer TextureBuffer(texture) Next ;Meshes meshcount=ReadInt(f) DebugLog meshcount+" meshes" For n=1 To meshcount flags=ReadInt(f) group=ReadInt(f) properties$=readstringn(f) r=ReadInt(f) g=ReadInt(f) b=ReadInt(f) x#=ReadFloat(f) y#=ReadFloat(f) z#=ReadFloat(f) facecount=ReadInt(f) DebugLog facecount+" surfaces." mesh=CreateMesh(map) NameEntity mesh,properties PositionEntity mesh,x,y,z ;Surfaces For s=1 To facecount flags=ReadInt(f) texturefile$=readstringn(f) lightmapindex=ReadInt(f) offsetu#=ReadFloat(f) offsetv#=ReadFloat(f) scaleu#=ReadFloat(f) scalev#=ReadFloat(f) rotation#=ReadFloat(f) vertexcount=ReadInt(f) DebugLog vertexcount+" vertices" trianglecount=ReadInt(f) DebugLog trianglecount+" triangles" linecount=ReadInt(f) surf=CreateSurface(mesh) brush=CreateBrush() BrushFX brush,2 texturefile=Lower(texturefile) texture=retrievetexture(texturepath+texturefile,texturebank) If texture BrushTexture brush,texture If lightmapindex>0 And lightmapindex*4<=BankSize(lightmapbank) lightmap=PeekInt(lightmapbank,(lightmapindex-1)*4) If lightmap BrushTexture brush,lightmap,0,1 BrushFX brush,3 EndIf EndIf PaintSurface surf,brush FreeBrush brush ;Vertices For v=0 To vertexcount-1 x#=ReadFloat(f) y#=ReadFloat(f) z#=ReadFloat(f) nx#=ReadFloat(f) ny#=ReadFloat(f) nz#=ReadFloat(f) r=ReadInt(f) g=ReadInt(f) b=ReadInt(f) u0#=ReadFloat(f) v0#=ReadFloat(f) w0#=ReadFloat(f) u1#=ReadFloat(f) v1#=ReadFloat(f) w1#=ReadFloat(f) TFormPoint x,y,z,0,mesh AddVertex surf,TFormedX(),TFormedY(),TFormedZ(),u0,-v0 VertexColor surf,v,r,g,b VertexTexCoords surf,v,u1,-v1,0,1 VertexNormal surf,v,nx,ny,nz Next ;Triangles For t=0 To trianglecount-1 a=ReadInt(f) b=ReadInt(f) c=ReadInt(f) AddTriangle surf,a,c,b Next For l=0 To linecount-1 a=ReadInt(f) b=ReadInt(f) Next Next Next ;Point Entities entitycount=ReadInt(f) DebugLog entitycount+" entities" For n=1 To entitycount flags=ReadInt(f) group=ReadInt(f) properties$=readstringn(f) x#=ReadFloat(f) y#=ReadFloat(f) z#=ReadFloat(f) entity=CreatePivot(map) NameEntity entity,properties PositionEntity entity,x,y,z Next ;Free textures For n=0 To BankSize(lightmapbank)-1 Step 4 FreeTexture PeekInt(lightmapbank,n) Next FreeBank lightmapbank For n=0 To BankSize(texturebank)-1 Step 8 FreeBank PeekInt(texturebank,n) FreeTexture PeekInt(texturebank,n+4) Next FreeBank texturebank CloseFile f Return map End Function ;Read a null-terminated string Function ReadStringN$(f,maxlength=0) Repeat ch=ReadByte(f) If ch=0 Return t$ If maxlength If Len(t$)=maxlength Return t$+Chr(ch) EndIf t$=t$+Chr$(ch) Forever End Function ;Return a loaded texture Function RetrieveTexture(file$,bank) For n=0 To BankSize(bank)-1 Step 8 namebank=PeekInt(bank,n) s$="" For b=0 To BankSize(namebank)-1 s=s+Chr(PeekByte(namebank,b)) Next If s=file Return PeekInt(bank,n+4) Next ResizeBank bank,BankSize(bank)+8 namebank=CreateBank(Len(file)) For b=0 To BankSize(namebank)-1 PokeByte namebank,b,Asc(Mid(file,b+1)) Next DebugLog "Loading texture "+Chr(34)+CurrentDir()+file+Chr(34) PokeInt bank,BankSize(bank)-8,namebank texture=LoadTexture(file) If Not texture DebugLog "Failed to load texture "+Chr(34)+CurrentDir()+file+Chr(34) PokeInt bank,BankSize(bank)-4,texture Return texture End Function ;Get the file part of a file path Function FileName$(file$,ext=1) file=Replace(file,"/","") Repeat p=Instr(file,"") If p file=Right(file,Len(file)-p) Else Exit EndIf Forever If Not ext p=Instr(file,".") If p file=Left(file,p-1) EndIf Return file End Function ;Get the directory of a file path Function FileDir$(file$) file=Replace(file,"/","") oldp=1 Repeat p=Instr(file,"",oldp) If p oldp=p+1 Else file=Left(file,oldp-1) Exit EndIf Forever Return file End Function ;Parsing function Function Piece$(s$,entry,char$=" ") While Instr(s,char+char) s=Replace(s,char+char,char) Wend For n=1 To entry-1 p=Instr(s,char) s=Right(s,Len(s)-p) Next p=Instr(s,char) If p<1 a$=s Else a=Left(s,p-1) EndIf Return a End Function ;Function for retrieving entity properties ;[ "light"=KeyValue(entity,"classname") ] Function KeyValue$(entity,key$) properties$=EntityName(entity) key$=Lower(key) Repeat p=Instr(properties,Chr(10)) If p test$=(Left(properties,p-1)) Else test=properties testkey$=Piece(test,1,"=") testkey=Trim(testkey) testkey=Replace(testkey,Chr(34),"") testkey=Lower(testkey) If testkey=key value$=Piece(test,2,"=") value$=Trim(value$) value$=Replace(value$,Chr(34),"") Return value EndIf If Not p Return properties=Right(properties,Len(properties)-p) Forever End Function