Lighting double sided surface

Blitz3D Forums/Blitz3D Beginners Area/Lighting double sided surface

Hi peeps - "puki" here.

I've been messing about with double-sided surfaces. Lighting the thing as a single surface (regardless of which one) is okay. When I display both surfaces together, they won't light.

What am I missing?

Graphics3D 640,480,16,2 
SetBuffer BackBuffer() 

cam = CreateCamera() 
MoveEntity cam, 0,0,-12

light=CreateLight(2)
LightColor light,0,0,255
MoveEntity light,1000,1000,-1000

light2=CreateLight(2)
LightColor light2,255,0,0
MoveEntity light2,-1000,1000,-1000

mesh = CreateMesh() 

surface=CreateSurface(mesh)

triangle1 = CreateSurface(mesh)
v1 = AddVertex (triangle1,-2,-2,-2) 
v2 = AddVertex (triangle1, 0, 2, -2) 
v3 = AddVertex (triangle1, 2,-2,-2)
tri = AddTriangle (triangle1,v1,v2,v3)
tri = AddTriangle (triangle1,v3,v2,v1)

UpdateNormals mesh

While Not KeyHit(1)
TurnEntity mesh,0,1,0
RenderWorld
Flip 
Wend
End


Please help. I did try faffing about with it.

Thanks in advance.

Hi Puki, I had a look at your code and messed about with it, I'm not sure if this gives what you want but it displays the lighting:

Graphics3D 640,480,16,2
SetBuffer BackBuffer()

cam = CreateCamera()
MoveEntity cam, 0,0,-12

light=CreateLight(2)
LightColor light,0,0,255
MoveEntity light,1000,1000,-1000

light2=CreateLight(2)
LightColor light2,255,0,0
MoveEntity light2,-1000,1000,-1000

mesh = CreateMesh()

surface=CreateSurface(mesh)

triangle1 = CreateSurface(mesh)
v1 = AddVertex (triangle1,-2,-2,-2)
v2 = AddVertex (triangle1, 0, 2, -2)
v3 = AddVertex (triangle1, 2,-2,-2)
tri = AddTriangle (triangle1,v1,v2,v3)
tri = AddTriangle (triangle1,v3,v2,v1)

UpdateNormals mesh
VertexNormal triangle1, v1,255,255,255
VertexNormal triangle1, v2,255,255,255
VertexNormal triangle1, v3,255,255,255

While Not KeyHit(1)
TurnEntity mesh,0,1,0

RenderWorld
Flip
Wend
End


Hope this help you a little anyhow. if not i'll look into it more for you.

Nice one "Goober"! On an initial quick look that is what I want. I'll have to check it over.

When I was faffing about with it - I had tried loading the 'VertexNormals' with the 3D space coordinates - coz that's how it appears to me in the printed manual (which indicates surface,index,nx#,ny#,nz#). The manual seems to refer to coordinates.

Hi Puki, Just made a slight update to the code which seems to work fine, here it is:

Graphics3D 640,480,16,2
SetBuffer BackBuffer()

cam = CreateCamera()
MoveEntity cam, 0,0,-12

light=CreateLight(2)
LightColor light,0,0,255
MoveEntity light,1000,1000,-1000

light2=CreateLight(2)
LightColor light2,255,0,0
MoveEntity light2,-1000,1000,-1000

mesh = CreateMesh()

surface=CreateSurface(mesh)

triangle1 = CreateSurface(mesh)
sv1 = AddVertex (surface,-2,-2,-2)
sv2 = AddVertex (surface, 0, 2, -2)
sv3 = AddVertex (surface, 2,-2,-2)
tv1 = AddVertex (triangle1,-2,-2,-2)
tv2 = AddVertex (triangle1, 0, 2, -2)
tv3 = AddVertex (triangle1, 2,-2,-2)
tri = AddTriangle (triangle1,tv1,tv2,tv3)
tri = AddTriangle (surface,sv3,sv2,sv1)

UpdateNormals mesh

While Not KeyHit(1)
TurnEntity mesh,0,1,0
RenderWorld
Flip
Wend
End

Has abit more coding but the results come out to be better.

Puki, any reason you want to put each triangle in a separate surface?

Thanks for the second bit of code "Goober". Will take a look at it.

"big10p" - the truthfull answer is 'I don't know'. Is there a better way? I'm still initially going to do it the way I am doing it - I am currently collecting different methods and documenting them.

The object above will be a cone/pyramid type object - there will be another 3 sides like the one above - the 'peaks' of the cones will be moved to meet each other at the centre (to form the pyramid). There will be no base - so you will see inside the pyramid/cone. So I have to double-side the surfaces.

