How to know if a triangle is facing the camera?

Blitz3D Forums/Blitz3D Programming/How to know if a triangle is facing the camera?

Hi,

I've been working with Sswift normal code from the archive...

http://www.blitzbasic.com/codearcs/codearcs.php?code=976

I was hoping that with the normal of the surface, that I would be able to tell if the triangle was in view of the camera. Is this logical or am I barking up the wrong tree? Any clues would be really appreciated as Im new to all this mesh/surface/triangles/vertex business.

Cheers

Yeah, i'm sure checking the normal of the triangle is the way to go. I would assume, tforming the normal (TFormNormal) to the cameras co-ords, would allow you to easily check by determining if the z vector is minus or not.

Could be wrong, but i think that's the way it works :o)

This should work ..

;get cameras direction normal
Tformnormal 0,0,1,Camera, 0
CamNx# = tformedx()
CamNy# = tformedy()
CamNz# = tformedz()

;compute dot product of camera normal and tri normal
CdotN# = CamNx*TriNx + CamNY * TriNy + CamNz * TriNz
If CdotN < 0 then
  {This tri is facing the camera}
Endif


I forget whether the CdotN should be < 0 or greater so bear that in mind if it doesn't work as is.

Stevie

Thanks both. I seem to be having a problem that my triangle normals are correct. I can calculate the mid point of triangle ok, and I would expect to see my normal coming out 90 to the surface, however the seem to be coming out at an odd angle. I've tried the codes in the archives, but seem to be doing something wrong.

Does anyone have a demo showning the a triangles norm, or a demo showing when a face is visible to the camera? Here's hoping as my head is hurting ;)

Cheers again,


Unc

What do you need this for? Are you using updatenormals - this will average the normals of shared vertices so is wrong?

hello, basically Im a using poly which isn't unwelded, so there are a lot of shared verts. I was hoping to try and find out which verts were visible to the camera (for a hidden line routine).

Im still new to this cross product / dot product stuff and still getting my head around it. Anyway when I use a dot product to check visibility with the shared verts, it doesnt always work i.e. I can physically see the vert on the screen before dot product is <=0. Maybe Im doing something wrong here?

So my next idea was to use the normals of each of triangle to check their dot products. If they were in view then I could assume that all the verts that go to make up that triangle are also visible (and therefore I wouldnt need to unweld my model).

HHmm I hope its clear? Thanks for you help on this Stevie G :)

Anyway when I use a dot product to check visibility with the shared verts, it doesnt always work i.e. I can physically see the vert on the screen before dot product is <=0.

1) You should probably unweld and correct the vertex normals first.
2) IIRC you need to point the camera at the vertex you are checking against. Or use a pivot as a 'dummy' camera, parented to the real camera. Then you don't have to bother restoring its rotation afterwards.

Maybe try (2) first and see if that sorts it out.

Here's the code so far. I can't take any credit for it as its Sswifts more or less. It's close to what Im looking for, but you will see when you turn the mesh, some vertexs appear before they should (this happens with welded and unwelded meshes) - I guess because Im not looking at any normals, and only verts positions.

Ref, your suggestion Joe, Im not sure where I would do that. Does the angle of the camera effect the dot calculation. Sorry Im really new to this.

;setup graphics
Graphics3D 1024, 768, 0, 2
SetBuffer BackBuffer()

;enable wireframe	
WireFrame 1

;create camera	
Global main_cam = CreateCamera()
MoveEntity main_cam, 0, 0, -5

;create cube	
Global cube = CreateSphere(4)

Global surfaces,tris,verts

Function plotvertex(x,y,col)
	If col=1 Then 
		Color 0,255,0
	Else
		Color 255,0,0
	EndIf
	Oval x,y,3,3
End Function

