added OBJ loader
This commit is contained in:
@@ -34,6 +34,7 @@ SET ( ENGINE_SRCS
|
||||
VariablesCommands.cc
|
||||
SimpleConsoleOverlay.cc
|
||||
Sprite.cc
|
||||
OBJModel.cc
|
||||
IMGUIControls.cc
|
||||
|
||||
Engine.cc
|
||||
|
||||
+1294
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
+499
-4
@@ -11,6 +11,8 @@
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
#include "OBJModel.h"
|
||||
|
||||
#include "DrawingsGL.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -103,16 +105,14 @@ int ViewBase::OnInit (int argc, char* argv[]) {
|
||||
else
|
||||
mUseShaders = false;
|
||||
|
||||
/*
|
||||
// load the shaders if possible
|
||||
if (mUseShaders) {
|
||||
mBlinnPhongShader = LoadShaderProgram ("./data/shaders/blinn_phong.glsl");
|
||||
mNormalMappingShader = LoadShaderProgram ("./data/shaders/normal_mapping.glsl");
|
||||
mBlinnPhongShader = LoadShaderProgram (GetResourceFullPath("/data/shaders/blinn_phong.glsl"));
|
||||
mNormalMappingShader = LoadShaderProgram (GetResourceFullPath("/data/shaders/normal_mapping.glsl"));
|
||||
} else {
|
||||
mBlinnPhongShader = 0;
|
||||
mNormalMappingShader = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Create a null texture that can be used for objects without textures
|
||||
// taken from http://www.dhpoware.com/demos/glslNormalMapping.html
|
||||
@@ -468,6 +468,501 @@ GLuint ViewBase::LoadTextureFromPNG (const std::string &filename) {
|
||||
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) {
|
||||
assert (mCamera);
|
||||
mCamera->GetEye (eye_out);
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace Engine {
|
||||
class Module;
|
||||
class ModelBase;
|
||||
class CameraBase;
|
||||
class OBJModel;
|
||||
|
||||
typedef boost::shared_ptr<OBJModel> OBJModelPtr;
|
||||
|
||||
/** \brief Performs the actual drawing based on Camera and Model
|
||||
*/
|
||||
@@ -134,9 +137,21 @@ class ViewBase : public Module{
|
||||
/** \brief All loaded textures */
|
||||
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 */
|
||||
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 mNormalMappingShader;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user