added OBJ loader

3d_asteroids
martin 2011-06-13 19:05:04 +02:00
parent 509e569c64
commit 5c58595f35
14 changed files with 2615 additions and 5 deletions

View File

@ -17,6 +17,8 @@
#include "AsteroidsEvents.h" #include "AsteroidsEvents.h"
#include "RocketEntity.h" #include "RocketEntity.h"
#include "OBJModel.h"
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
@ -77,6 +79,8 @@ int View::OnInit (int argc, char* argv[]) {
mShipPartsSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/ship_parts.png")); mShipPartsSprite.LoadFromPNG (Engine::GetResourceFullPath("/data/textures/ship_parts.png"));
mShipPartsSprite.SetSubSpriteCount (10); mShipPartsSprite.SetSubSpriteCount (10);
mAsteroidModel = LoadOBJModel (Engine::GetResourceFullPath("/data/models/asteroid/asteroid_model.obj"));
Engine::RegisterListener (this, EventAccelerateStart); Engine::RegisterListener (this, EventAccelerateStart);
Engine::RegisterListener (this, EventAccelerateStop); Engine::RegisterListener (this, EventAccelerateStop);
Engine::RegisterListener (this, EventShipExplode); Engine::RegisterListener (this, EventShipExplode);
@ -265,6 +269,20 @@ void View::Draw() {
DrawWorld (); DrawWorld ();
} }
glPushMatrix();
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glRotatef (90, 1., 0., 0.);
// glScalef (10., 10., 10.);
DrawOBJModel (mAsteroidModel);
glDisable (GL_LIGHT0);
glDisable (GL_LIGHTING);
glPopMatrix();
DrawUi (); DrawUi ();
// Perform post-Draw actions // Perform post-Draw actions

View File