This is all part of me wanting to finally resolve my virtually zero (because I've never used it) knowledge of the Blitz3D 'Surface' stuff.

If you want your triangles to be double sided, you can use 'EntityFX entity,16' to disable backface culling. However, this may not be what you want because the 'backface' triangle will be lit using the same normals as the front face triangle, since it's using the same vertices.

Another way is to simply build a second triangle using the same verts we used to build the first, but we 'wind' them in the opposite direction, in order to make the backface triangle face the opposite direction. Something like this:
Graphics3D 640,480,16,2 
SetBuffer BackBuffer() 

cam = CreateCamera() 
MoveEntity cam, 0,0,-12 

light=CreateLight(2) 
LightColor light,0,0,255 
MoveEntity light,1000,1000,-1000 

light2=CreateLight(2) 
LightColor light2,255,0,0 
MoveEntity light2,-1000,1000,-1000 

mesh = CreateMesh() 
surface = CreateSurface(mesh) 

v1 = AddVertex (surface,-2,-2,-2) 
v2 = AddVertex (surface, 0, 2, -2) 
v3 = AddVertex (surface, 2,-2,-2) 
tri1 = AddTriangle (surface,v1,v2,v3) ;Wind clockwise to face camera
tri2 = AddTriangle (surface,v3,v2,v1) ;Wind anti-clockwise to face away from camera
VertexNormal surface,v1,0,0,-1
VertexNormal surface,v2,0,0,-1
VertexNormal surface,v3,0,0,-1

While Not KeyHit(1) 
TurnEntity mesh,0,1,0 
RenderWorld 
Flip 
Wend 
End 

Again, however, the second triangle is lit using the first triangle's normals since they still share the same verts. Also note that I've set the vertex normals by hand as using UpdateNormals here won't work due to the way it tries to smooth normals. Arg! I think this might be getting a bit confusing, but I'll carry on anyway... :)

Finally, you can build the two triangles by giving each it's own set of 3 verts. This means we can then light each triangle correctly due to the fact that each has it's own set of vertex normals:
Graphics3D 640,480,16,2 
SetBuffer BackBuffer() 

cam = CreateCamera() 
MoveEntity cam, 0,0,-12 

light=CreateLight(2) 
LightColor light,0,0,255 
MoveEntity light,1000,1000,-1000 

light2=CreateLight(2) 
LightColor light2,255,0,0 
MoveEntity light2,-1000,1000,-1000 

mesh = CreateMesh() 
surface = CreateSurface(mesh) 

; First triangle.
v1 = AddVertex (surface,-2,-2,-2) 
v2 = AddVertex (surface, 0, 2, -2) 
v3 = AddVertex (surface, 2,-2,-2) 
tri1 = AddTriangle (surface,v1,v2,v3) ;Wind clockwise to face camera
VertexNormal surface,v1,0,0,-1
VertexNormal surface,v2,0,0,-1
VertexNormal surface,v3,0,0,-1

; Second triangle.
v4 = AddVertex (surface,-2,-2,-2) 
v5 = AddVertex (surface, 0, 2, -2) 
v6 = AddVertex (surface, 2,-2,-2) 
tri2 = AddTriangle (surface,v6,v5,v4) ;Wind anti-clockwise to face away from camera
VertexNormal surface,v4,0,0,1
VertexNormal surface,v5,0,0,1
VertexNormal surface,v6,0,0,1

While Not KeyHit(1) 
TurnEntity mesh,0,1,0 
RenderWorld 
Flip 
Wend 
End 


You might find this little include library of mine useful while checking this stuff out. It draws the normals so you can actually see where they're pointing:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1085
It's very easy to include. See comments at top of code for details.

Hey, nice "big10p" - I will read through this - I'll mention you and "Goober" in my worklog. I'm not doing it for a couple of days though. However, I will take a look at this post now - thanks very much.

The various ways of achieving something is very interesting - I'm enjoying faffing about with this stuff.

Edit:
You are using the 'VertexNormal' more the way I was expecting - "Goober" threw me a bit with his 'RGB-looking' stuff. Still, I hadn't nailed the use of the 'VertexNormal' commands - they are not exactly well documented.

"Goober" threw me a bit with his 'RGB-looking' stuff.


Er, yeah, I'm not too sure what Goober was attempting with that 'VertexNormal triangle1,v1,255,255,255' malarkey. :)

Although, with regard to "big10p's" second piece of code - are the 'VertexNormal' commands required? What is their purpose?

I can replicate without using them - but am I missing something here?
Graphics3D 640,480,16,2
SetBuffer BackBuffer()

cam = CreateCamera()
MoveEntity cam, 0,0,-12

light=CreateLight(2)
LightColor light,0,0,255
MoveEntity light,1000,1000,-1000

light2=CreateLight(2)
LightColor light2,255,0,0
MoveEntity light2,-1000,1000,-1000

mesh = CreateMesh()

triangle1 = CreateSurface(mesh)
v1 = AddVertex (triangle1,-2,-2,-2)
v2 = AddVertex (triangle1, 0, 2,-2)
v3 = AddVertex (triangle1, 2,-2,-2)
tri = AddTriangle (triangle1,v1,v2,v3)

triangle2 = CreateSurface(mesh)
v1 = AddVertex (triangle2,-2,-2,-2)
v2 = AddVertex (triangle2, 0, 2,-2)
v3 = AddVertex (triangle2, 2,-2,-2)
tri = AddTriangle (triangle2,v3,v2,v1)

UpdateNormals mesh

While Not KeyHit(1)
TurnEntity mesh,0,1,0 
RenderWorld
Flip
Wend
End


Sorry to be a pain.

No, that's fine. You can use UpdateNormals instead of the VertexNormal commands if you want. I was simply using them to show more clearly the way the normals should be set, and to be consistent with the previous example which won't work if you use UpdateNormals.

[edit] Er, actually, just remembered that my example won't work with UpdateNormals. :) This is because of the smoothing error I mentioned. Yours works with UpdateNormals because you have put the 2 triangles into different surfaces so UpdateNormals doesn't try and smooth the normals between them.

Aha, thanks "big10p".

Wait Puki, come back!!! I've just edited my post. :)

Okay, I'll take a look.

Edit:

Thanks "big10p".