; ID: 1143 ; Author: big10p ; Date: 2004-08-22 18:32:38 ; Title: Mesh Clipping Demo ; Description: Clips a mesh along an arbitrary plane. ; ; Mesh clip demo by big10p (A.K.A. Chris Chadwick) 2004. ; ; Written with Blitz3D v1.87 ; ; Known issues: ; 1) copy_mesh_clip() attempts to paint the clipped mesh with the same brushes ; that are applied to the mesh being copied. For multiple surface meshes, ; GetSurfaceBrush() is used but only works if the mesh's surfaces have been ; painted with PaintSurface(). If the multi surface mesh has been painted ; en masse - using EntityTexture, EntityColor etc. - it doesn't work. ; 2) There seems to be a slight, noticeable color change when clipping tris that ; are vertex colored. Not sure if this is down to a lack of precision with floats ; or something I'm doing wrong. I'll have to investigate some more, I think. :) ; 3) I seem to get a much higher FPS (with frame locking turned off) if I turn off the ; visible clipping plane. Not sure why it makes such a big difference as it's only ; one surface with two triangles in!? :/ ; Graphics3D 800,600,32 ; Create chequer pattern texture. Global tex = CreateTexture(64,64) SetBuffer TextureBuffer(tex) For y = 0 To 63 Step 4 For x = 0 To 63 Step 2 If c Then Color 255,255,255 Else Color 255,0,0 c = Not c Rect x,y,2,4 Next c = Not c Next SetBuffer BackBuffer() WireFrame 0 AntiAlias 0 SeedRnd MilliSecs() ; Demo mesh info type. Type infoT Field mesh Field FX% Field vert_info% End Type ; Frame timing and control. Global frame_count% Global fps% Global slowest_fps% Global fps_timeout% Global frame_time% Global slowest_frame% Global frame_start% fps_timer = CreateTimer(60) ; Demo state flags. show_text% = True show_plane% = True rotate_plane% = True rotate_mesh% = True cull_backface% = False wiref% = False slowmo% = False frame_lock% = True ; Flags to tell clip_tri functions the order to wind triangles. Const WIND_012% = 0 Const WIND_102% = 1 Const WIND_201% = 2 ; Flags to tell copy_mesh_clip() which vertex info to include when clipping. Const CLIP_NORMALS% = 1 Const CLIP_UV_SET0% = 2 Const CLIP_UV_SET1% = 4 Const CLIP_RGBA% = 8 Const DEF_CLIP_INFO% = CLIP_NORMALS+CLIP_UV_SET0 cam = CreateCamera() CameraRange cam,1,100 PositionEntity cam,0,0,-3 light = CreateLight() AmbientLight 100,100,100 ; Create the demo meshes. Dim mesh.infoT(0) create_meshes() current_mesh% = 0 ; Clipping plane. Const MAX_PLANE_DIST# = 1.3 plane_pitch# = 0 plane_yaw# = 0 plane_dist# = -MAX_PLANE_DIST plane_move# = 0.01 plane_piv = CreatePivot() plane = CreateMesh(plane_piv) ps = CreateSurface(plane) AddVertex(ps,-2,0,2) AddVertex(ps,2,0,2) AddVertex(ps,-2,0,-2) AddVertex(ps,2,0,-2) AddTriangle(ps,0,1,2) AddTriangle(ps,1,3,2) EntityAlpha plane,.3 EntityColor plane,0,0,200 EntityFX plane,1+16 PositionEntity plane,0,plane_dist,0 RotateEntity plane_piv,plane_pitch,plane_yaw,0 clip_mesh = copy_mesh_clip(mesh(current_mesh)\mesh,plane_dist,plane_pitch,plane_yaw,mesh(current_mesh)\vert_info) EntityFX clip_mesh,mesh(current_mesh)\FX Xor (cull_backface Shl 4) ; ; --- Main loop --- ; While Not KeyHit(1) frame_start = MilliSecs() If KeyHit(2) Then show_text = Not show_text If KeyHit(3) show_plane = Not show_plane If show_plane Then ShowEntity plane Else HideEntity plane EndIf If KeyHit(4) rotate_plane = Not rotate_plane plane_pitch = 0 plane_yaw = 0 EndIf If KeyHit(5) Then rotate_mesh = Not rotate_mesh If KeyHit(6) Then cull_backface = Not cull_backface If KeyHit(7) Then wiref = Not wiref : WireFrame wiref If KeyHit(8) Then slowmo = Not slowmo If KeyHit(9) Then frame_lock = Not frame_lock If KeyHit(57) Then current_mesh = (current_mesh + 1) Mod 5 If rotate_mesh Then RotateMesh mesh(current_mesh)\mesh,1,0,1 ; Change clipping plane distance. plane_dist = plane_dist + plane_move If Abs(plane_dist) > MAX_PLANE_DIST Then plane_move = -plane_move ; Rotate clipping plane. If rotate_plane plane_pitch = (plane_pitch + 1) Mod 360 plane_yaw = (plane_yaw + .5) Mod 360 EndIf ; Create an updated, clipped version of the current mesh. FreeEntity clip_mesh clip_mesh = copy_mesh_clip(mesh(current_mesh)\mesh,plane_dist,plane_pitch,plane_yaw,mesh(current_mesh)\vert_info) EntityFX clip_mesh,mesh(current_mesh)\FX Xor (cull_backface Shl 4) ; Position visible plane to match clipping plane. If show_plane PositionEntity plane,0,plane_dist,0 RotateEntity plane_piv,plane_pitch,plane_yaw,0 EndIf RenderWorld frame_time = MilliSecs() - frame_start If show_text Then show_info() If frame_lock WaitTimer(fps_timer) Flip True Else Flip False EndIf If slowmo Then Delay 200 Wend End ; ; Creates a copy of a mesh, clipped along the given plane. ; Note: this function can only really perform clipping along an XZ aligned plane. ; To perform clipping on an arbitrary, rotated plane, we cheat :) - first ; we align the mesh to the XZ plane, perform the clipping, then return ; the mesh to it's original orientation. ; ; Params: ; source_mesh - Mesh to be copied (remains unaltered by this function). ; plane_y - Y distance of clipping plane from mesh origin. ; plane_pitch - Pitch of clipping plane. ; plane_yaw - Yaw of clipping plane. ; vert_info - Bit flags defining vertex info to include when clipping. ; ; Returns: ; Handle of newly created, clipped mesh. ; Function copy_mesh_clip(source_mesh,plane_y#,plane_pitch#,plane_yaw#,vert_info%=DEF_CLIP_INFO) surf_count = CountSurfaces(source_mesh) ; Temporarily align source mesh to XZ clipping plane. ; Note: doing yaw THEN pitch rotation separately is important! ; Prevents gimble lock when returning the mesh back to it's original rotation. RotateMesh source_mesh,0,-plane_yaw,0 RotateMesh source_mesh,-plane_pitch,0,0 If surf_count=1 ; We can make a copy of single surface meshes more quickly using CopyMesh. ; (Unfortunately, CopyMesh combines surfs unless they use different textures ; so this method can't be used with multi surface meshes). dest_mesh = CopyMesh(source_mesh) ; Kill tris but keep verts. ClearSurface GetSurface(dest_mesh,1),False,True brush = GetEntityBrush(source_mesh) PaintEntity dest_mesh,brush FreeBrush brush Else dest_mesh = CreateMesh() ; Copy all surfaces and vertices from source_mesh into dest_mesh. ; For ss=1 To surf_count source_surf = GetSurface(source_mesh,ss) brush = GetSurfaceBrush(source_surf) dest_surf = CreateSurface(dest_mesh,brush) FreeBrush brush For sv=0 To CountVertices(source_surf)-1 vy# = VertexY(source_surf,sv) dv = AddVertex(dest_surf,VertexX(source_surf,sv),vy,VertexZ(source_surf,sv)) ; We don't need to bother with any other info for verts ; in dest_mesh that are beyond the clipping plane. If Not vy fps_timeout Then fps_timeout = MilliSecs() + 1000 fps = frame_count frame_count = 0 If fps < slowest_fps Or slowest_fps = 0 Then slowest_fps = fps EndIf If frame_time > slowest_frame Then slowest_frame = frame_time Color 255,255,255 Text 10,10, "Press to toggle:" Text 10,25, "1 - This text" Text 10,40, "2 - Clipping plane" Text 10,55, "3 - Clipping plane rotation" Text 10,70, "4 - Mesh rotation" Text 10,85, "5 - Backface culling" Text 10,100,"6 - Wireframe" Text 10,115,"7 - Slow motion" Text 10,130,"8 - Frame lock" Text 10,160,"Press SPACE to change mesh" Color 255,255,0 Text 10,190,"Millisecs: " + frame_time Text 10,205," Slowest: " + slowest_frame Color 0,255,255 Text 10,220," FPS: " + fps Text 10,235," Worst: " + slowest_fps Else ; First call initialization. fps_timeout = MilliSecs() + 1000 EndIf End Function