393 lines
10 KiB
C++
393 lines
10 KiB
C++
// ==============================================================
|
|
// This file is part of Glest Shared Library (www.glest.org)
|
|
//
|
|
// Copyright (C) 2001-2008 Martiño Figueroa
|
|
//
|
|
// You can redistribute this code and/or modify it under
|
|
// the terms of the GNU General Public License as published
|
|
// by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version
|
|
// ==============================================================
|
|
|
|
#include "model_renderer_gl.h"
|
|
|
|
#include "opengl.h"
|
|
#include "gl_wrap.h"
|
|
#include "texture_gl.h"
|
|
#include "interpolation.h"
|
|
#include "leak_dumper.h"
|
|
|
|
using namespace Shared::Platform;
|
|
|
|
namespace Shared { namespace Graphics { namespace Gl {
|
|
|
|
// =====================================================
|
|
// class MyClass
|
|
// =====================================================
|
|
|
|
// ===================== PUBLIC ========================
|
|
|
|
ModelRendererGl::ModelRendererGl() {
|
|
rendering= false;
|
|
duplicateTexCoords= false;
|
|
secondaryTexCoordUnit= 1;
|
|
lastTexture=0;
|
|
}
|
|
|
|
void ModelRendererGl::begin(bool renderNormals, bool renderTextures, bool renderColors,
|
|
bool colorPickingMode, MeshCallback *meshCallback) {
|
|
//assertions
|
|
assert(rendering == false);
|
|
assertGl();
|
|
|
|
this->renderTextures= renderTextures;
|
|
this->renderNormals= renderNormals;
|
|
this->renderColors= renderColors;
|
|
this->colorPickingMode = colorPickingMode;
|
|
this->meshCallback= meshCallback;
|
|
|
|
rendering= true;
|
|
lastTexture= 0;
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
//push attribs
|
|
glPushAttrib(GL_ENABLE_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_CURRENT_BIT | GL_TEXTURE_BIT);
|
|
glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
|
|
|
|
//init opengl
|
|
if(this->colorPickingMode == false) {
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
glFrontFace(GL_CCW);
|
|
|
|
if(this->colorPickingMode == false) {
|
|
glEnable(GL_NORMALIZE);
|
|
glEnable(GL_BLEND);
|
|
|
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
|
glPolygonOffset(0.005f, 0.0f);
|
|
}
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
if(renderNormals){
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
|
|
if(renderTextures){
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
|
|
/*
|
|
glHint( GL_LINE_SMOOTH_HINT, GL_FASTEST );
|
|
glHint( GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_FASTEST );
|
|
glHint( GL_GENERATE_MIPMAP_HINT, GL_FASTEST );
|
|
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST );
|
|
glHint( GL_POINT_SMOOTH_HINT, GL_FASTEST );
|
|
glHint( GL_POLYGON_SMOOTH_HINT, GL_FASTEST );
|
|
glHint( GL_TEXTURE_COMPRESSION_HINT, GL_FASTEST );
|
|
*/
|
|
|
|
if(this->colorPickingMode == true) {
|
|
BaseColorPickEntity::beginPicking();
|
|
}
|
|
|
|
//assertions
|
|
assertGl();
|
|
}
|
|
|
|
void ModelRendererGl::end() {
|
|
//assertions
|
|
assert(rendering);
|
|
assertGl();
|
|
|
|
//set render state
|
|
rendering= false;
|
|
|
|
if(this->colorPickingMode == false) {
|
|
glPolygonOffset( 0.0f, 0.0f );
|
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
|
}
|
|
|
|
//pop
|
|
glPopAttrib();
|
|
glPopClientAttrib();
|
|
|
|
if(colorPickingMode == true) {
|
|
BaseColorPickEntity::endPicking();
|
|
}
|
|
|
|
//assertions
|
|
assertGl();
|
|
}
|
|
|
|
void ModelRendererGl::render(Model *model,int renderMode) {
|
|
//assertions
|
|
assert(rendering);
|
|
assertGl();
|
|
|
|
//if(model->getIsStaticModel()) printf("In [%s::%s Line: %d] filename [%s] is static about to render...\n",__FILE__,__FUNCTION__,__LINE__,model->getFileName().c_str());
|
|
|
|
//render every mesh
|
|
//if(model->getIsStaticModel() == true) {
|
|
for(uint32 i = 0; i < model->getMeshCount(); ++i) {
|
|
renderMesh(model->getMeshPtr(i),renderMode);
|
|
}
|
|
//}
|
|
//assertions
|
|
assertGl();
|
|
}
|
|
|
|
void ModelRendererGl::renderNormalsOnly(Model *model) {
|
|
//assertions
|
|
assert(rendering);
|
|
assertGl();
|
|
|
|
//render every mesh
|
|
//if(model->getIsStaticModel() == true) {
|
|
for(uint32 i=0; i<model->getMeshCount(); ++i) {
|
|
renderMeshNormals(model->getMeshPtr(i));
|
|
}
|
|
//}
|
|
|
|
//assertions
|
|
assertGl();
|
|
}
|
|
|
|
// ===================== PRIVATE =======================
|
|
|
|
void ModelRendererGl::renderMesh(Mesh *mesh,int renderMode) {
|
|
|
|
if(renderMode==rmSelection && mesh->getNoSelect()==true)
|
|
{// don't render this and do nothing
|
|
return;
|
|
}
|
|
if(renderMode!=rmSelection){
|
|
if(mesh->getOnlySelect()) {
|
|
return;
|
|
}
|
|
}
|
|
//assertions
|
|
assertGl();
|
|
|
|
//glPolygonOffset(0.05f, 0.0f);
|
|
//set cull face
|
|
if(mesh->getTwoSided()) {
|
|
glDisable(GL_CULL_FACE);
|
|
}
|
|
else{
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
|
|
if(renderMode==rmNormal && mesh->getGlow()==true){
|
|
// glow on
|
|
glDisable(GL_LIGHTING);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
|
}
|
|
|
|
if(this->colorPickingMode == false) {
|
|
//set color
|
|
if(renderColors) {
|
|
Vec4f color(mesh->getDiffuseColor(), mesh->getOpacity());
|
|
glColor4fv(color.ptr());
|
|
}
|
|
|
|
//texture state
|
|
const Texture2DGl *texture= static_cast<const Texture2DGl*>(mesh->getTexture(mtDiffuse));
|
|
if(texture != NULL && renderTextures) {
|
|
if(lastTexture != texture->getHandle()){
|
|
//assert(glIsTexture(texture->getHandle()));
|
|
//throw megaglest_runtime_error("glIsTexture(texture->getHandle()) == false for texture: " + texture->getPath());
|
|
if(glIsTexture(texture->getHandle()) == GL_TRUE) {
|
|
glBindTexture(GL_TEXTURE_2D, texture->getHandle());
|
|
lastTexture= texture->getHandle();
|
|
}
|
|
else {
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
lastTexture= 0;
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
lastTexture= 0;
|
|
}
|
|
|
|
if(meshCallback != NULL) {
|
|
meshCallback->execute(mesh);
|
|
}
|
|
}
|
|
|
|
//misc vars
|
|
uint32 vertexCount= mesh->getVertexCount();
|
|
uint32 indexCount= mesh->getIndexCount();
|
|
|
|
//assertions
|
|
assertGl();
|
|
|
|
if(getVBOSupported() == true && mesh->getFrameCount() == 1) {
|
|
if(mesh->hasBuiltVBOEntities() == false) {
|
|
mesh->BuildVBOs();
|
|
}
|
|
//printf("Rendering Mesh with VBO's\n");
|
|
|
|
//vertices
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBOVertices() );
|
|
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL ); // Set The Vertex Pointer To The Vertex Buffer
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
|
|
//normals
|
|
if(renderNormals) {
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBONormals() );
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(GL_FLOAT, 0, (char *) NULL);
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
}
|
|
else{
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
|
|
assertGl();
|
|
|
|
//tex coords
|
|
if(renderTextures && mesh->getTexture(mtDiffuse) != NULL ) {
|
|
if(duplicateTexCoords) {
|
|
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
|
|
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBOTexCoords() );
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // Set The TexCoord Pointer To The TexCoord Buffer
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
}
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBOTexCoords() );
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer( 2, GL_FLOAT, 0, (char *) NULL ); // Set The TexCoord Pointer To The TexCoord Buffer
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
}
|
|
else {
|
|
if(duplicateTexCoords) {
|
|
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
}
|
|
else {
|
|
//printf("Rendering Mesh WITHOUT VBO's\n");
|
|
|
|
//vertices
|
|
glVertexPointer(3, GL_FLOAT, 0, mesh->getInterpolationData()->getVertices());
|
|
|
|
//normals
|
|
if(renderNormals) {
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(GL_FLOAT, 0, mesh->getInterpolationData()->getNormals());
|
|
}
|
|
else{
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
|
|
assertGl();
|
|
|
|
//tex coords
|
|
if(renderTextures && mesh->getTexture(mtDiffuse)!=NULL ) {
|
|
if(duplicateTexCoords) {
|
|
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh->getTexCoords());
|
|
}
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh->getTexCoords());
|
|
}
|
|
else {
|
|
if(duplicateTexCoords) {
|
|
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
}
|
|
}
|
|
|
|
if(getVBOSupported() == true && mesh->getFrameCount() == 1) {
|
|
assertGl();
|
|
|
|
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->getVBOIndexes() );
|
|
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, (char *)NULL);
|
|
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
|
|
//glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
|
|
|
assertGl();
|
|
}
|
|
else {
|
|
//draw model
|
|
assertGl();
|
|
|
|
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
|
}
|
|
|
|
// glow
|
|
if(renderMode==rmNormal && mesh->getGlow()==true){
|
|
// glow off
|
|
glEnable(GL_LIGHTING);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
//assertions
|
|
assertGl();
|
|
}
|
|
|
|
void ModelRendererGl::renderMeshNormals(Mesh *mesh) {
|
|
if(getVBOSupported() == true && mesh->getFrameCount() == 1) {
|
|
if(mesh->hasBuiltVBOEntities() == false) {
|
|
mesh->BuildVBOs();
|
|
}
|
|
|
|
//printf("Rendering Mesh Normals with VBO's\n");
|
|
|
|
//vertices
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBOVertices() );
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer( 3, GL_FLOAT, 0, (char *) NULL ); // Set The Vertex Pointer To The Vertex Buffer
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
|
|
//normals
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBONormals() );
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(GL_FLOAT, 0, (char *) NULL);
|
|
//glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
|
|
//misc vars
|
|
uint32 vertexCount= mesh->getVertexCount();
|
|
uint32 indexCount= mesh->getIndexCount();
|
|
|
|
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mesh->getVBOIndexes() );
|
|
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, (char *)NULL);
|
|
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
|
|
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
|
|
}
|
|
else {
|
|
//printf("Rendering Mesh Normals WITHOUT VBO's\n");
|
|
|
|
glBegin(GL_LINES);
|
|
for(unsigned int i = 0; i < mesh->getIndexCount(); ++i) {
|
|
const Vec3f &vertex= mesh->getInterpolationData()->getVertices()[mesh->getIndices()[i]];
|
|
const Vec3f &normal= vertex + mesh->getInterpolationData()->getNormals()[mesh->getIndices()[i]];
|
|
|
|
glVertex3fv(vertex.ptr());
|
|
glVertex3fv(normal.ptr());
|
|
}
|
|
glEnd();
|
|
}
|
|
}
|
|
|
|
}}}//end namespace
|