@ -139,7 +139,9 @@ class View : public Engine::ViewBase {
Engine::Sprite mShipSprite; Engine::Sprite mShipSprite;
Engine::Sprite mShipThrustSprite; Engine::Sprite mShipThrustSprite;
Engine::Sprite mShipPartsSprite; Engine::Sprite mShipPartsSprite;
Engine::OBJModelPtr mAsteroidModel;
float screen_left; float screen_left;
float screen_right; float screen_right;
float screen_top; float screen_top;

Binary file not shown.

View File

@ -0,0 +1,12 @@
# Material Count: 1
newmtl asteroid_asteroid_texture_full
Ns 37.254902
Ka 0.069978 0.069978 0.069978
Kd 0.640000 0.640000 0.640000
Ks 0.600000 0.600000 0.600000
Ni 1.000000
d 1.000000
illum 2
#map_Kd asteroid_texture_full.png
map_Kd asteroid_texture_solid.png
map_bump asteroid_normals_uv.png

View File

@ -0,0 +1,377 @@
# Blender v2.55 (sub 0) OBJ File: 'asteroidfull.blend'
# www.blender.org
mtllib asteroid_model.mtl
o Asteroid_Icosphere
v -1.783176 3.157423 -2.187264
v -0.623617 3.419646 -2.279537
v -4.136988 -1.528819 1.175240
v 1.622063 -3.012534 -1.107284
v -2.764359 2.370088 -1.340167
v 0.011242 3.019686 2.574161
v -3.271742 2.084863 -0.140242
v -1.924542 3.110817 -0.535404
v -3.428460 0.084386 1.434556
v -1.127657 -3.141940 1.362692
v -3.526288 1.205355 -1.042213
v -3.326865 -1.851120 -2.151031
v 3.315345 2.078610 0.192092
v 1.677497 2.826964 1.998395
v -3.488970 -0.830072 -2.166265
v 2.454325 -1.478905 -2.751490
v 0.892076 -2.198434 3.836253
v -0.529430 -1.099092 -4.090514
v -1.530568 2.367935 2.067323
v -0.082300 -2.695156 3.227212
v -4.186931 -0.713751 0.795901
v -3.847708 0.187925 -0.543515
v 2.213019 2.683415 -2.315270
v -3.271944 1.840718 0.932036
v 0.112475 -1.622629 4.020147
v -1.052165 1.693250 -4.113129
v -1.423264 -0.272173 -4.052314
v -2.335668 2.112422 -2.554989
v 1.706754 -3.029854 0.171139
v -2.704852 0.116766 -2.710793
v 3.689623 1.837504 -1.209753
v -1.948996 -3.023728 0.875353
v 3.308379 -0.730487 -2.346540
v -0.899223 -1.466655 3.453547
v 3.176398 -0.164593 2.544505
v 1.450483 3.221935 0.923732
v -2.242297 -2.166627 2.063739
v -1.472705 -1.333648 -3.420503
v 3.871596 0.740806 1.546153
v 2.533928 1.975883 1.930760
v 0.492799 2.513122 -3.092595
v -0.349212 3.148993 -0.029523
v 3.267344 1.184023 2.241151
v -4.353748 -1.612557 -0.495422
v -1.930530 1.654793 2.510300
v 0.573979 -0.844695 -4.044802
v 0.528275 -3.143214 -1.789249
v 3.692719 -1.577900 -1.071348
v 1.168138 1.079678 3.139852
v 3.753358 -0.623585 -0.108652
v 3.379341 -1.003592 1.838246
v -1.351585 2.874982 -3.067893
v 1.766429 -1.157478 3.728364
v 3.667178 1.594924 1.024512
v -0.884260 1.836161 2.998022
v -1.073378 -3.132030 -1.461949
v -0.467529 3.159610 1.532913
v 3.709228 0.144063 -1.087636
v 3.605958 -1.445132 -1.878629
v 2.660886 3.124851 -0.854361
v -0.436671 0.126434 -4.552140
v -2.266935 -2.809002 -1.819118
v -2.916038 -0.990559 1.868705
v 0.627561 3.215132 -1.810096
v 2.894693 -2.446815 -1.574007
v 0.482250 2.215932 3.057291
v 2.681753 1.396219 -2.708434
v 0.310227 -2.120141 -3.148356
v 3.060341 -1.967882 0.490186
v 1.224500 -2.950663 1.059580
v 3.238048 2.395264 -1.831406
v 2.981815 0.133216 -2.548208
v 3.870637 0.807691 -0.134255
v 0.576682 -3.072934 2.294799
v -0.354720 0.674670 3.589938
v 1.886084 -2.119545 3.151299
v -3.599368 -2.470988 0.392379
v 0.714642 0.489363 -4.151877
vt 0.962265 0.728057
vt 0.899626 0.745931
vt 0.929662 0.684568
vt 0.750291 0.839492
vt 0.789824 0.780340
vt 0.836636 0.898960
vt 0.197601 0.657079
vt 0.236349 0.516526
vt 0.295964 0.556306
vt 0.406744 0.084655
vt 0.437681 0.165538
vt 0.371831 0.150081
vt 0.937341 0.802735
vt 0.739755 0.637792
vt 0.713864 0.558013
vt 0.790163 0.605118
vt 0.466004 0.054740
vt 0.531386 0.156801
vt 0.407272 0.036392
vt 0.227384 0.053071
vt 0.204144 0.126771
vt 0.146542 0.125405
vt 0.861072 0.549518
vt 0.871220 0.610164
vt 0.540887 0.052625
vt 0.483144 0.379133
vt 0.531410 0.373100
vt 0.566293 0.430810
vt 0.066866 0.123562
vt 0.065190 0.224005
vt 0.002406 0.127618
vt 0.881327 0.854767
vt 0.500670 0.000000
vt 0.321590 0.676758
vt 0.371831 0.718807
vt 0.319555 0.758685
vt 0.885719 0.501947
vt 0.883607 0.391689
vt 0.934425 0.485845
vt 0.000000 0.251617
vt 0.741391 0.942675
vt 0.814392 0.974820
vt 0.777879 1.000000
vt 0.635861 0.539129
vt 0.561478 0.627398
vt 0.446596 0.581324
vt 0.695576 0.850029
vt 0.128100 0.635461
vt 0.141764 0.513552
vt 0.359817 0.484969
vt 0.371774 0.529646
vt 0.372111 0.218880
vt 0.062065 0.038661
vt 0.000031 0.066144
vt 0.752155 0.392965
vt 0.762496 0.520997
vt 0.699231 0.418395
vt 0.845722 0.651852
vt 0.741723 0.694331
vt 0.371831 0.596760
vt 0.426111 0.638510
vt 0.365584 0.589421
vt 0.395927 0.271007
vt 0.515240 0.285039
vt 0.501419 0.319046
vt 0.561706 0.232608
vt 0.118925 0.447635
vt 0.173827 0.444650
vt 0.066425 0.272682
vt 0.752460 0.638720
vt 0.864116 0.319046
vt 0.634457 0.598443
vt 0.643782 0.659783
vt 0.207013 0.293435
vt 0.808222 0.487833
vt 0.608847 0.000134
vt 0.695638 0.677489
vt 0.696948 0.736016
vt 0.157426 0.707879
vt 0.668226 0.056560
vt 0.671934 0.003912
vt 0.198776 0.481993
vt 0.273634 0.449727
vt 0.804622 0.216599
vt 0.791229 0.301115
vt 0.747758 0.249256
vt 0.721640 0.137550
vt 0.191523 0.354536
vt 0.820792 0.282262
vt 0.950867 0.369066
vt 0.324779 0.115257
vt 0.323095 0.062677
vt 0.695576 0.356821
vt 0.647322 0.164260
vt 0.005872 0.513634
vt 0.041462 0.548754
vt 0.006022 0.612097
vt 0.429869 0.368933
vt 0.426298 0.477853
vt 0.044569 0.356401
vt 0.330651 0.269674
vt 0.101029 0.677297
vt 0.075503 0.599948
vt 0.682265 0.212902
vt 0.721592 0.099681
vt 0.985494 0.451521
vt 0.944144 0.577592
vt 0.268275 0.230026
vt 0.265275 0.163033
vt 0.610146 0.272739
vt 1.000000 0.368928
vt 0.371831 0.160502
vt 0.294827 0.352889
vt 0.179156 0.406072
vt 0.695576 0.633236
vt 0.912297 0.560646
vt 0.068301 0.408852
vt 0.837648 0.638720
vt 0.183490 0.418129
vt 0.674900 0.548703
vt 0.360881 0.086504
vt 0.170343 0.000000
vt 0.499177 0.455094
vt 0.730293 0.321189
vt 0.945692 0.869305
vt 0.006033 0.668066
vt 0.005872 0.612097
vt 0.055275 0.612495
vt 0.953257 0.914727
vt 0.586418 0.354851
vt 0.666332 0.438154
vt 0.252839 0.408852
vt 0.328739 0.431163
vt 0.388098 0.659674
vt 0.000000 0.475701
vt 0.041462 0.408852
vt 0.041403 0.513634
vt 0.489351 0.319046
vt 0.721592 0.319046
vt 0.354845 0.326581
vt 0.240882 0.751040
usemtl asteroid_asteroid_normals_uv.p
s 1
f 1/1 28/2 52/3
f 15/4 30/5 22/6
f 78/7 72/8 67/9
f 1/10 8/11 5/12
f 1/1 5/13 28/2
f 48/14 69/15 50/16
f 2/17 42/18 8/11
f 8/11 1/10 2/17
f 2/17 1/10 52/19
f 69/20 29/21 70/22
f 50/16 39/23 73/24
f 2/17 64/25 42/18
f 3/26 21/27 9/28
f 74/29 10/30 20/31
f 30/5 28/2 11/32
f 41/33 64/25 2/17
f 41/34 2/35 52/36
f 43/37 49/38 40/39
f 37/40 20/31 10/30
f 44/41 21/42 3/43
f 45/44 75/45 34/46
f 12/47 30/5 15/4
f 46/48 16/49 72/8
f 72/8 31/50 71/51
f 5/12 8/11 7/52
f 45/44 34/46 9/28
f 30/5 11/32 22/6
f 76/53 74/29 17/54
f 53/55 51/56 76/57
f 26/58 28/2 30/5
f 51/56 50/16 69/15
f 46/48 72/8 78/7
f 26/58 30/5 27/59
f 10/30 74/29 70/22
f 20/60 34/46 25/61
f 67/9 23/62 41/34
f 24/63 19/64 45/65
f 53/55 49/38 43/37
f 76/53 69/20 70/22
f 24/63 7/52 8/11
f 24/63 8/11 57/66
f 24/63 57/66 19/64
f 65/67 59/68 16/49
f 32/69 37/40 10/30
f 26/58 27/59 61/70
f 53/55 75/71 49/38
f 8/11 42/18 57/66
f 75/45 55/72 66/73
f 10/30 70/22 56/74
f 35/75 43/37 39/23
f 76/53 70/22 74/29
f 23/76 64/25 41/33
f 27/59 18/77 61/70
f 12/47 38/78 30/5
f 46/48 78/7 61/79
f 60/80 64/25 23/76
f 60/80 23/76 71/81
f 33/82 59/68 58/83
f 33/82 58/83 72/8
f 72/8 71/51 67/9
f 60/84 31/85 13/86
f 35/75 39/23 51/56
f 60/84 13/86 36/87
f 62/88 32/69 56/74
f 51/56 39/23 50/16
f 60/84 71/89 31/85
f 75/71 66/90 49/38
f 65/91 29/21 69/20
f 65/91 69/20 48/92
f 53/55 76/57 17/93
f 36/94 42/18 64/25
f 36/94 64/25 60/80
f 13/95 54/96 40/97
f 77/98 3/26 37/99
f 77/100 37/40 32/69
f 68/101 62/88 56/74
f 77/100 32/69 62/88
f 18/102 68/103 46/48
f 44/41 22/6 21/42
f 14/104 36/94 13/105
f 14/106 13/107 40/39
f 78/7 67/9 41/34
f 47/108 29/21 4/109
f 14/104 6/110 36/94
f 27/59 38/78 18/77
f 47/108 56/74 70/22
f 47/108 70/22 29/21
f 66/90 6/111 14/106
f 66/90 14/106 40/39
f 66/90 40/39 49/38
f 65/91 16/112 68/101
f 36/94 6/110 57/66
f 36/94 57/66 42/18
f 45/44 55/72 75/45
f 68/101 38/113 62/88
f 65/91 68/101 47/108
f 77/100 62/88 12/114
f 66/73 55/72 6/115
f 54/116 39/23 43/37
f 16/49 59/68 33/82
f 37/99 34/46 20/60
f 77/100 12/114 44/117
f 53/55 43/37 35/75
f 48/14 50/16 58/118
f 48/119 58/83 59/68
f 6/115 55/72 19/120
f 6/110 19/64 57/66
f 54/116 43/37 40/39
f 25/61 34/46 75/45
f 62/88 38/113 12/114
f 65/91 48/92 59/121
f 76/53 51/122 69/20
f 9/28 34/46 63/123
f 19/120 55/72 45/44
f 65/91 47/108 4/109
f 63/123 34/46 37/99
f 16/49 33/82 72/8
f 47/108 68/101 56/74
f 3/26 9/28 63/123
f 53/55 35/75 51/56
f 3/26 63/123 37/99
f 74/29 20/31 17/54
f 53/55 25/124 75/71
f 11/32 28/2 5/13
f 11/32 5/13 7/125
f 73/126 54/127 13/128
f 22/6 11/32 7/125
f 22/6 7/125 24/129
f 22/130 24/131 9/28
f 50/132 73/133 58/83
f 20/60 25/61 17/134
f 44/41 15/4 22/6
f 72/8 58/83 31/50
f 65/91 4/109 29/21
f 53/55 17/93 25/124
f 31/50 58/83 73/133
f 21/135 22/136 9/137
f 10/30 56/74 32/69
f 67/9 71/51 23/62
f 77/98 44/138 3/26
f 27/59 30/5 38/78
f 31/85 73/139 13/86
f 68/101 18/140 38/113
f 24/131 45/44 9/28
f 73/24 39/23 54/116
f 26/141 61/79 78/7
f 26/141 78/7 41/34
f 44/41 12/47 15/4
f 26/141 41/34 52/36
f 46/48 68/103 16/49
f 18/102 46/48 61/79
f 26/58 52/3 28/2

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,63 @@
Copyright (c) 2006-2007 dhpoware. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
-------------------------------------------------------------------------------
Per-fragment Blinn-Phong shader for a single directional light source.
[vert]
#version 110
varying vec3 normal;
void main()
{
normal = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
[frag]
#version 110
uniform sampler2D colorMap;
uniform float materialAlpha;
varying vec3 normal;
void main()
{
vec3 n = normalize(normal);
float nDotL = max(0.0, dot(n, gl_LightSource[0].position.xyz));
float nDotH = max(0.0, dot(normal, vec3(gl_LightSource[0].halfVector)));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);
vec4 ambient = gl_FrontLightProduct[0].ambient;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
vec4 specular = gl_FrontLightProduct[0].specular * power;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;
gl_FragColor = color * texture2D(colorMap, gl_TexCoord[0].st);
gl_FragColor.a = materialAlpha;
}

View File

@ -0,0 +1,89 @@
Copyright (c) 2006-2007 dhpoware. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
-------------------------------------------------------------------------------
Tangent space normal mapping shader for a single directional light source.
The tangent vector is passed to the vertex shader in gl_MultiTexCoord1. The
tangent vector is assumed to be a four component vector. The tangent vector's
w component indicates the handedness of the local tangent space at this vertex.
The handedness is used to calculate the bitangent vector. The reason for the
inclusion of the handedness component is to allow for triangles with mirrored
texture mappings.
-------------------------------------------------------------------------------
[vert]
#version 110
varying vec3 lightDir;
varying vec3 halfVector;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * gl_MultiTexCoord1.xyz);
vec3 b = cross(n, t) * gl_MultiTexCoord1.w;
mat3 tbnMatrix = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.z, n.z);
lightDir = gl_LightSource[0].position.xyz;
lightDir = tbnMatrix * lightDir;
halfVector = gl_LightSource[0].halfVector.xyz;
halfVector = tbnMatrix * halfVector;
}
[frag]
#version 110
uniform sampler2D colorMap;
uniform sampler2D normalMap;
uniform float materialAlpha;
varying vec3 lightDir;
varying vec3 halfVector;
void main()
{
vec3 n = normalize(texture2D(normalMap, gl_TexCoord[0].st).rgb * 2.0 - 1.0);
vec3 l = normalize(lightDir);
vec3 h = normalize(halfVector);
float nDotL = max(0.0, dot(n, l));
float nDotH = max(0.0, dot(n, h));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);
vec4 ambient = gl_FrontLightProduct[0].ambient;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL;
vec4 specular = gl_FrontLightProduct[0].specular * power;
vec4 color = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;
gl_FragColor = color * texture2D(colorMap, gl_TexCoord[0].st);
gl_FragColor.a = materialAlpha;
}