Function Hidden(mesh)
	; Calculate the normal which indicates the direction the camera is pointing.	
	TFormNormal 0,0,1, main_cam, 0	
	CNx# = TFormedX#()
	CNy# = TFormedY#()
	CNz# = TFormedZ#()
	;count the surfaces of the mesh
	surfaces=CountSurfaces(mesh)
	
	;loop through all the surfaces
	For surfcount=1 To surfaces
		;count the number of triangles on the surfaces
		s=GetSurface(mesh,surfcount)
		tris=CountTriangles(s)
		verts=CountVertices(s)
		For t=0 To tris-1
			
			;get the corners of each triangle
			corner1=TriangleVertex(s,t,0)
			corner2=TriangleVertex(s,t,1)
			corner3=TriangleVertex(s,t,2)
			
			; get vertex information for corner 1
			TFormPoint VertexX(s,corner1),VertexY(s,corner1),VertexZ(s,corner1),mesh,0
			ax#=TFormedX()
			ay#=TFormedY()
			az#=TFormedZ()
			CameraProject main_cam,ax,ay,az
			vax#=ProjectedX()	
			vay#=ProjectedY()
			
			; get vertex information for corner 2
			TFormPoint VertexX(s,corner2),VertexY(s,corner2),VertexZ(s,corner2),mesh,0
			bx#=TFormedX()
			by#=TFormedY()
			bz#=TFormedZ()
			CameraProject main_cam,bx,by,bz
			vbx#=ProjectedX()	
			vby#=ProjectedY()
			
			; get vertex information for corner 3
			TFormPoint VertexX(s,corner3),VertexY(s,corner3),VertexZ(s,corner3),mesh,0
			cx#=TFormedX()
			cy#=TFormedY()
			cz#=TFormedZ()
			CameraProject main_cam,cx,cy,cz
			vbx#=ProjectedX()	
			vby#=ProjectedY()
			
			; Triangle 1
			; Get the vectors for two edges of the triangle.
			Px# = Ax#-Bx#
			Py# = Ay#-By#
			Pz# = Az#-Bz#
			
			Qx# = Bx#-Cx#
			Qy# = By#-Cy#
			Qz# = Bz#-Cz#
			
			; Compute their cross product to get the face normal.
			FNx# = Py#*Qz# - Pz#*Qy#
			FNy# = Pz#*Qx# - Px#*Qz#
			FNz# = Px#*Qy# - Py#*Qx#
			
			; Compute the dot product of the face and camera normal.
			DP# = FNx#*CNx# + FNy#*CNy# + FNz#*CNz#
			
			; Is this face facing towards the camera, if so then draw its verts?
			If DP# < 0
				plotvertex(vax,vay,1)
				plotvertex(vbx,vby,1)
				plotvertex(vcx,vcy,1)
			EndIf	
		Next
	Next
End Function


fps=0
oldfps=0
fpstime=MilliSecs()+1000

While Not KeyDown(1)
	; fps stuff
	If MilliSecs()>fpstime Then
		fps=oldfps
		oldfps=0
		fpstime=MilliSecs()+1000
	Else
		oldfps=oldfps+1
	EndIf
	; main stuff
	If MouseDown(1) Then TurnEntity cube,0,0.4,0
	If MouseDown(2) Then TurnEntity cube,0.4,0,0
	If KeyDown(200) Then TranslateEntity cube,0,0.1,0
	If KeyDown(205) Then TranslateEntity cube,0.1,0,0
	If KeyDown(203) Then TranslateEntity cube,-0.1,0,0
	If KeyDown(208) Then TranslateEntity cube,0,-0.1,0
	RenderWorld()
	Hidden(cube)
	Color 255,255,255
	Text 10,10,"Surfaces : "+surfaces
	Text 10,25,"Triangles : "+tris
	Text 10,40,"Vertices : "+verts
	Text 930,10,"FPS : "+fps
	Text 10,750,"Left / Right Mouse Button to rotate, and cursors to move. "
	Flip 
	
Wend


ok, nearly got it :)

;setup graphics
Graphics3D 1024, 768, 0, 2
SetBuffer BackBuffer()

;enable wireframe	
WireFrame 1

;create camera	
Global main_cam = CreateCamera()
MoveEntity main_cam, 0, 0, -5

;create cube	
Global cube = CreateSphere(4)

Global surfaces,tris,verts

Function plotvertex(x,y,col)
	If col=1 Then 
		Color 0,255,0
	Else
		Color 255,0,0
	EndIf
	Oval x,y,3,3
End Function


