Archive for category Programming

Getting started on adding a Gui.

I started working on a native gui for my opengl engine. I first thought about using windows gui, but because I have made a lot of custom gui’s before, and I didn’t feel like messing around with the windows system, I decided to just write my own. I am at a stage where I got the windows drawing, and have made a couple of gadget drawing methods. Next up is writing the control code to get things interactive.

OpenGL Gui

OpenGL Gui

No Comments

Multitexturing problem was solved.

I had a problem with multi texturing which ment that if one entity used multi texturing, then all other entities suddenly also used it. It had to do with not disabling muti textures the right way. This has now been fixed, and its one less problem to think about :)

cubes with multi texture

cubes with multi texture

No Comments

Mesh load/save methods.

This morning I added load/save methods to the mesh type. And the heightmap test went from taking about 1500 millisecs to calculate, to taking 23 millisecs to load and ready. I also did a test with coloring the terrain from a heightmap color gradient. And it seems to be working great.

terrain colored by a heightmap gradient

terrain colored by a heightmap gradient

No Comments

Heightmap from image.

I got the first version of a heightmap from image method done. It will load an image, extract the height coordinates from one of the color channels, then create a mesh and recalculate normals for it. The normal calculations takes a very long time if the heightmap is large, so I will soon have to write my own load/save format for objects, so that I can pre-calculate everything, save it to a binary format, then when loading everything is already calculated, so it will be much faster.

I did not have any colormaps for a heightmap, so I just used a grayscale image.

heightmap

heightmap terrain

No Comments

Planequads added.

I have just added planequads, which is basically just a quad where the texture repeat can be defined at creation. This is useful for things like floors & walls. Nothing major, but it was a quick add while I was going through the mesh code, so I figured I might as well add it.

A plane made from a quad

A plane made from a quad

No Comments

Display Lists added

I had a little time, so I decided to add in display lists. After all its an easy addon, and it can speed up things in certain circumstances. I decided to add a static flag on the mesh type which will tell the engine if the mesh is dynamic or static, and if its static, that it should use a display list instead.

I made a method within the mesh type to produce a display list from its current arrays. This can also be used to convert loaded models since it does not care where the data came from.

I will tackle VBOs next, but not until after the code cleanup that I keep talking about, but haven’t gotten around to yet.

No Comments

.3ds model loader

To complete the model loader functions, here is the .3ds one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Function load3DSmodel:TMesh(file:String)
Local tmp:TMesh = TMesh.init()
Local stream:TStream, size:Int, id_node:String, size_node:Int, b:Byte, i:Int

stream = ReadStream(file)
If stream = Null Then Return tmp ' file could not be loaded, return false
size = FileSize(file)
DebugLog "Open "+file+" | Size:"+size

While Not Eof(stream)
id_node = Right(Upper(Hex(ReadShort(stream))),4)
size_node = ReadInt(stream)
DebugLog "Id="+id_node+"  size="+size_node

Select id_node
Case "4D4D" 'Main node
Case "3D3D" 'Config
Case "4000" ' OBJECT BLOCK
Repeat ' read the name of the object
b = ReadByte(stream)
If b = 0 Exit
tmp.name :+ Chr(b)
Until b = 0
DebugLog "Object name ="+tmp.name
Case "4100" ' MESH BLOCK
Case "4110" ' VERTICES LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
tmp.addVertex(ReadFloat(stream),ReadFloat(stream),ReadFloat(stream)) ' default colors and tex uv for now
Next
DebugLog "    Vertices: "+t
Case "4120" ' FACE LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
tmp.addFace(ReadShort(stream),ReadShort(stream),ReadShort(stream))
ReadShort(stream)
Next
DebugLog "    Faces: "+t
Case "4140" ' TEXTURE MAPPING COORDINATES LIST
Local t:Int = ReadShort(stream)
For i = 0 To t-1
tmp.addTexUV(ReadFloat(stream),ReadFloat(stream))
Next
DebugLog "    TexCoords: "+t
Default
' no ID was found that we need, so fastforward past this chunk
SeekStream(stream,StreamPos(stream)-6+size_node)
End Select
Wend
CloseStream stream
DebugLog "*** End of file ***"
End Function

No Comments

.ase model loader

I have posted a couple of other model loader functions on the dbf forum, so I thought that I might as well post them here as well to complete the trio.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Function loadASEmodel:TMesh(loadfile:String)
Local tmp:TMesh = TMesh.init()

Local v1:String, v2:String, v3:String
Local f1:Int, f2:Int, f3:Int, l:String
Local a:Int, b:Int, i:Int, vertices:Int, faces:Int

Local filein:TStream = ReadFile(loadfile)

Repeat
l = ReadLine(filein)
Until Instr( l, "*MESH_NUMVERTEX" )    ' find the point where the vetrice And face number is
l = Trim( l )                    ' remove all unnecessary spaces
l = Right( l, Len( l )-16 )            ' find the vertex number
vertices = Int( l )

l = ReadLine(filein)    ' read next line to get face number
l = Trim( l )                    ' remove all unnecessary spaces
l = Right( l, Len( l )-15 )            ' find the face number
faces = Int( l )

l = ReadLine(filein)    ' skip one line

For a = 1 To vertices
l = ReadLine( filein )
l = Trim( l )                ' remove all unnecessary spaces
l = Right( l, Len( l )-11 )        ' find the vertex data
l = Replace( l, " ", "," )
v1 = NthField( l, Chr(9), 2 )
v2 = NthField( l, Chr(9), 3 )
v3 = NthField( l, Chr(9), 4 )
tmp.addVertex(Float(v1),Float(v2),Float(v3))
Next