View File

@ -34,6 +34,7 @@ SET ( ENGINE_SRCS
VariablesCommands.cc VariablesCommands.cc
SimpleConsoleOverlay.cc SimpleConsoleOverlay.cc
Sprite.cc Sprite.cc
OBJModel.cc
IMGUIControls.cc IMGUIControls.cc
Engine.cc Engine.cc

1294
engine/OBJModel.cc Normal file

File diff suppressed because it is too large Load Diff

244
engine/OBJModel.h Normal file
View File

@ -0,0 +1,244 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2007 dhpoware. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _OBJMODEL_H
#define _OBJMODEL_H
#include <map>
#include <string>
#include <vector>
//-----------------------------------------------------------------------------
// Alias|Wavefront OBJ file loader.
//
// This OBJ file loader contains the following restrictions:
// 1. Group information is ignored. Faces are grouped based on the material
// that each face uses.
// 2. Object information is ignored. This loader will merge everything into a
// single object.
// 3. The MTL file must be located in the same directory as the OBJ file. If
// it isn't then the MTL file will fail to load and a default material is
// used instead.
// 4. This loader triangulates all polygonal faces during importing.
//-----------------------------------------------------------------------------
namespace Engine {
class OBJModel
{
public:
struct Material
{
float ambient[4];
float diffuse[4];
float specular[4];
float shininess; // [0 = min shininess, 1 = max shininess]
float alpha; // [0 = fully transparent, 1 = fully opaque]
std::string name;
std::string colorMapFilename;
std::string bumpMapFilename;
};
struct Vertex
{
float position[3];
float texCoord[2];
float normal[3];
float tangent[4];
float bitangent[3];
};
struct Mesh
{
int startIndex;
int triangleCount;
const Material *pMaterial;
};
OBJModel();
~OBJModel();
void destroy();
bool import(const char *pszFilename, bool rebuildNormals = false);
void normalize(float scaleTo = 1.0f, bool center = true);
void reverseWinding();
// Getter methods.
void getCenter(float &x, float &y, float &z) const;
float getWidth() const;
float getHeight() const;
float getLength() const;
float getRadius() const;
const int *getIndexBuffer() const;
int getIndexSize() const;
const Material &getMaterial(int i) const;
const Mesh &getMesh(int i) const;
int getNumberOfIndices() const;
int getNumberOfMaterials() const;
int getNumberOfMeshes() const;
int getNumberOfTriangles() const;
int getNumberOfVertices() const;
const std::string &getPath() const;
const Vertex &getVertex(int i) const;
const Vertex *getVertexBuffer() const;
int getVertexSize() const;
bool hasNormals() const;
bool hasPositions() const;
bool hasTangents() const;
bool hasTextureCoords() const;
private:
void addTrianglePos(int index, int material,
int v0, int v1, int v2);
void addTrianglePosNormal(int index, int material,
int v0, int v1, int v2,
int vn0, int vn1, int vn2);
void addTrianglePosTexCoord(int index, int material,
int v0, int v1, int v2,
int vt0, int vt1, int vt2);
void addTrianglePosTexCoordNormal(int index, int material,
int v0, int v1, int v2,
int vt0, int vt1, int vt2,
int vn0, int vn1, int vn2);
int addVertex(int hash, const Vertex *pVertex);
void bounds(float center[3], float &width, float &height,
float &length, float &radius) const;
void buildMeshes();
void generateNormals();
void generateTangents();
void importGeometryFirstPass(FILE *pFile);
void importGeometrySecondPass(FILE *pFile);
bool importMaterials(const char *pszFilename);
void scale(float scaleFactor, float offset[3]);
bool m_hasPositions;
bool m_hasTextureCoords;
bool m_hasNormals;
bool m_hasTangents;
int m_numberOfVertexCoords;
int m_numberOfTextureCoords;
int m_numberOfNormals;
int m_numberOfTriangles;
int m_numberOfMaterials;
int m_numberOfMeshes;
float m_center[3];
float m_width;
float m_height;
float m_length;
float m_radius;
std::string m_directoryPath;
std::vector<Mesh> m_meshes;
std::vector<Material> m_materials;
std::vector<Vertex> m_vertexBuffer;
std::vector<int> m_indexBuffer;
std::vector<int> m_attributeBuffer;
std::vector<float> m_vertexCoords;
std::vector<float> m_textureCoords;
std::vector<float> m_normals;
std::map<std::string, int> m_materialCache;
std::map<int, std::vector<int> > m_vertexCache;
};
//-----------------------------------------------------------------------------
inline void OBJModel::getCenter(float &x, float &y, float &z) const
{ x = m_center[0]; y = m_center[1]; z = m_center[2]; }
inline float OBJModel::getWidth() const
{ return m_width; }
inline float OBJModel::getHeight() const
{ return m_height; }
inline float OBJModel::getLength() const
{ return m_length; }
inline float OBJModel::getRadius() const
{ return m_radius; }
inline const int *OBJModel::getIndexBuffer() const
{ return &m_indexBuffer[0]; }
inline int OBJModel::getIndexSize() const
{ return static_cast<int>(sizeof(int)); }
inline const OBJModel::Material &OBJModel::getMaterial(int i) const
{ return m_materials[i]; }
inline const OBJModel::Mesh &OBJModel::getMesh(int i) const
{ return m_meshes[i]; }
inline int OBJModel::getNumberOfIndices() const
{ return m_numberOfTriangles * 3; }
inline int OBJModel::getNumberOfMaterials() const
{ return m_numberOfMaterials; }
inline int OBJModel::getNumberOfMeshes() const
{ return m_numberOfMeshes; }
inline int OBJModel::getNumberOfTriangles() const
{ return m_numberOfTriangles; }
inline int OBJModel::getNumberOfVertices() const
{ return static_cast<int>(m_vertexBuffer.size()); }
inline const std::string &OBJModel::getPath() const
{ return m_directoryPath; }
inline const OBJModel::Vertex &OBJModel::getVertex(int i) const
{ return m_vertexBuffer[i]; }
inline const OBJModel::Vertex *OBJModel::getVertexBuffer() const
{ return &m_vertexBuffer[0]; }
inline int OBJModel::getVertexSize() const
{ return static_cast<int>(sizeof(Vertex)); }
inline bool OBJModel::hasNormals() const
{ return m_hasNormals; }
inline bool OBJModel::hasPositions() const
{ return m_hasPositions; }
inline bool OBJModel::hasTangents() const
{ return m_hasTangents; }
inline bool OBJModel::hasTextureCoords() const
{ return m_hasTextureCoords; }
}
#endif

View File

@ -11,6 +11,8 @@
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#include "OBJModel.h"
#include "DrawingsGL.h" #include "DrawingsGL.h"
using namespace std; using namespace std;
@ -103,16 +105,14 @@ int ViewBase::OnInit (int argc, char* argv[]) {
else else
mUseShaders = false; mUseShaders = false;
/*
// load the shaders if possible // load the shaders if possible
if (mUseShaders) { if (mUseShaders) {
mBlinnPhongShader = LoadShaderProgram ("./data/shaders/blinn_phong.glsl"); mBlinnPhongShader = LoadShaderProgram (GetResourceFullPath("/data/shaders/blinn_phong.glsl"));
mNormalMappingShader = LoadShaderProgram ("./data/shaders/normal_mapping.glsl"); mNormalMappingShader = LoadShaderProgram (GetResourceFullPath("/data/shaders/normal_mapping.glsl"));
} else { } else {
mBlinnPhongShader = 0; mBlinnPhongShader = 0;
mNormalMappingShader = 0; mNormalMappingShader = 0;
} }
*/
// Create a null texture that can be used for objects without textures // Create a null texture that can be used for objects without textures
// taken from http://www.dhpoware.com/demos/glslNormalMapping.html // taken from http://www.dhpoware.com/demos/glslNormalMapping.html
@ -468,6 +468,501 @@ GLuint ViewBase::LoadTextureFromPNG (const std::string &filename) {
return temp_sprite.GetGLTextureName(); return temp_sprite.GetGLTextureName();
} }
/*
* OBJModel loading and drawing
*/
OBJModelPtr ViewBase::LoadOBJModel (const std::string &model_filename) {
LogDebug ("Loading OBJ model %s", model_filename.c_str());
OBJModelPtr result_model (new OBJModel);
if(!result_model->import (model_filename.c_str(), true)) {
LogError("Could not load model %s", model_filename.c_str());
return result_model;
}
result_model->normalize();
result_model->reverseWinding();
// Load any associated textures.
// Note the path where the textures are assumed to be located.
const OBJModel::Material *pMaterial = 0;
GLuint textureId = 0;
std::string::size_type offset = 0;
std::string filename;
for (int i = 0; i < result_model->getNumberOfMaterials(); ++i)
{
pMaterial = &result_model->getMaterial(i);
// Look for and load any diffuse color map textures.
if (!pMaterial->colorMapFilename.empty()) {
// Try load the texture using the path in the .MTL file.
textureId = LoadTextureFromPNG(pMaterial->colorMapFilename.c_str());
if (!textureId)
{
offset = pMaterial->colorMapFilename.find_last_of('\\');
if (offset != std::string::npos)
filename = pMaterial->colorMapFilename.substr(++offset);
else
filename = pMaterial->colorMapFilename;
// Try loading the texture from the same directory as the OBJ file.
textureId = LoadTextureFromPNG((filename).c_str());
}
} else {
LogMessage ("No diffuse color map found!");
}
// Look for and load any normal map textures.
if (!pMaterial->bumpMapFilename.empty()) {
// Try load the texture using the path in the .MTL file.
textureId = LoadTextureFromPNG((pMaterial->bumpMapFilename).c_str());
if (!textureId)
{
offset = pMaterial->bumpMapFilename.find_last_of('\\');
if (offset != std::string::npos)
filename = pMaterial->bumpMapFilename.substr(++offset);
else
filename = pMaterial->bumpMapFilename;
// Try loading the texture from the same directory as the OBJ file.
textureId = LoadTextureFromPNG((result_model->getPath() + filename).c_str());
}
} else {
LogMessage ("Material has no bumpmap!");
continue;
}
}
// Update the window caption.
LogMessage ("Loaded model %s successful, dimensions (whl): %f, %f, %f meshes %d vertices %d triangles: %d",
model_filename.c_str(),
result_model->getWidth(),
result_model->getHeight(),
result_model->getLength(),
result_model->getNumberOfMeshes(),
result_model->getNumberOfVertices(),
result_model->getNumberOfTriangles()
);
return result_model;
}
void ViewBase::DrawOBJModel (OBJModelPtr obj_model) {
if (mUseShaders) {
DrawOBJModelShaded(obj_model);
} else {
DrawOBJModelSolid (obj_model);
}
}
void ViewBase::DrawOBJModelSolid (OBJModelPtr obj_model) {
const OBJModel::Mesh *pMesh = 0;
const OBJModel::Material *pMaterial = 0;
const OBJModel::Vertex *pVertices = 0;
std::map<std::string, GLuint>::const_iterator iter;
for (int i = 0; i < obj_model->getNumberOfMeshes(); ++i)
{
pMesh = &obj_model->getMesh(i);
pMaterial = pMesh->pMaterial;
pVertices = obj_model->getVertexBuffer();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);
if (pMaterial->colorMapFilename.size() > 0)
{
iter = mGLTextures.find(pMaterial->colorMapFilename);
if (iter == mGLTextures.end())
{
LogError ("Could not find required colormap '%s'", pMaterial->colorMapFilename.c_str());
glDisable(GL_TEXTURE_2D);
}
else
{
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, iter->second);
}
}
else
{
glDisable(GL_TEXTURE_2D);
}
if (obj_model->hasPositions())
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->position);
}
if (obj_model->hasTextureCoords())
{
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->texCoord);
}
if (obj_model->hasNormals())
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->normal);
}
glDrawElements(GL_TRIANGLES, pMesh->triangleCount * 3, GL_UNSIGNED_INT,
obj_model->getIndexBuffer() + pMesh->startIndex);
if (obj_model->hasNormals())
glDisableClientState(GL_NORMAL_ARRAY);
if (obj_model->hasTextureCoords())
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
if (obj_model->hasPositions())
glDisableClientState(GL_VERTEX_ARRAY);
// disable texture drawing if active
if (pMaterial->colorMapFilename.size() > 0)
glDisable(GL_TEXTURE_2D);
}
}
void ViewBase::DrawOBJModelShaded (OBJModelPtr obj_model) {
const OBJModel::Mesh *pMesh = 0;
const OBJModel::Material *pMaterial = 0;
const OBJModel::Vertex *pVertices = 0;
std::map<std::string, GLuint>::const_iterator iter;
GLuint texture = 0;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (int i = 0; i < obj_model->getNumberOfMeshes(); ++i)
{
pMesh = &obj_model->getMesh(i);
pMaterial = pMesh->pMaterial;
pVertices = obj_model->getVertexBuffer();
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, pMaterial->ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, pMaterial->diffuse);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pMaterial->specular);
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, pMaterial->shininess * 128.0f);
// if there is no bumpmap we will simply use a blinn phong shader and draw
// the color map onto our model
if (pMaterial->bumpMapFilename.empty())
{
// LogMessage ("using Blinn Phong shader");
// Per fragment Blinn-Phong code path.
glUseProgram(mBlinnPhongShader);
// Bind the color map texture.
texture = mNullTexture;
if (pMaterial->colorMapFilename.size() > 0) {
iter = mGLTextures.find(pMaterial->colorMapFilename);
if (iter != mGLTextures.end())
texture = iter->second;
} else {
LogMessage ("Disabling textures");
}
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// Update shader parameters.
assert (glIsProgram (mBlinnPhongShader) == GL_TRUE);
assert (glGetUniformLocation(mBlinnPhongShader, "materialAlpha") != -1);
assert (glGetUniformLocation(mBlinnPhongShader, "colorMap") != -1);
glUniform1i(glGetUniformLocation(
mBlinnPhongShader, "colorMap"), 0);
glUniform1f(glGetUniformLocation(
mBlinnPhongShader, "materialAlpha"), pMaterial->alpha);
}
else
{
// if there is a bumpmap we use both the bump map and the color map and
// apply it on our model
// LogMessage ("using Normal Mapping Shader");
// Normal mapping code path.
glUseProgram(mNormalMappingShader);
// Bind the normal map texture.
iter = mGLTextures.find(pMaterial->bumpMapFilename);
if (iter != mGLTextures.end()) {
texture = iter->second;
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
} else {
LogMessage ("bumpmap %s not found", pMaterial->bumpMapFilename.c_str());
}
// Bind the color map texture.
texture = mNullTexture;
if (pMaterial->colorMapFilename.size() > 0)
{
iter = mGLTextures.find(pMaterial->colorMapFilename);
if (iter != mGLTextures.end()) {
texture = iter->second;
} else {
LogMessage ("color map %s not found", pMaterial->colorMapFilename.c_str());
}
}
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// Update shader parameters.
assert (glGetUniformLocation(mNormalMappingShader, "colorMap") != -1);
assert (glGetUniformLocation(mNormalMappingShader, "normalMap") != -1);
assert (glGetUniformLocation(mNormalMappingShader, "materialAlpha") != -1);
glUniform1i(glGetUniformLocation(
mNormalMappingShader, "colorMap"), 0);
glUniform1i(glGetUniformLocation(
mNormalMappingShader, "normalMap"), 1);
glUniform1f(glGetUniformLocation(
mNormalMappingShader, "materialAlpha"), pMaterial->alpha);
}
// Render mesh.
if (obj_model->hasPositions())
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->position);
}
if (obj_model->hasTextureCoords())
{
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->texCoord);
}
if (obj_model->hasNormals())
{
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->normal);
}
if (obj_model->hasTangents())
{
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(4, GL_FLOAT, obj_model->getVertexSize(),
obj_model->getVertexBuffer()->tangent);
}
glDrawElements(GL_TRIANGLES, pMesh->triangleCount * 3, GL_UNSIGNED_INT,
obj_model->getIndexBuffer() + pMesh->startIndex);
if (obj_model->hasTangents())
{
glClientActiveTexture(GL_TEXTURE1);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (obj_model->hasNormals())
glDisableClientState(GL_NORMAL_ARRAY);
if (obj_model->hasTextureCoords())
{
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
if (obj_model->hasPositions())
glDisableClientState(GL_VERTEX_ARRAY);
}
// as we might be using multiple textures (at least for the normal mapping
// case) we have to disable both textures
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgram(0);
glDisable(GL_BLEND);
// disable texture drawing
// glDisable(GL_TEXTURE_2D);
}
/*
* Shader loading, compiling, linking
*/
/** Compiles a shader program
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example (see http://www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase::CompileShader (GLenum type, const GLchar *source, GLint length) {
GLuint shader = glCreateShader(type);
if (shader) {
GLint compiled = 0;
glShaderSource (shader, 1, &source, &length);
glCompileShader(shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
GLsizei info_log_size = 0;
std::string info_log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_size);
info_log.resize (info_log_size);
glGetShaderInfoLog (shader, info_log_size, &info_log_size, &info_log[0]);
LogError ("Error compiling shader: %s", info_log.c_str());
}
}
return shader;
}
/** Links the given shader programs
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example (see http://www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase::LinkShaders (GLuint vertex_shader, GLuint fragment_shader) {
GLuint program = glCreateProgram();
if (program) {
GLint linked = 0;
if (vertex_shader)
glAttachShader (program, vertex_shader);
if (fragment_shader)
glAttachShader (program, fragment_shader);
glLinkProgram (program);
glGetProgramiv (program, GL_LINK_STATUS, &linked);
if (!linked) {
GLsizei info_log_size = 0;
std::string info_log;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_size);
info_log.resize (info_log_size);
glGetProgramInfoLog (program, info_log_size, &info_log_size, &info_log[0]);
LogError ("Error linking shaders vert: %d, frag: %d", vertex_shader, fragment_shader);
}
if (vertex_shader)
glDeleteShader (vertex_shader);
if (fragment_shader)
glDeleteShader (fragment_shader);
}
return program;
}
/** Loads a vertex or fragment shader program
*
* This function contains code mainly taken from dhpowares excellent
* objviewer example (see http://www.dhpoware.com/demos/gl3NormalMapping.html ).
*/
GLuint ViewBase::LoadShaderProgram (const std::string &filename) {
LogDebug ("Loading shader program %s", filename.c_str());
std::ifstream program_file (filename.c_str());
if (!program_file) {
LogError ("Could not open file '%s' while loading shader program", filename.c_str());
}
// read the whole file into a string
std::string shader_program ((std::istreambuf_iterator<char>(program_file)), std::istreambuf_iterator<char>());
program_file.close();
GLuint program = 0;
if (shader_program.size() > 0) {
const GLchar *source;
GLint length = 0;
GLuint vertex_shader = 0;
GLuint fragment_shader = 0;
std::string::size_type vertex_shader_offset = shader_program.find("[vert]");
std::string::size_type fragment_shader_offset = shader_program.find("[frag]");
if (vertex_shader_offset != std::string::npos) {
// skip over the [vert] tag
vertex_shader_offset += 6;
source = reinterpret_cast<const GLchar *> (&shader_program[vertex_shader_offset]);
length = static_cast<GLint>(fragment_shader_offset - vertex_shader_offset);
vertex_shader = CompileShader (GL_VERTEX_SHADER, source, length);
LogMessage ("Compiled vertex shader with id %d", vertex_shader);
}
if (fragment_shader_offset != std::string::npos) {
// skip over the [vert] tag
fragment_shader_offset += 6;
source = reinterpret_cast<const GLchar *> (&shader_program[fragment_shader_offset]);
length = static_cast<GLint>(shader_program.length() - fragment_shader_offset - 1);
fragment_shader = CompileShader (GL_FRAGMENT_SHADER, source, length);
LogMessage ("Compiled fragment shader with id %d", fragment_shader);
}
program = LinkShaders (vertex_shader, fragment_shader);
LogMessage ("Successfully linked shaders vert: %d frag: %d from file %s into program %d", vertex_shader, fragment_shader, filename.c_str(), program);
}
mShaderPrograms[filename] = program;
return program;
}
/*
* Camera and other auxillary functions
*/
void ViewBase::GetCamereEye (float *eye_out) { void ViewBase::GetCamereEye (float *eye_out) {
assert (mCamera); assert (mCamera);
mCamera->GetEye (eye_out); mCamera->GetEye (eye_out);

View File

@ -16,6 +16,9 @@ namespace Engine {
class Module; class Module;
class ModelBase; class ModelBase;
class CameraBase; class CameraBase;
class OBJModel;
typedef boost::shared_ptr<OBJModel> OBJModelPtr;
/** \brief Performs the actual drawing based on Camera and Model /** \brief Performs the actual drawing based on Camera and Model
*/ */
@ -134,9 +137,21 @@ class ViewBase : public Module{
/** \brief All loaded textures */ /** \brief All loaded textures */
std::map<std::string, GLuint> mGLTextures; std::map<std::string, GLuint> mGLTextures;
OBJModelPtr LoadOBJModel (const std::string &model_filename);
void DrawOBJModel (OBJModelPtr mesh);
void DrawOBJModelSolid (OBJModelPtr mesh);
void DrawOBJModelShaded (OBJModelPtr mesh);
std::map<std::string, OBJModelPtr> mOBJModeles;
/** \brief Whether we can use shader programs */ /** \brief Whether we can use shader programs */
bool mUseShaders; bool mUseShaders;
GLuint CompileShader (GLenum type, const GLchar *source, GLint length);
GLuint LinkShaders (GLuint vertex_shader, GLuint fragment_shader);
GLuint LoadShaderProgram (const std::string &filename);
std::map<std::string, GLuint> mShaderPrograms;
GLuint mBlinnPhongShader; GLuint mBlinnPhongShader;
GLuint mNormalMappingShader; GLuint mNormalMappingShader;