Code archives/3D Graphics - Misc/TriMesh

This code has been declared by its author to be Public Domain code.

Download source code

TriMesh by BlitzSupport2002
Draws the triangles in a mesh, skipping those facing away from the camera. Useful for limited display of simple meshes, anyway...

Big thanks to Mark, SSwift and Floyd!

UPDATED: Speeded up a lot by inlining everything. Now using Simon Armstrong's AcidLine function for even more speed :)
; -----------------------------------------------------------------------------
; TriMesh (camera, mesh)
; -----------------------------------------------------------------------------
; Inline version, uses Simon Armstrong's line function (which Blitz's line
; function is based on), because you can use it on locked buffers, which turns
; out to be quite a lot faster in this fairly demanding loop...

Function TriMesh (usecam, mesh, argb = $FFFFFFFF)

	; Save some hassle if the mesh can't be seen...
	
	If EntityInView (mesh, usecam)

		; Lock current buffer...
		
		LockBuffer

			; Parse each surface in mesh...
			
			For s = 1 To CountSurfaces (mesh)
	
				surf = GetSurface (mesh, s)
	
				; Parse each triangle in surface...
				
				For t = 0 To CountTriangles (surf) - 1
	
					; Get triangle's vertice positions... presumably these are
					; in anti-clockwise order (since it appears to work :)
	
					v0 = TriangleVertex (surf, t, 0)
					v1 = TriangleVertex (surf, t, 1)
					v2 = TriangleVertex (surf, t, 2)
	
					; ---------------------------------------------------------
					; Mark's code for backface culling...
					; ---------------------------------------------------------
					
				    ; Vertex positions...
				
				    x0# = VertexX (surf, v0)
					y0# = VertexY (surf, v0)
					z0# = VertexZ (surf, v0)
					
				    x1# = VertexX (surf, v1)
					y1# = VertexY (surf, v1)
					z1# = VertexZ (surf, v1)
					
				    x2# = VertexX (surf, v2)
					y2# = VertexY (surf, v2)
					z2# = VertexZ (surf, v2)
				    
				    ; Deltas...
				
				    dx1# = x1 - x0: dy1# = y1 - y0: dz1# = z1 - z0
				    dx2# = x2 - x0: dy2# = y2 - y0: dz2# = z2 - z0
				
				    ; Cross product...
				
				    cx# = dy1 * dz2 - dy2 * dz1
				    cy# = dz1 * dx2 - dz2 * dx1
				    cz# = dx1 * dy2 - dx2 * dy1
				    
				    ; Normalize...
				
				    sz# = Sqr (cx * cx + cy * cy + cz * cz)
				    cx = cx / sz: cy = cy / sz: cz = cz / sz
				    
				    ; Plane offset...
				
				    dt# = -(cx * x0 + cy * y0 + cz * z0)
				    
				    ; Transform eye to mesh coords...
				
				    TFormPoint 0, 0, 0, usecam, mesh
	
					; Super-complicated cull-decision stuff...

				    If TFormedX () * cx + TFormedY () * cy + TFormedZ () * cz + dt > 0

						; -----------------------------------------------------
						; Get 2D position for each point of triangle...
						; -----------------------------------------------------
	
						TFormPoint (x0, y0, z0, mesh, 0)
						CameraProject usecam, TFormedX (), TFormedY (), TFormedZ ()
						vx0 = ProjectedX ()
						vy0 = ProjectedY ()
	
						TFormPoint (x1, y1, z1, mesh, 0)
						CameraProject usecam, TFormedX (), TFormedY (), TFormedZ ()
						vx1 = ProjectedX ()
						vy1 = ProjectedY ()
	
						TFormPoint (x2, y2, z2, mesh, 0)
						CameraProject usecam, TFormedX (), TFormedY (), TFormedZ ()
						vx2 = ProjectedX ()
						vy2 = ProjectedY ()
	
						; -----------------------------------------------------
						; Draw triangle...
						; -----------------------------------------------------

						AcidLine (vx0, vy0, vx1, vy1, argb)
						AcidLine (vx1, vy1, vx2, vy2, argb)
						AcidLine (vx2, vy2, vx0, vy0, argb)
						
					EndIf
					
				Next
	
			Next

		; Unlock locked buffer...
		
		UnlockBuffer

	EndIf

End Function

; -----------------------------------------------------------------------------
; Simon Armstrong's Line function, slightly modified: I lock the buffers once
; per TriMesh call, so disabled that here -- be sure to re-enabled the commented
; out Lock/UnlockBuffer lines if you use this elsewhere!
; -----------------------------------------------------------------------------

