Some tips for SetMeshData() and OGRE
Posted: Fri Jul 02, 2004 12:21 pm
The following information is a summary of different individual posting
and my own experiences. Special thanks goes to Danilo!
Hope that helps someone to get light into the dark mysterious OGRE/PB world ;-)
And here a working example for demonstration:
and my own experiences. Special thanks goes to Danilo!
Hope that helps someone to get light into the dark mysterious OGRE/PB world ;-)
Code: Select all
SetMeshData () – Tutorial ( DiGe 06/2994 German Forum )
http://robsite.de/php/pureboard/viewtopic.php?t=4924
------------------------------
Technical background
------------------------------
Maxium Vertices pro Mesh: 65.000
127 x 127 = 16.129
16.129 * 4 corners = 64.516 vertices ( Posting from Danilo )
SetMeshData () copies the Data and + Structures to OGRE’s memory. You can do this several times for the same mesh and the entity will changed ... useful for animations and deformations.
------------------------------
Vertices ( Corner points )
------------------------------
Vertices define points in a 3d area and contents 3 floats ( x.f; y.f; z.f )
This is the first step to create a 3d model.
------------------------------
Faces ( areas )
------------------------------
The second step is connect the vertices to faces. PureBasic only supports triangular faces. ( other faces could be: lines, polygons, quads ... )
The sequence (direction) of definition will specify the back or front of each face. It is necessary to work clockwise or against the clock. If you want to have both sides of a face visible, you’ll have to define 2 faces in clockwise and opposite direction.
1 Faces contains 3 words ( v1.w, v2.w, v3.w )
------------------------------
Quad faces
------------------------------
As I wrote already, PB supports only triangular faces. So if you need lines or quads you’ll have to build it from two triangles.
(-1,1,0) (1,1,0)
Vertex 3 Vertex 2
O-------O
| /|
| II / |
| / |
| x |
| / |
| / I |
|/ |
O-------O
Vertex 0 Vertex 1
(-1,-1,0) (1,-1,0)
x = center (0,0,0) I = 1. Triangle II = 2. Triangle
4 Vertics: 0, 1, 2, 3 and two triangular faces: I (2, 1, 0), II(0, 3, 2)
------------------------------
Textures UV
------------------------------
The Texturcoordinates for each face are 8 floats ( 4 x 2 ), witch define a rectangle inside the texture-bitmap.
1 +
|
|
0.5 + [Textur]
|
|
+-------+-------+
0 0.5 1
If you want to use the whole bitmap: 0.0,0.0, 1.0,0.0, 1.0,1.0, 0.0,1.0
Values > 1 causes that the texture is represented several times.
------------------------------
Meshes
------------------------------
A mesh contains vertices, faces, colors, texturecoordinates and normals.
Meshes will filled up with SetMeshData (). The following overview shows the needed data, types und values:
#PB_Mesh_Vertices 1 Vertex = 3 Floats x, y, z
#PB_Mesh_Triangles 1 Face = 3 Words 0-2-1
#PB_Mesh_UVCoordinates 1 UV = 2 Floats x, y 1 Face -> 8 Floats
#PB_Mesh_Normals 1 Nrm = 3 Floats x, y, z 1 Face -> 9 Floats
#PB_Mesh_Colors 1 Col = 3 Floats x, y, z
From my point of view it is useful to create the biggest meshes first. Another speed improvement is to divide big meshes into smaller parts. It seems that OGRE can calculate it better.
------------------------------
Enitiys
------------------------------
You can add materials to meshes -> called entity. The pivot point ( for rotation etc. ) is always 0, 0, 0. So if you want to rotated an entity around itself you have to create it at the coordinates origin and the center of your mesh must be located at 0, 0, 0. And then move the object to its target position.
If you create Meshes with PB-Arrays, remind that Dim(10) means 11 Elements!
------------------------------
OGRE-PB Coordinate-System
------------------------------
+Y
|
|
|
+------ +X
/
/
/
+Z
------------------------------
Light and Normal-Vectors
------------------------------
To render lights, shadows and reflections its necessary to calculate the normal vector from each face and all connected vertices.
1 Normal-Vector needs 3 floats.
plan view: side view:
+----------------X +----------------X
| 2 | 0 1
| + | +----+
| | \ | |
| | \ | |
| | S + 1 | N ( 0, 1, 0 )
| | / |
| | / |
| + |
| 0 |
Z Y
We have only triangular faces ... so it is very easy to calculate the normals:
Norm_x1 = (y1 - y2) * (z2 - z3) - (z1 - z2) * (y2 - y3)
Norm_y1 = (z1 - z2) * (x2 - x3) - (x1 - x2) * (z2 - z3)
Norm_z1 = (x1 - x2) * (y2 - y3) - (y1 - y2) * (x2 - x3)
Length = Sqr( Norm_x1² + Norm_y1² + Norm_z1² )
If Length = 0 : Length = 1 : EndIf
Norm_x1 / Length
Norm_y1 / Length
Norm_z1 / Length
And here a working example for demonstration:
Code: Select all
; SetMeshData / Normals Example by DiGe 07/2004
Structure _Vertices
x1.f ; Vertex 1
y1.f
z1.f
x2.f ; Vertex 2
y2.f
z2.f
x3.f ; Vertex 3
y3.f
z3.f
EndStructure
Structure _Triangles
TriangleF_a.w
TriangleF_b.w
TriangleF_c.w
TriangleB_a.w
TriangleB_b.w
TriangleB_c.w
EndStructure
Structure _TextureCoordinates
Vertex1_a.f ; Vertex 1
Vertex1_b.f
Vertex2_a.f ; Vertex 2
Vertex2_b.f
Vertex3_a.f ; Vertex 3
Vertex3_b.f
Vertex4_a.f ; Vertex 4
Vertex4_b.f
EndStructure
Structure _Normals
x1.f ; Normals Vertex 1
y1.f
z1.f
x2.f ; Normals Vertex 2
y2.f
z2.f
x3.f ; Normals Vertex 3
y3.f
z3.f
EndStructure
Structure _Colors
; Farben für jede Seite des Dreieckes
col_a.l
col_b.l
col_c.l
EndStructure
Procedure GetNormals ( *Vertics, *Normals, Negativ.b )
*TEMP._Vertices = *Vertics
*NRML._Normals = *Normals
If Negativ
*NRML\x1 = ((*TEMP\y3 - *TEMP\y2) * (*TEMP\z2 - *TEMP\z1)) - ((*TEMP\z3 - *TEMP\z2) * (*TEMP\y2 - *TEMP\y1))
*NRML\y1 = ((*TEMP\z3 - *TEMP\z2) * (*TEMP\x2 - *TEMP\x1)) - ((*TEMP\x3 - *TEMP\x2) * (*TEMP\z2 - *TEMP\z1))
*NRML\z1 = ((*TEMP\x3 - *TEMP\x2) * (*TEMP\y2 - *TEMP\y1)) - ((*TEMP\y3 - *TEMP\y2) * (*TEMP\x2 - *TEMP\x1))
Else
*NRML\x1 = ((*TEMP\y1 - *TEMP\y2) * (*TEMP\z2 - *TEMP\z3)) - ((*TEMP\z1 - *TEMP\z2) * (*TEMP\y2 - *TEMP\y3))
*NRML\y1 = ((*TEMP\z1 - *TEMP\z2) * (*TEMP\x2 - *TEMP\x3)) - ((*TEMP\x1 - *TEMP\x2) * (*TEMP\z2 - *TEMP\z3))
*NRML\z1 = ((*TEMP\x1 - *TEMP\x2) * (*TEMP\y2 - *TEMP\y3)) - ((*TEMP\y1 - *TEMP\y2) * (*TEMP\x2 - *TEMP\x3))
EndIf
Length.f = Sqr( *NRML\x1 * *NRML\x1 + *NRML\y1 * *NRML\y1 + *NRML\z1 * *NRML\z1)
If Length = 0 : Length = 1 : EndIf
*NRML\x1 / Length
*NRML\y1 / Length
*NRML\z1 / Length
*NRML\x2 = *NRML\x1
*NRML\y2 = *NRML\y1
*NRML\z2 = *NRML\z1
*NRML\x3 = *NRML\x1
*NRML\y3 = *NRML\y1
*NRML\z3 = *NRML\z1
EndProcedure
Procedure InitGameTimer()
; initialize highres timing function TimeGetTime_()
Shared _GT_DevCaps.TIMECAPS
timeGetDevCaps_(_GT_DevCaps,SizeOf(TIMECAPS))
timeBeginPeriod_(_GT_DevCaps\wPeriodMin)
EndProcedure
Procedure StopGameTimer()
; de-initialize highres timing function TimeGetTime_()
Shared _GT_DevCaps.TIMECAPS
timeEndPeriod_(_GT_DevCaps\wPeriodMin)
EndProcedure
Procedure ShowError(error$)
#ERR_1 = "Cant create "
#ERR_2 = " !"+Chr(13)+"(out of memory?)"
MessageRequester("ERROR",#ERR_1+error$+#ERR_2,#MB_ICONERROR)
End
EndProcedure
;{ Initialisierung
If InitEngine3D() And InitSprite() And InitKeyboard() And InitMouse()
#LOOPTIME = 1000/60 ; 60 Frames in 1000ms (1second)
SmallFont = LoadFont(0,"Tahoma", 10, #PB_Font_Bold)
If OpenWindow(0, 0, 0, 800, 600, #PB_Window_SystemMenu|#PB_Window_ScreenCentered, "OGRE Rocks")
If OpenWindowedScreen(WindowID(),0, 0, 800, 600, 0, 0, 0)=0
MessageRequester("ERROR","Cant open DirectX screen !",#MB_ICONERROR):End
EndIf
EndIf
Dim TextureCoordinates._TextureCoordinates (3)
Dim Triangles._Triangles(3)
Dim Vertices._Vertices (3)
Dim Normals._Normals (3)
; Pyramide
Restore Pyramide_Vertics
For a = 0 To 3
Read Vertices(a)\x1
Read Vertices(a)\y1
Read Vertices(a)\z1
Read Vertices(a)\x2
Read Vertices(a)\y2
Read Vertices(a)\z2
Read Vertices(a)\x3
Read Vertices(a)\y3
Read Vertices(a)\z3
Vertices(a)\x1 - 1
Vertices(a)\x2 - 1
Vertices(a)\x3 - 1
Vertices(a)\z1 - 1
Vertices(a)\z2 - 1
Vertices(a)\z3 - 1
GetNormals(@Vertices(a), @Normals(a), 0 )
Next
Restore Pyramide_Faces
For a = 0 To 3
Read Triangles(a)\TriangleF_a
Read Triangles(a)\TriangleF_b
Read Triangles(a)\TriangleF_c
Read Triangles(a)\TriangleB_a
Read Triangles(a)\TriangleB_b
Read Triangles(a)\TriangleB_c
Next
For a = 0 To 3
Restore Pyramide_UV
Read TextureCoordinates(a)\Vertex1_a
Read TextureCoordinates(a)\Vertex1_b
Read TextureCoordinates(a)\Vertex2_a
Read TextureCoordinates(a)\Vertex2_b
Read TextureCoordinates(a)\Vertex3_a
Read TextureCoordinates(a)\Vertex3_b
Read TextureCoordinates(a)\Vertex4_a
Read TextureCoordinates(a)\Vertex4_b
Next
If CreateMesh(0)
SetMeshData( 0, #PB_Mesh_Vertices ,@Vertices() , 12 * 3 )
SetMeshData( 0, #PB_Mesh_Triangles ,@Triangles() , 4 * 2 )
SetMeshData( 0, #PB_Mesh_UVCoordinates,@TextureCoordinates(), 4 * 2 )
SetMeshData( 0, #PB_Mesh_Normals ,@Normals() , 4 * 3 )
If CreateTexture(0, 64, 64)
If StartDrawing(TextureOutput(0))
Box(0,0,64,64,$FF0000)
Box(1,1,62,62,$00FFFF)
FrontColor( 0, 0, 0 )
DrawingMode(1)
Locate ( 3, 5 ) : DrawText( "LiGHT" )
StopDrawing()
EndIf
CreateMaterial(0,TextureID(0))
If CreateEntity(0, MeshID(0),MaterialID(0))
MaterialShadingMode (0, #PB_Material_Flat )
MaterialDiffuseColor (0, RGB($FF,$FF,$FF))
MaterialAmbientColor (0, RGB($90,$90,$90))
MaterialSpecularColor(0, RGB($F0,$F0,$F0))
MaterialFilteringMode(0, #PB_Material_Trilinear )
EndIf
CopyEntity ( 0, 1 ) : ResizeEntity( 1, 0.5, 0.5, 0.5 )
CopyEntity ( 1, 2 ) : ResizeEntity( 2, 0.25, 0.25, 0.25 )
CopyEntity ( 1, 3 ) : ResizeEntity( 3, 0.75, 0.75, 0.75 )
CopyEntity ( 1, 4 ) : ResizeEntity( 4, 1.25, 1.25, 1.25 )
EntityLocate( 1, -2, 0, 2 )
EntityLocate( 2, 2, 0, 2 )
EntityLocate( 3, -2, 0, -2 )
EntityLocate( 4, 2, 0, -2 )
EndIf
EndIf
CreateCamera (0, 0, 0, 100, 100)
CameraRange (0, 0.1, 400 )
CameraLookAt (0, 0, 0, 0 )
CameraLocate (0, 0, 1, 5 )
If CreateLight(1,RGB($FF,$FF,$FF))=0:ShowError("light"):Else:LightLocate(1, 0, 1, 2):EndIf
; start game timer
InitGameTimer()
LoopTimer = timeGetTime_()
;}
;{ Schleife, Abfrage
Repeat
If fullscreen
While ( timeGetTime_()-LoopTimer )<#LOOPTIME : Delay(1) : Wend
LoopTimer = timeGetTime_()
Else
Repeat
Event=WindowEvent()
If Event=#PB_Event_CloseWindow
Quit = #True
ElseIf Event=0
While ( timeGetTime_()-LoopTimer )<#LOOPTIME : Delay(1) : Wend
LoopTimer = timeGetTime_()
EndIf
Until Event=0
EndIf
; check keys
If ExamineKeyboard()
If KeyboardPushed(#PB_Key_Right)
MoveCamera(0, 1,0,0):EndIf
If KeyboardPushed(#PB_Key_Left)
MoveCamera(0,-1,0,0):EndIf
If KeyboardPushed(#PB_Key_Up)
MoveCamera(0,0,0,-1):EndIf
If KeyboardPushed(#PB_Key_Down)
MoveCamera(0,0,0, 1):EndIf
If KeyboardPushed(#PB_Key_F3)
FOV - 1 : If FOV < 40:FOV=40:EndIf
CameraFOV(0,FOV):EndIf
If KeyboardPushed(#PB_Key_F4)
FOV + 1 : If FOV > 120:FOV=120:EndIf
CameraFOV(0,FOV):EndIf
If keypressed=0
If KeyboardPushed(#PB_Key_F1)
HideText!1 : keypressed=20 : EndIf
If KeyboardPushed(#PB_Key_F2)
RenderMode+1 : If RenderMode=3:RenderMode=0:EndIf
CameraRenderMode(0,RenderMode):keypressed=20:EndIf
If KeyboardPushed(#PB_Key_F5)
ScaleEntity(enti, 1.1, 1.1, 1.1)
EndIf
Else
keypressed-1
EndIf
EndIf
; mouse freelook
If ExamineMouse()
RotateCamera(0,-MouseDeltaX(),-MouseDeltaY(),0)
EndIf
RotateEntity( 0, 1, 0, 0 )
; info text
If HideText=0
If StartDrawing(ScreenOutput())
DrawingMode(1):FrontColor($40,$FF,$00):DrawingFont(SmallFont)
Locate( 15,15):DrawText("F2 : RenderMode")
Locate( 15,30):DrawText("Count : "+Str( CountRenderedTriangles() ))
Locate( 15,45):DrawText("FPS : "+Str( Engine3DFrameRate(#PB_Engine3D_Current)))
Locate(250,15):DrawText("CameraX: "+RSet(StrF(CameraX(0),2),4,"0"))
Locate(250,30):DrawText("CameraY: "+RSet(StrF(CameraY(0),2),4,"0"))
Locate(250,45):DrawText("CameraZ: "+RSet(StrF(CameraZ(0),2),4,"0"))
StopDrawing()
EndIf
EndIf
FlipBuffers()
RenderWorld()
Until KeyboardPushed(#PB_Key_Escape) Or Quit
StopGameTimer()
Else
MessageRequester("Error", "Cant init DirectX 3D Engine",0)
EndIf
;}
End
;{ Daten-Sektion
DataSection
Pyramide_Vertics:
Data.f 0,0,0 ; Vertex0
Data.f 1,2,1 ; Vertex1
Data.f 2,0,0 ; Vertex2
Data.f 2,0,0 ; Vertex3
Data.f 1,2,1 ; Vertex4
Data.f 2,0,2 ; Vertex5
Data.f 2,0,2 ; Vertex6
Data.f 1,2,1 ; Vertex7
Data.f 0,0,2 ; Vertex8
Data.f 0,0,2 ; Vertex9
Data.f 1,2,1 ; Vertex10
Data.f 0,0,0 ; Vertex11
Pyramide_Faces:
Data.w 0, 1, 2 ; Face 1
Data.w 0, 2, 1 ; Face 2
Data.w 3, 4, 5 ; Face 3
Data.w 3, 5, 4 ; Face 4
Data.w 6, 7, 8 ; Face 5
Data.w 6, 8, 7 ; Face 6
Data.w 9, 10, 11 ; Face 7
Data.w 9, 11, 10 ; Face 8
Pyramide_UV:
Data.f 0.0, 0.0
Data.f 0.0, 3.0
Data.f 3.0, 3.0
Data.f 3.0, 0.0
EndDataSection
;}