![]() |
Tutorial 13: Memory usage and speed improvements In this tutorial we revisit the 3D data structures. Our goal is to improve memory usage, and increase the rendering speed of models. |
![]() |
![]() | ![]() |
![]() |
![]() |
Control | Name | DoubleBuffer | Left | Top | Maximize Button |
Window | SurfaceWindow | - | - | - | ON |
OpenGLSurface | Surface | ON | 0 | 0 | - |
![]() |
Surface.Render |
X3_Initialize X3_EnableLight OpenGL.GL_LIGHT0, new X3Core.X3Light(0, 0, 1) |
X3_SetPerspective Surface |
Name | Type | Default |
VIndex() | Integer | |
TIndex | Integer | -1 |
ParentModel | X3Model |
mParentModel = New WeakRef(value) |
return X3Model(mParentModel.Value) |
Name | Type |
Texture() | X3Texture |
Vertex() | X3Vector |
OGLName | Integer |
Sub AppendPolygon(poly As X3Core.X3Polygon) poly.ParentModel = me Polygon.Append poly End Sub |
Dim i, j As Integer Dim poly As X3Core.X3Polygon OpenGL.glPushMatrix X3_SetRotation(model.Rotation) if (model.OGLName > 0) then OpenGL.glCallList model.OGLName else model.OGLName = OpenGL.glGenLists(1) OpenGL.glNewList model.OGLName, OpenGL.GL_COMPILE OpenGL.glBegin OpenGL.GL_TRIANGLES for i = 0 to model.Polygon.Ubound poly = model.Polygon(i) OpenGL.glNormal3d poly.Normal.X, poly.Normal.Y, poly.Normal.Z if (poly.TIndex >= 0) and (poly.UVMap.Ubound >= poly.VIndex.Ubound) then OpenGL.glColor4d(1, 1, 1, 1) OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, model.Texture(poly.TIndex).OGLName) for j = 0 to poly.VIndex.Ubound OpenGL.glTexCoord2d poly.UVMap(j).U, poly.UVMap(j).V OpenGL.glVertex3d model.Vertex(poly.VIndex(j)).X, model.Vertex(poly.VIndex(j)).Y, model.Vertex(poly.VIndex(j)).Z next j else if poly.FillColor <> nil then OpenGL.glColor4d(poly.FillColor.Red, poly.FillColor.Green, poly.FillColor.Blue, poly.FillColor.Alpha) else OpenGL.glColor4d(1, 1, 1, 1) end if for j = 0 to 2 OpenGL.glVertex3d model.Vertex(poly.VIndex(j)).X, model.Vertex(poly.VIndex(j)).Y, model.Vertex(poly.VIndex(j)).Z next j end if next i OpenGL.glEnd OpenGL.glEndList OpenGL.glCallList model.OGLName end if OpenGL.glPopMatrix |
' replace ' v1X = Vertex(1).X - Vertex(0).X ' v1Y = Vertex(1).Y - Vertex(0).Y ' v1Z = Vertex(1).Z - Vertex(0).Z ' v2X = Vertex(2).X - Vertex(1).X ' v2Y = Vertex(2).Y - Vertex(1).Y ' v2Z = Vertex(2).Z - Vertex(1).Z ' with v1X = ParentModel.Vertex(VIndex(1)).X - ParentModel.Vertex(VIndex(0)).X v1Y = ParentModel.Vertex(VIndex(1)).Y - ParentModel.Vertex(VIndex(0)).Y v1Z = ParentModel.Vertex(VIndex(1)).Z - ParentModel.Vertex(VIndex(0)).Z v2X = ParentModel.Vertex(VIndex(2)).X - ParentModel.Vertex(VIndex(1)).X v2Y = ParentModel.Vertex(VIndex(2)).Y - ParentModel.Vertex(VIndex(1)).Y v2Z = ParentModel.Vertex(VIndex(2)).Z - ParentModel.Vertex(VIndex(1)).Z |
Name | Type |
Model | X3Core.X3Model |
MousePrevX | Integer |
MousePrevY | Integer |
Self.MouseCursor = System.Cursors.StandardPointer Model = X3Test_Cube6() |
OpenGL.glClearColor(0.7, 0.7, 0.7, 1) OpenGL.glClear(OpenGL.GL_COLOR_BUFFER_BIT + OpenGL.GL_DEPTH_BUFFER_BIT) OpenGL.glPushMatrix OpenGL.glTranslatef 0, 0, -5 X3_RenderModel Model OpenGL.glPopMatrix |
MousePrevX = x MousePrevY = y return true |
X3_RotateWithXY Model.Rotation, (y - MousePrevY), (x - MousePrevX) Surface.Render MousePrevX = x MousePrevY = y |
Get return X3Model(mParentModel.Value) End Get |
Set mParentModel = New WeakRef(value) End Set |
Since the actual vertex and texture data of the polygon is now stored in the X3Model class, we need a way to access that data. The computed ParentModel property serves that purpose. The problem is that we now have a reference that points to the parent model, and the parent model stores a reference back to the polygon, creating a circular reference. Circular references cause problems when objects are unloaded from memory. To circumvent memory problems the mParentModel property is of type WeakRef. Using a WeakRef object breaks the circular reference and ensures the correct unloading of polygon objects from memory. The set and get methods respectively cast X3Model objects to and from WeakRef instances. |
Sub AppendPolygon(poly As X3Core.X3Polygon) poly.ParentModel = me Polygon.Append poly End Sub |
AppendPolygon is a helper method to easily add new polygons to an existing model. It sets the ParentModel property of the polygon correctly and adds the polygon to the existing array of polygons. |
Dim i, j As Integer Dim poly As X3Core.X3Polygon OpenGL.glPushMatrix X3_SetRotation(model.Rotation) if (model.OGLName > 0) then OpenGL.glCallList model.OGLName else model.OGLName = OpenGL.glGenLists(1) OpenGL.glNewList model.OGLName, OpenGL.GL_COMPILE OpenGL.glBegin OpenGL.GL_TRIANGLES for i = 0 to model.Polygon.Ubound poly = model.Polygon(i) OpenGL.glNormal3d poly.Normal.X, poly.Normal.Y, poly.Normal.Z if (poly.TIndex >= 0) and (poly.UVMap.Ubound >= poly.VIndex.Ubound) then OpenGL.glColor4d(1, 1, 1, 1) OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, model.Texture(poly.TIndex).OGLName) for j = 0 to poly.VIndex.Ubound OpenGL.glTexCoord2d poly.UVMap(j).U, poly.UVMap(j).V OpenGL.glVertex3d model.Vertex(poly.VIndex(j)).X, model.Vertex(poly.VIndex(j)).Y, model.Vertex(poly.VIndex(j)).Z next j OpenGL.glBindTexture(OpenGL.GL_TEXTURE_2D, 0) ' unbind from the polygon's texture else if poly.FillColor <> nil then OpenGL.glColor4d(poly.FillColor.Red, poly.FillColor.Green, poly.FillColor.Blue, poly.FillColor.Alpha) else OpenGL.glColor4d(1, 1, 1, 1) end if for j = 0 to 2 OpenGL.glVertex3d model.Vertex(poly.VIndex(j)).X, model.Vertex(poly.VIndex(j)).Y, model.Vertex(poly.VIndex(j)).Z next j end if next i OpenGL.glEnd OpenGL.glEndList OpenGL.glCallList model.OGLName end if OpenGL.glPopMatrix |
In the new render method, notice how the arrays model.Texture and model.Vertex are now used with the indexes poly.TIndex and poly.VIndex respectively. Since all the vertex and texture data are now stored in the model, we need to retrieve the respective instances from the arrays in the model. |
v1X = ParentModel.Vertex(VIndex(1)).X - ParentModel.Vertex(VIndex(0)).X v1Y = ParentModel.Vertex(VIndex(1)).Y - ParentModel.Vertex(VIndex(0)).Y v1Z = ParentModel.Vertex(VIndex(1)).Z - ParentModel.Vertex(VIndex(0)).Z v2X = ParentModel.Vertex(VIndex(2)).X - ParentModel.Vertex(VIndex(1)).X v2Y = ParentModel.Vertex(VIndex(2)).Y - ParentModel.Vertex(VIndex(1)).Y v2Z = ParentModel.Vertex(VIndex(2)).Z - ParentModel.Vertex(VIndex(1)).Z |
Similar to the render method, the CalculateNormal method had to be changed to access vertex information in the parent model. |
![]() |
![]() |