Repeat
l = ReadLine(filein)
Until Instr( l, "*MESH_FACE_LIST {" )    ' locate face list
For a = 1 To faces
l = ReadLine(filein)
l = Trim( l )                        ' remove all unnecessary spaces
l = Right( l, Len( l ) - 10 )
l = Left(l, 61)
f1 = Int(Mid(l, 13,5))
f2 = Int(Mid(l, 21,5))
f3 = Int(Mid(l, 29,5))
tmp.addFace(f1,f2,f3)
Next

Repeat
l = ReadLine(filein)
Until Instr( l, "*MESH_NORMALS {" )        ' find the point where the vetrice And face normals are
For a = 1 To faces
l = ReadLine(filein)
l = Trim( l )
l = Right( l, Len( l )-19)
If Left( l, 1 ) = Chr(9) Then l = Right( l, Len( l )-1 )
l = Replace( l, Chr(9), "," )
v1 = NthField( l, ",", 1 )
v2 = NthField( l, ",", 2 )
v3 = NthField( l, ",", 3 )
tmp.addFaceNormal(Float(v1),Float(v2),Float(v3))
For b = 1 To 3
l = ReadLine(filein)
l = Trim( l )
l = Right( l, Len( l$ )-20)
If Left( l, 1 ) = Chr(9) Then l = Right( l, Len( l )-1 )
l = Replace( l, Chr(9), "," )
v1 = NthField( l, ",", 1 )
v2 = NthField( l, ",", 2 )
v3 = NthField( l, ",", 3 )
tmp.addVertexNormal(Float(v1),Float(v2),Float(v3))
Next
Next

CloseFile(filein)
Print "V:"+vertices
Print "F:"+faces
Return tmp
End Function

' Given a String, a delimiter, And a n -- returns the nth Field
Function NthField:String(s:String, delim:String, n:Int)
Local o:Int = 1
For Local i:Int = 1 To n - 1
o = Instr(s, delim, o)
If o = 0 Then
Return ""
End If
o = o + 1
Next
Local p:Int = Instr(s, delim, o)
If p = 0 Then
Return Mid(s, o)
Else
Return Mid(s, o, p - o)
End If
End Function

No Comments

.obj model loader code

I am fairly certain that my code for loading .obj model files is working as its intended now, so I thought that I would post the code as it might be of use for someone else as well. It is ofcause written in BlitzMax like everything else I code, but since BlitzMax is somewhat easy to read and understand, I think that it should be trivial to convert the code into other languages as well.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
Function loadOBJmodel:TMesh(loadfile:String)
Local tmp:TMesh = TMesh.init()

Local sline:String, ck:String
Local v1:String, v2:String, v3:String
Local f1:String, f2:String, f3:String
Local vertices:Int, texUV:Int, vNormals:Int, faces:Int

Local filein:TStream = ReadFile(loadfile)

' locate vertex data
Repeat
sline = ReadLine(filein)
ck = Left( sline,2 )

Select ck
Case "v " ' vertex
v1 = NthField( sline," ",2 )
v2 = NthField( sline," ",3 )
v3 = NthField( sline," ",4 )
tmp.addVertex(Float(v1),Float(v2),Float(v3))
vertices:+ 1
Case "vt" ' vertex texture
v1 = NthField( sline," ",2 )
v2 = NthField( sline," ",3 )
tmp.addTexUV(Float(v1),Float(v2))
Print v1+","+v2
texUV :+ 1
Case "vn" ' vertex normal
v1 = NthField( sline," ",2 )
v2 = NthField( sline," ",3 )
v3 = NthField( sline," ",4 )
tmp.addVertexNormal(Float(v1),Float(v2),Float(v3))
vNormals :+ 1
Case "f " ' face
sline = Right(sline,Len(sline)-2) ' trim start of string
sline = Replace(sline," ","/") ' replace spaces
' vertex pointers
f1 = NthField( sline,"/",1 )
f2 = NthField( sline,"/",4 )
f3 = NthField( sline,"/",7 )
tmp.addFVpointer(Int(f1)-1,Int(f2)-1,Int(f3)-1)
' texture pointers
f1 = NthField( sline,"/",2 )
f2 = NthField( sline,"/",5 )
f3 = NthField( sline,"/",8 )
tmp.addFVTexUV(Int(f1)-1,Int(f2)-1,Int(f3)-1)
' normal pointers
f1 = NthField( sline,"/",3 )
f2 = NthField( sline,"/",6 )
f3 = NthField( sline,"/",9 )
tmp.addFVnormal(Int(f1)-1,Int(f2)-1,Int(f3)-1)
faces :+ 1
End Select

Until Eof(filein)
Return tmp
End Function

' Given a String, a delimiter, And a n -- returns the nth Field
Function NthField:String(s:String, delim:String, n:Int)
Local o:Int = 1
For Local i:Int = 1 To n - 1
o = Instr(s, delim, o)
If o = 0 Then
Return ""
End If
o = o + 1
Next
Local p:Int = Instr(s, delim, o)
If p = 0 Then
Return Mid(s, o)
Else
Return Mid(s, o, p - o)
End If
End Function

No Comments

The basic cube :)

My first project, now that I am programming again is a 3d opengl engine. So far I have gotten to the point where I can create objects and basic vertex lighting seems to be working.  I don’t have a lot to show so far since most work at the moment has to do with getting the foundation of the code working, such as loading setting up the window, creation of meshes, entities, lights and so on. Once I am confident that the basic stuff works, then I will expand with more effecient ways of doing the objects, such as displaylists, or VBOs (vertex buffer objects).

So for now the only thing I have to show is the very basic, but almost mandatory cube, textured ofcause :)

some boxes

some boxes

No Comments