Function Hidden(mesh)
	; Calculate the normal which indicates the direction the camera is pointing.	
	;count the surfaces of the mesh
	surfaces=CountSurfaces(mesh)
	
	;loop through all the surfaces
	For surfcount=1 To surfaces
		;count the number of triangles on the surfaces
		s=GetSurface(mesh,surfcount)
		tris=CountTriangles(s)
		verts=CountVertices(s)
		For t=0 To tris-1
			
			;get the corners of each triangle
			corner1=TriangleVertex(s,t,0)
			corner2=TriangleVertex(s,t,1)
			corner3=TriangleVertex(s,t,2)
			
			; get vertex information for corner 1
			TFormPoint VertexX(s,corner1),VertexY(s,corner1),VertexZ(s,corner1),mesh,0
			ax#=TFormedX()
			ay#=TFormedY()
			az#=TFormedZ()
			CameraProject main_cam,ax,ay,az
			vax#=ProjectedX()	
			vay#=ProjectedY()
			
			; get vertex information for corner 2
			TFormPoint VertexX(s,corner2),VertexY(s,corner2),VertexZ(s,corner2),mesh,0
			bx#=TFormedX()
			by#=TFormedY()
			bz#=TFormedZ()
			CameraProject main_cam,bx,by,bz
			vbx#=ProjectedX()	
			vby#=ProjectedY()
			
			; get vertex information for corner 3
			TFormPoint VertexX(s,corner3),VertexY(s,corner3),VertexZ(s,corner3),mesh,0
			cx#=TFormedX()
			cy#=TFormedY()
			cz#=TFormedZ()
			CameraProject main_cam,cx,cy,cz
			vbx#=ProjectedX()	
			vby#=ProjectedY()
			
			; find mid point of triangle and plot it
			mx# = (ax+bx+cx) / 3
			my# = (ay+by+cy) / 3
			mz# = (az+bz+cz) / 3
			
			; Triangle 1
			; Get the vectors for two edges of the triangle.
			Px# = Ax#-Bx#
			Py# = Ay#-By#
			Pz# = Az#-Bz#
			
			Qx# = Bx#-Cx#
			Qy# = By#-Cy#
			Qz# = Bz#-Cz#
			
			; Compute their cross product to get the face normal.
			FNx# = Py#*Qz# - Pz#*Qy#
			FNy# = Pz#*Qx# - Px#*Qz#
			FNz# = Px#*Qy# - Py#*Qx#
			
			PositionEntity campivot,EntityX(main_cam,1),EntityY(main_cam,1),EntityZ(main_cam,1)
			PositionEntity temppivot,mx,my,mz
			PointEntity campivot,temppivot
			TFormNormal 0,0,1,campivot,0
			cnx#=TFormedX()
			cny#=TFormedY()
			cnz#=TFormedZ()
			
			; Compute the dot product of the face and camera normal.
			DP# = FNx#*CNx# + FNy#*CNy# + FNz#*CNz#
			
			; Is this face facing towards the camera, if so then draw its verts?
			If DP# <0
				plotvertex(vax,vay,1)
				plotvertex(vbx,vby,1)
				plotvertex(vcx,vcy,1)
			EndIf	
		Next
	Next
End Function

Global campivot=CreatePivot()
Global temppivot=CreatePivot()
fps=0
oldfps=0
fpstime=MilliSecs()+1000

While Not KeyDown(1)
	; fps stuff
	If MilliSecs()>fpstime Then
		fps=oldfps
		oldfps=0
		fpstime=MilliSecs()+1000
	Else
		oldfps=oldfps+1
	EndIf
	; main stuff
	If MouseDown(1) Then TurnEntity cube,0,0.4,0
	If MouseDown(2) Then TurnEntity cube,0.4,0,0
	If KeyDown(200) Then TranslateEntity main_cam,0,0.1,0
	If KeyDown(205) Then TranslateEntity main_cam,0.1,0,0
	If KeyDown(203) Then TranslateEntity main_cam,-0.1,0,0
	If KeyDown(208) Then TranslateEntity main_cam,0,-0.1,0
	RenderWorld()
	Hidden(cube)
	Color 255,255,255
	Text 10,10,"Surfaces : "+surfaces
	Text 10,25,"Triangles : "+tris
	Text 10,40,"Vertices : "+verts
	Text 930,10,"FPS : "+fps
	Text 10,750,"Left / Right Mouse Button to rotate, and cursors to move. "
	Flip 
	
Wend


There are now only a couple of point which should be highlight, which aren't. Not sure why. Anyone got an ideas? Im hoping its something stupid that I have forgotten to do.

Cheers :)

Yay! I got it, and it was something stupid... I wasn't recording the projected vertices for the last corner of the triangle correctly. The code read :

CameraProject main_cam,cx,cy,cz
vbx#=ProjectedX()
vby#=ProjectedY()

It should be

CameraProject main_cam,cx,cy,cz
vcx#=ProjectedX()
vcy#=ProjectedY()

Doh! Anyway, this routine works now (fingers crossed). It simply shows all the vertexs which are visible to the camera.

Thanks to everyone for you help on this. Couldnt have done it without you. thats for sure.

Well done. Satisfying, isn't it? Sorry my last post didn't make much sense. I should have looked at your code more carefully. I unweld my mesh and use a vertex normal rather than a face normal in the dot product calculation because that way you don't have to do the cross product stuff that you do to find the face normal. But you seem to have figured out what I meant.

Now get those lines back in and you'll be ready to get cracking on occlusion and depth-sorting. :)