Function AcidLine (x0, y0, x1, y1, argb)

	cx0 = 0
	cy0 = 0

	cx1 = GraphicsWidth () - 1
	cy1 = GraphicsHeight () - 1

	While True

		clip0 = 0
		clip1 = 0
		
		If y0 > cy1 clip0 = clip0 Or 1 Else If y0 < cy0 clip0 = clip0 Or 2 
		If x0 > cx1 clip0 = clip0 Or 4 Else If x0 < cx0 clip0 = clip0 Or 8 
		If y1 > cy1 clip1 = clip1 Or 1 Else If y1 < cy0 clip1 = clip1 Or 2
		If x1 > cx1 clip1 = clip1 Or 4 Else If x1 < cx0 clip1 = clip1 Or 8 

		If (clip0 Or clip1) = 0 Exit ;draw Line
		If (clip0 And clip1) Return ;outside

		If (clip0 And 1) = 1 x0 = x0 + ((x1 - x0) * (cy1 - y0)) / (y1 - y0) y0 = cy1 Goto continue 
		If (clip0 And 2) = 2 x0 = x0 + ((x1 - x0) * (cy0 - y0)) / (y1 - y0) y0 = cy0 Goto continue 
		If (clip0 And 4) = 4 y0 = y0 + ((y1 - y0) * (cx1 - x0)) / (x1 - x0) x0 = cx1 Goto continue 
		If (clip0 And 8) = 8 y0 = y0 + ((y1 - y0) * (cx0 - x0)) / (x1 - x0) x0 = cx0 Goto continue 
		If (clip1 And 1) = 1 x1 = x0 + ((x1 - x0) * (cy1 - y0)) / (y1 - y0) y1 = cy1 Goto continue 
		If (clip1 And 2) = 2 x1 = x0 + ((x1 - x0) * (cy0 - y0)) / (y1 - y0) y1 = cy0 Goto continue 
		If (clip1 And 4) = 4 y1 = y0 + ((y1 - y0) * (cx1 - x0)) / (x1 - x0) x1 = cx1 Goto continue 
		If (clip1 And 8) = 8 y1 = y0 + ((y1 - y0) * (cx0 - x0)) / (x1 - x0) x1 = cx0 Goto continue 

		.continue

	Wend
	
	dx = x1 - x0
	dy = y1 - y0

	;RuntimeError dx
		
	If (dx Or dy) = 0 
		WritePixel x0, y0, argb
		Return
	EndIf
	
	If (dx >= 0) sx = 1: ax = dx Else sx =-1: ax = -dx 
	If (dy >= 0) sy = 1: ay = dy Else sy =-1: ay = -dy 
	
;	LockBuffer GraphicsBuffer ()

	If (ax > ay)
	
		ddf	 = ay + ay - ax
		sadj = ax + ax
		padj = ay + ay
		
		While (ax > -1);0)
			WritePixelFast x0, y0, argb
			x0 = x0 + sx
			ddf = ddf + padj
			If (ddf > 0) y0 = y0 + sy: ddf = ddf - sadj
			ax = ax - 1
		Wend
		
	Else
	
		ddf  = ax + ax - ay
		sadj = ay + ay
		padj = ax + ax
		
		While (ay > -1);0)
			WritePixelFast x0, y0, argb
			y0  = y0 + sy
			ddf = ddf + padj
			If (ddf > 0) x0 = x0 + sx: ddf = ddf - sadj
			ay = ay - 1
		Wend
		
	EndIf
	
;	UnlockBuffer GraphicsBuffer ()
	
End Function



; -----------------------------------------------------------------------------
; Demo...
; -----------------------------------------------------------------------------

AppTitle "TriMesh: Use cursors, plus A & Z... SPACE draws lines"

Graphics3D 640, 480, 0, 2

; Our camera...

cam = CreateCamera ()
CameraClsColor cam, 32, 64, 96
MoveEntity cam, 0, 0, -5

; A cube, yesterday...

cube = CreateCube ()
EntityColor cube, 128, 128, 64

; A light...

light = CreateLight ()
PositionEntity light, -100, 20, -50
PointEntity light, cube

Repeat

	TurnEntity cube, 0.1, 0.2, 0.4
		
	If KeyDown (203) TranslateEntity cube, -0.1, 0, 0
	If KeyDown (205) TranslateEntity cube, 0.1, 0, 0
	If KeyDown (200) TranslateEntity cube, 0, 0.1, 0
	If KeyDown (208) TranslateEntity cube, 0, -0.1, 0
	If KeyDown (30) TranslateEntity cube, 0, 0, 0.1
	If KeyDown (44) TranslateEntity cube, 0, 0, -0.1

	RenderWorld

	If KeyDown (57)
		TriMesh cam, cube
	Else
		EntityAlpha cube, 1
	EndIf
	
	Flip

Until KeyHit (1)

End

Comments

RemiD2016
I would have called this "wireframe overlay on frontfaces".

Thanks,


Code Archives Forum