Made changes to properly isolate new unit rotation code so that it is disabled by default

This commit is contained in:
Mark Vejvoda
2010-03-13 21:10:45 +00:00
parent c983eab0af
commit 2012b7e22c
27 changed files with 9174 additions and 58 deletions

View File

@@ -0,0 +1,172 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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
// ==============================================================
#ifndef _SHARED_GRAPHICS_MODEL_H_
#define _SHARED_GRAPHICS_MODEL_H_
#include <string>
#include <map>
#include "types.h"
#include "pixmap.h"
#include "texture_manager.h"
#include "texture.h"
#include "model_header.h"
using std::string;
using std::map;
using std::pair;
namespace Shared{ namespace Graphics{
class Model;
class Mesh;
class ShadowVolumeData;
class InterpolationData;
class TextureManager;
// =====================================================
// class Mesh
//
// Part of a 3D model
// =====================================================
class Mesh{
private:
//mesh data
Texture2D *textures[meshTextureCount];
string texturePaths[meshTextureCount];
//vertex data counts
uint32 frameCount;
uint32 vertexCount;
uint32 indexCount;
//vertex data
Vec3f *vertices;
Vec3f *normals;
Vec2f *texCoords;
Vec3f *tangents;
uint32 *indices;
//material data
Vec3f diffuseColor;
Vec3f specularColor;
float specularPower;
float opacity;
//properties
bool twoSided;
bool customColor;
InterpolationData *interpolationData;
public:
//init & end
Mesh();
~Mesh();
void init();
void end();
//maps
const Texture2D *getTexture(int i) const {return textures[i];}
//counts
uint32 getFrameCount() const {return frameCount;}
uint32 getVertexCount() const {return vertexCount;}
uint32 getIndexCount() const {return indexCount;}
uint32 getTriangleCount() const;
//data
const Vec3f *getVertices() const {return vertices;}
const Vec3f *getNormals() const {return normals;}
const Vec2f *getTexCoords() const {return texCoords;}
const Vec3f *getTangents() const {return tangents;}
const uint32 *getIndices() const {return indices;}
//material
const Vec3f &getDiffuseColor() const {return diffuseColor;}
const Vec3f &getSpecularColor() const {return specularColor;}
float getSpecularPower() const {return specularPower;}
float getOpacity() const {return opacity;}
//properties
bool getTwoSided() const {return twoSided;}
bool getCustomTexture() const {return customColor;}
//external data
const InterpolationData *getInterpolationData() const {return interpolationData;}
//interpolation
void buildInterpolationData();
void updateInterpolationData(float t, bool cycle) const;
void updateInterpolationVertices(float t, bool cycle) const;
//load
void loadV2(const string &dir, FILE *f, TextureManager *textureManager);
void loadV3(const string &dir, FILE *f, TextureManager *textureManager);
void load(const string &dir, FILE *f, TextureManager *textureManager);
void save(const string &dir, FILE *f);
private:
void computeTangents();
};
// =====================================================
// class Model
//
// 3D Model, than can be loaded from a g3d file
// =====================================================
class Model{
private:
TextureManager *textureManager;
private:
uint8 fileVersion;
uint32 meshCount;
Mesh *meshes;
public:
//constructor & destructor
Model();
virtual ~Model();
virtual void init()= 0;
virtual void end()= 0;
//data
void updateInterpolationData(float t, bool cycle) const;
void updateInterpolationVertices(float t, bool cycle) const;
void buildShadowVolumeData() const;
//get
uint8 getFileVersion() const {return fileVersion;}
uint32 getMeshCount() const {return meshCount;}
const Mesh *getMesh(int i) const {return &meshes[i];}
uint32 getTriangleCount() const;
uint32 getVertexCount() const;
//io
void load(const string &path);
void save(const string &path);
void loadG3d(const string &path);
void saveS3d(const string &path);
void setTextureManager(TextureManager *textureManager) {this->textureManager= textureManager;}
private:
void buildInterpolationData() const;
};
}}//end namespace
#endif

View File

@@ -0,0 +1,80 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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
// ==============================================================
#ifndef _SHARED_UTIL_PROPERTIES_H_
#define _SHARED_UTIL_PROPERTIES_H_
#include <string>
#include <map>
#include <vector>
using std::map;
using std::vector;
using std::string;
using std::pair;
namespace Shared{ namespace Util{
// =====================================================
// class Properties
//
/// ini-like file loader
// =====================================================
class Properties{
private:
static const int maxLine= 1024;
public:
typedef pair<string, string> PropertyPair;
typedef map<string, string> PropertyMap;
typedef vector<PropertyPair> PropertyVector;
private:
PropertyVector propertyVector;
PropertyMap propertyMap;
string path;
public:
void clear();
void load(const string &path);
void save(const string &path);
int getPropertyCount() {return propertyVector.size();}
string getKey(int i) {return propertyVector[i].first;}
string getString(int i) {return propertyVector[i].second;}
bool getBool(const string &key, const char *defaultValueIfNotFound=NULL) const;
int getInt(const string &key, const char *defaultValueIfNotFound=NULL) const;
int getInt(const string &key, int min, int max, const char *defaultValueIfNotFound=NULL) const;
float getFloat(const string &key, const char *defaultValueIfNotFound=NULL) const;
float getFloat(const string &key, float min, float max, const char *defaultValueIfNotFound=NULL) const;
const string getString(const string &key, const char *defaultValueIfNotFound=NULL) const;
int getInt(const char *key,const char *defaultValueIfNotFound=NULL) const;
bool getBool(const char *key,const char *defaultValueIfNotFound=NULL) const;
float getFloat(const char *key,const char *defaultValueIfNotFound=NULL) const;
const string getString(const char *key,const char *defaultValueIfNotFound=NULL) const;
void setInt(const string &key, int value);
void setBool(const string &key, bool value);
void setFloat(const string &key, float value);
void setString(const string &key, const string &value);
string toString();
};
}}//end namespace
#endif

View File

@@ -0,0 +1,151 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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 "opengl.h"
#include <stdexcept>
#include "graphics_interface.h"
#include "context_gl.h"
#include "gl_wrap.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
// =====================================================
// class Globals
// =====================================================
bool isGlExtensionSupported(const char *extensionName){
const char *s;
GLint len;
const GLubyte *extensionStr= glGetString(GL_EXTENSIONS);
s= reinterpret_cast<const char *>(extensionStr);
len= strlen(extensionName);
if(s != NULL) {
while ((s = strstr (s, extensionName)) != NULL) {
s+= len;
if((*s == ' ') || (*s == '\0')) {
return true;
}
}
}
return false;
}
bool isGlVersionSupported(int major, int minor, int release){
const char *strVersion= getGlVersion();
//major
const char *majorTok= strVersion;
int majorSupported= atoi(majorTok);
if(majorSupported<major){
return false;
}
else if(majorSupported>major){
return true;
}
//minor
int i=0;
while(strVersion[i]!='.'){
++i;
}
const char *minorTok= &strVersion[i]+1;
int minorSupported= atoi(minorTok);
if(minorSupported<minor){
return false;
}
else if(minorSupported>minor){
return true;
}
//release
++i;
while(strVersion[i]!='.'){
++i;
}
const char *releaseTok= &strVersion[i]+1;
if(atoi(releaseTok)<release){
return false;
}
return true;
}
const char *getGlVersion(){
return reinterpret_cast<const char *>(glGetString(GL_VERSION));
}
const char *getGlRenderer(){
return reinterpret_cast<const char *>(glGetString(GL_RENDERER));
}
const char *getGlVendor(){
return reinterpret_cast<const char *>(glGetString(GL_VENDOR));
}
const char *getGlExtensions(){
return reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
}
const char *getGlPlatformExtensions(){
Context *c= GraphicsInterface::getInstance().getCurrentContext();
return getPlatformExtensions(static_cast<ContextGl*>(c)->getPlatformContextGl());
}
int getGlMaxLights(){
int i;
glGetIntegerv(GL_MAX_LIGHTS, &i);
return i;
}
int getGlMaxTextureSize(){
int i;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &i);
return i;
}
int getGlMaxTextureUnits(){
int i;
glGetIntegerv(GL_MAX_TEXTURE_UNITS, &i);
return i;
}
int getGlModelviewMatrixStackDepth(){
int i;
glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &i);
return i;
}
int getGlProjectionMatrixStackDepth(){
int i;
glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &i);
return i;
}
void checkGlExtension(const char *extensionName){
if(!isGlExtensionSupported(extensionName)){
throw runtime_error("OpenGL extension not supported: " + string(extensionName));
}
}
}}}// end namespace

View File

@@ -0,0 +1,373 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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 "texture_gl.h"
#include <stdexcept>
#include "opengl.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Graphics{ namespace Gl{
using namespace Platform;
GLint toWrapModeGl(Texture::WrapMode wrapMode){
switch(wrapMode){
case Texture::wmClamp:
return GL_CLAMP;
case Texture::wmRepeat:
return GL_REPEAT;
case Texture::wmClampToEdge:
return GL_CLAMP_TO_EDGE;
default:
assert(false);
return GL_CLAMP;
}
}
GLint toFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE;
case 3:
return GL_RGB;
case 4:
return GL_RGBA;
default:
assert(false);
return GL_RGBA;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE;
case Texture::fAlpha:
return GL_ALPHA;
case Texture::fRgb:
return GL_RGB;
case Texture::fRgba:
return GL_RGBA;
default:
assert(false);
return GL_RGB;
}
}
GLint toInternalFormatGl(Texture::Format format, int components){
switch(format){
case Texture::fAuto:
switch(components){
case 1:
return GL_LUMINANCE8;
case 3:
return GL_RGB8;
case 4:
return GL_RGBA8;
default:
assert(false);
return GL_RGBA8;
}
break;
case Texture::fLuminance:
return GL_LUMINANCE8;
case Texture::fAlpha:
return GL_ALPHA8;
case Texture::fRgb:
return GL_RGB8;
case Texture::fRgba:
return GL_RGBA8;
default:
assert(false);
return GL_RGB8;
}
}
// =====================================================
// class Texture1DGl
// =====================================================
void Texture1DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_1D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, wrap);
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
//build mipmaps
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int error= gluBuild1DMipmaps(
GL_TEXTURE_1D, glInternalFormat, pixmap.getW(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture 1D mipmaps");
}
}
else{
//build single texture
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage1D(
GL_TEXTURE_1D, 0, glInternalFormat, pixmap.getW(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 1D");
}
}
inited= true;
}
assertGl();
}
void Texture1DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class Texture2DGl
// =====================================================
void Texture2DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_2D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
//maxAnisotropy
if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
}
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
//build mipmaps
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
int error= gluBuild2DMipmaps(
GL_TEXTURE_2D, glInternalFormat,
pixmap.getW(), pixmap.getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture 2D mipmaps");
}
}
else{
//build single texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(
GL_TEXTURE_2D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 2D");
}
}
inited= true;
}
assertGl();
}
void Texture2DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class Texture3DGl
// =====================================================
void Texture3DGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//params
GLint wrap= toWrapModeGl(wrapMode);
GLint glFormat= toFormatGl(format, pixmap.getComponents());
GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
//pixel init var
const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_3D, handle);
//wrap params
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap);
//build single texture
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage3D(
GL_TEXTURE_3D, 0, glInternalFormat,
pixmap.getW(), pixmap.getH(), pixmap.getD(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
GLint error= glGetError();
if(error!=GL_NO_ERROR){
throw runtime_error("Error creating texture 3D");
}
inited= true;
}
assertGl();
}
void Texture3DGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
// =====================================================
// class TextureCubeGl
// =====================================================
void TextureCubeGl::init(Filter filter, int maxAnisotropy){
assertGl();
if(!inited){
//gen texture
glGenTextures(1, &handle);
glBindTexture(GL_TEXTURE_CUBE_MAP, handle);
//wrap
GLint wrap= toWrapModeGl(wrapMode);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap);
//filter
if(mipmap){
GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, glFilter);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
else{
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
for(int i=0; i<6; ++i){
//params
const Pixmap2D *currentPixmap= pixmap.getFace(i);
GLint glFormat= toFormatGl(format, currentPixmap->getComponents());
GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents());
//pixel init var
const uint8* pixels= pixmapInit? currentPixmap->getPixels(): NULL;
GLenum target= GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
if(mipmap){
int error= gluBuild2DMipmaps(
target, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
glFormat, GL_UNSIGNED_BYTE, pixels);
if(error!=0){
throw runtime_error("Error building texture cube mipmaps");
}
}
else{
glTexImage2D(
target, 0, glInternalFormat,
currentPixmap->getW(), currentPixmap->getH(),
0, glFormat, GL_UNSIGNED_BYTE, pixels);
}
if(glGetError()!=GL_NO_ERROR){
throw runtime_error("Error creating texture cube");
}
}
inited= true;
}
assertGl();
}
void TextureCubeGl::end(){
if(inited){
assertGl();
glDeleteTextures(1, &handle);
assertGl();
}
}
}}}//end namespace

View File

@@ -0,0 +1,525 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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.h"
#include <cstdio>
#include <cassert>
#include <stdexcept>
#include "interpolation.h"
#include "conversion.h"
#include "util.h"
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace std;
namespace Shared{ namespace Graphics{
using namespace Util;
// =====================================================
// class Mesh
// =====================================================
// ==================== constructor & destructor ====================
Mesh::Mesh(){
frameCount= 0;
vertexCount= 0;
indexCount= 0;
vertices= NULL;
normals= NULL;
texCoords= NULL;
tangents= NULL;
indices= NULL;
interpolationData= NULL;
for(int i=0; i<meshTextureCount; ++i){
textures[i]= NULL;
}
twoSided= false;
customColor= false;
}
Mesh::~Mesh(){
end();
}
void Mesh::init(){
vertices= new Vec3f[frameCount*vertexCount];
normals= new Vec3f[frameCount*vertexCount];
texCoords= new Vec2f[vertexCount];
indices= new uint32[indexCount];
}
void Mesh::end(){
delete [] vertices;
delete [] normals;
delete [] texCoords;
delete [] tangents;
delete [] indices;
delete interpolationData;
}
// ========================== shadows & interpolation =========================
void Mesh::buildInterpolationData(){
interpolationData= new InterpolationData(this);
}
void Mesh::updateInterpolationData(float t, bool cycle) const{
interpolationData->update(t, cycle);
}
void Mesh::updateInterpolationVertices(float t, bool cycle) const{
interpolationData->updateVertices(t, cycle);
}
// ==================== load ====================
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV2 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
throw runtime_error("Old model: vertex frame count different from normal frame count");
}
if(meshHeader.texCoordFrameCount!=1){
throw runtime_error("Old model: texture coord frame count is not 1");
}
//init
frameCount= meshHeader.vertexFrameCount;
vertexCount= meshHeader.pointCount;
indexCount= meshHeader.indexCount;
init();
//misc
twoSided= false;
customColor= false;
//texture
if(meshHeader.hasTexture && textureManager!=NULL){
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
string texPath= dir+"/"+texturePaths[mtDiffuse];
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
if(textures[mtDiffuse]==NULL){
textures[mtDiffuse]= textureManager->newTexture2D();
textures[mtDiffuse]->load(texPath);
}
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV3 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
throw runtime_error("Old model: vertex frame count different from normal frame count");
}
//init
frameCount= meshHeader.vertexFrameCount;
vertexCount= meshHeader.pointCount;
indexCount= meshHeader.indexCount;
init();
//misc
twoSided= (meshHeader.properties & mp3TwoSided) != 0;
customColor= (meshHeader.properties & mp3CustomColor) != 0;
//texture
if(!(meshHeader.properties & mp3NoTexture) && textureManager!=NULL){
texturePaths[mtDiffuse]= toLower(reinterpret_cast<char*>(meshHeader.texName));
string texPath= dir+"/"+texturePaths[mtDiffuse];
textures[mtDiffuse]= static_cast<Texture2D*>(textureManager->getTexture(texPath));
if(textures[mtDiffuse]==NULL){
textures[mtDiffuse]= textureManager->newTexture2D();
textures[mtDiffuse]->load(texPath);
}
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
for(int i=0; i<meshHeader.texCoordFrameCount; ++i){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeader meshHeader;
fread(&meshHeader, sizeof(MeshHeader), 1, f);
//init
frameCount= meshHeader.frameCount;
vertexCount= meshHeader.vertexCount;
indexCount= meshHeader.indexCount;
init();
//properties
customColor= (meshHeader.properties & mpfCustomColor) != 0;
twoSided= (meshHeader.properties & mpfTwoSided) != 0;
//material
diffuseColor= Vec3f(meshHeader.diffuseColor);
specularColor= Vec3f(meshHeader.specularColor);
specularPower= meshHeader.specularPower;
opacity= meshHeader.opacity;
//maps
uint32 flag= 1;
for(int i=0; i<meshTextureCount; ++i){
if((meshHeader.textures & flag) && textureManager!=NULL){
uint8 cMapPath[mapPathSize];
fread(cMapPath, mapPathSize, 1, f);
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
string mapFullPath= dir + "/" + mapPath;
textures[i]= static_cast<Texture2D*>(textureManager->getTexture(mapFullPath));
if(textures[i]==NULL){
textures[i]= textureManager->newTexture2D();
if(meshTextureChannelCount[i]!=-1){
textures[i]->getPixmap()->init(meshTextureChannelCount[i]);
}
textures[i]->load(mapFullPath);
}
}
flag*= 2;
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(meshHeader.textures!=0){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(indices, sizeof(uint32)*indexCount, 1, f);
//tangents
if(textures[mtNormal]!=NULL){
computeTangents();
}
}
void Mesh::save(const string &dir, FILE *f){
/*MeshHeader meshHeader;
meshHeader.vertexFrameCount= vertexFrameCount;
meshHeader.normalFrameCount= normalFrameCount;
meshHeader.texCoordFrameCount= texCoordFrameCount;
meshHeader.colorFrameCount= colorFrameCount;
meshHeader.pointCount= pointCount;
meshHeader.indexCount= indexCount;
meshHeader.properties= 0;
if(twoSided) meshHeader.properties|= mpTwoSided;
if(customTexture) meshHeader.properties|= mpCustomTexture;
if(texture==NULL){
meshHeader.properties|= mpNoTexture;
meshHeader.texName[0]= '\0';
}
else{
strcpy(reinterpret_cast<char*>(meshHeader.texName), texName.c_str());
texture->getPixmap()->saveTga(dir+"/"+texName);
}
fwrite(&meshHeader, sizeof(MeshHeader), 1, f);
fwrite(vertices, sizeof(Vec3f)*vertexFrameCount*pointCount, 1, f);
fwrite(normals, sizeof(Vec3f)*normalFrameCount*pointCount, 1, f);
fwrite(texCoords, sizeof(Vec2f)*texCoordFrameCount*pointCount, 1, f);
fwrite(colors, sizeof(Vec4f)*colorFrameCount, 1, f);
fwrite(indices, sizeof(uint32)*indexCount, 1, f);*/
}
void Mesh::computeTangents(){
delete [] tangents;
tangents= new Vec3f[vertexCount];
for(int i=0; i<vertexCount; ++i){
tangents[i]= Vec3f(0.f);
}
for(int i=0; i<indexCount; i+=3){
for(int j=0; j<3; ++j){
uint32 i0= indices[i+j];
uint32 i1= indices[i+(j+1)%3];
uint32 i2= indices[i+(j+2)%3];
Vec3f p0= vertices[i0];
Vec3f p1= vertices[i1];
Vec3f p2= vertices[i2];
float u0= texCoords[i0].x;
float u1= texCoords[i1].x;
float u2= texCoords[i2].x;
float v0= texCoords[i0].y;
float v1= texCoords[i1].y;
float v2= texCoords[i2].y;
tangents[i0]+=
((p2-p0)*(v1-v0)-(p1-p0)*(v2-v0))/
((u2-u0)*(v1-v0)-(u1-u0)*(v2-v0));
}
}
for(int i=0; i<vertexCount; ++i){
/*Vec3f binormal= normals[i].cross(tangents[i]);
tangents[i]+= binormal.cross(normals[i]);*/
tangents[i].normalize();
}
}
// ===============================================
// class Model
// ===============================================
// ==================== constructor & destructor ====================
Model::Model(){
meshCount= 0;
meshes= NULL;
textureManager= NULL;
}
Model::~Model(){
delete [] meshes;
}
// ==================== data ====================
void Model::buildInterpolationData() const{
for(int i=0; i<meshCount; ++i){
meshes[i].buildInterpolationData();
}
}
void Model::updateInterpolationData(float t, bool cycle) const{
for(int i=0; i<meshCount; ++i){
meshes[i].updateInterpolationData(t, cycle);
}
}
void Model::updateInterpolationVertices(float t, bool cycle) const{
for(int i=0; i<meshCount; ++i){
meshes[i].updateInterpolationVertices(t, cycle);
}
}
// ==================== get ====================
uint32 Model::getTriangleCount() const{
uint32 triangleCount= 0;
for(uint32 i=0; i<meshCount; ++i){
triangleCount+= meshes[i].getIndexCount()/3;
}
return triangleCount;
}
uint32 Model::getVertexCount() const{
uint32 vertexCount= 0;
for(uint32 i=0; i<meshCount; ++i){
vertexCount+= meshes[i].getVertexCount();
}
return vertexCount;
}
// ==================== io ====================
void Model::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="g3d" || extension=="G3D"){
loadG3d(path);
}
else{
throw runtime_error("Unknown model format: " + extension);
}
}
void Model::save(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="g3d" ||extension=="G3D" || extension=="s3d" || extension=="S3D"){
saveS3d(path);
}
else{
throw runtime_error("Unknown model format: " + extension);
}
}
/*void Model::loadG3dOld(const string &path){
try{
FILE *f=fopen(path.c_str(),"rb");
if (f==NULL){
throw runtime_error("Error opening 3d model file");
}
string dir= cutLastFile(path);
//read header
ModelHeaderOld modelHeader;
fread(&modelHeader, sizeof(ModelHeader), 1, f);
meshCount= modelHeader.meshCount;
if(modelHeader.id[0]!='G' || modelHeader.id[1]!='3' || modelHeader.id[2]!='D'){
throw runtime_error("Model: "+path+": is not a valid G3D model");
}
switch(modelHeader.version){
case 3:{
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].load(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
break;
}
default:
throw runtime_error("Unknown model version");
}
fclose(f);
}
catch(exception &e){
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
}
}*/
//load a model from a g3d file
void Model::loadG3d(const string &path){
try{
FILE *f=fopen(path.c_str(),"rb");
if (f==NULL){
throw runtime_error("Error opening 3d model file");
}
string dir= cutLastFile(path);
//file header
FileHeader fileHeader;
fread(&fileHeader, sizeof(FileHeader), 1, f);
if(strncmp(reinterpret_cast<char*>(fileHeader.id), "G3D", 3)!=0){
printf("In [%s::%s] file = [%s] fileheader.id = [%s][%c]\n",__FILE__,__FUNCTION__,path.c_str(),reinterpret_cast<char*>(fileHeader.id),fileHeader.id[0]);
throw runtime_error("Not a valid S3D model");
}
fileVersion= fileHeader.version;
//version 4
if(fileHeader.version==4){
//model header
ModelHeader modelHeader;
fread(&modelHeader, sizeof(ModelHeader), 1, f);
meshCount= modelHeader.meshCount;
if(modelHeader.type!=mtMorphMesh){
throw runtime_error("Invalid model type");
}
//load meshes
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].load(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
//version 3
else if(fileHeader.version==3){
fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV3(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
//version 2
else if(fileHeader.version==2){
fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV2(dir, f, textureManager);
meshes[i].buildInterpolationData();
}
}
else{
throw runtime_error("Invalid model version: "+ intToStr(fileHeader.version));
}
fclose(f);
}
catch(exception &e){
throw runtime_error("Exception caught loading 3d file: " + path +"\n"+ e.what());
}
}
//save a model to a g3d file
void Model::saveS3d(const string &path){
/*FILE *f= fopen(path.c_str(), "wb");
if(f==NULL){
throw runtime_error("Cant open file for writting: "+path);
}
ModelHeader modelHeader;
modelHeader.id[0]= 'G';
modelHeader.id[1]= '3';
modelHeader.id[2]= 'D';
modelHeader.version= 3;
modelHeader.meshCount= meshCount;
string dir= cutLastFile(path);
fwrite(&modelHeader, sizeof(ModelHeader), 1, f);
for(int i=0; i<meshCount; ++i){
meshes[i].save(dir, f);
}
fclose(f);*/
}
}}//end namespace

View File

@@ -0,0 +1,96 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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 "texture_manager.h"
#include <cstdlib>
#include "graphics_interface.h"
#include "graphics_factory.h"
#include "leak_dumper.h"
namespace Shared{ namespace Graphics{
// =====================================================
// class TextureManager
// =====================================================
TextureManager::TextureManager(){
textureFilter= Texture::fBilinear;
maxAnisotropy= 1;
}
TextureManager::~TextureManager(){
end();
}
void TextureManager::init(){
for(int i=0; i<textures.size(); ++i){
textures[i]->init(textureFilter, maxAnisotropy);
}
}
void TextureManager::end(){
for(int i=0; i<textures.size(); ++i){
textures[i]->end();
delete textures[i];
}
textures.clear();
}
void TextureManager::setFilter(Texture::Filter textureFilter){
this->textureFilter= textureFilter;
}
void TextureManager::setMaxAnisotropy(int maxAnisotropy){
this->maxAnisotropy= maxAnisotropy;
}
Texture *TextureManager::getTexture(const string &path){
for(int i=0; i<textures.size(); ++i){
if(textures[i]->getPath()==path){
return textures[i];
}
}
return NULL;
}
Texture1D *TextureManager::newTexture1D(){
Texture1D *texture1D= GraphicsInterface::getInstance().getFactory()->newTexture1D();
textures.push_back(texture1D);
return texture1D;
}
Texture2D *TextureManager::newTexture2D(){
Texture2D *texture2D= GraphicsInterface::getInstance().getFactory()->newTexture2D();
textures.push_back(texture2D);
return texture2D;
}
Texture3D *TextureManager::newTexture3D(){
Texture3D *texture3D= GraphicsInterface::getInstance().getFactory()->newTexture3D();
textures.push_back(texture3D);
return texture3D;
}
TextureCube *TextureManager::newTextureCube(){
TextureCube *textureCube= GraphicsInterface::getInstance().getFactory()->newTextureCube();
textures.push_back(textureCube);
return textureCube;
}
}}//end namespace

View File

@@ -0,0 +1,126 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>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 "conversion.h"
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
const int strSize = 256;
bool strToBool(const string &s){
if (s=="0" || s=="false"){
return false;
}
if (s=="1" || s=="true"){
return true;
}
throw runtime_error("Error converting string to bool, expected 0 or 1, found: [" + s + "]");
}
int strToInt(const string &s){
char *endChar;
int intValue= strtol(s.c_str(), &endChar, 10);
if(*endChar!='\0'){
throw runtime_error("Error converting from string to int, found: [" + s + "]");
}
return intValue;
}
float strToFloat(const string &s){
char *endChar;
float floatValue= static_cast<float>(strtod(s.c_str(), &endChar));
if(*endChar!='\0'){
throw runtime_error("Error converting from string to float, found: [" + s + "]");
}
return floatValue;
}
bool strToBool(const string &s, bool *b){
if (s=="0" || s=="false"){
*b= false;
return true;
}
if (s=="1" || s=="true"){
*b= true;
return true;
}
return false;
}
bool strToInt(const string &s, int *i){
char *endChar;
*i= strtol(s.c_str(), &endChar, 10);
if(*endChar!='\0'){
return false;
}
return true;
}
bool strToFloat(const string &s, float *f){
char *endChar;
*f= static_cast<float>(strtod(s.c_str(), &endChar));
if(*endChar!='\0'){
return false;
}
return true;
}
string boolToStr(bool b){
if(b){
return "1";
}
else{
return "0";
}
}
string intToStr(int i){
char str[strSize];
sprintf(str, "%d", i);
return str;
}
string intToHex(int i){
char str[strSize];
sprintf(str, "%x", i);
return str;
}
string floatToStr(float f){
char str[strSize];
sprintf(str, "%.2f", f);
return str;
}
string doubleToStr(double d){
char str[strSize];
sprintf(str, "%.2f", d);
return str;
}
}}//end namespace

View File

@@ -0,0 +1,224 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2007 Marti<74>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 "properties.h"
#include <fstream>
#include <stdexcept>
#include <cstring>
#include "conversion.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
// =====================================================
// class Properties
// =====================================================
void Properties::load(const string &path){
ifstream fileStream;
char lineBuffer[maxLine];
string line, key, value;
int pos;
this->path= path;
fileStream.open(path.c_str(), ios_base::in);
if(fileStream.fail()){
throw runtime_error("Can't open propertyMap file: " + path);
}
propertyMap.clear();
while(!fileStream.eof()){
fileStream.getline(lineBuffer, maxLine);
lineBuffer[maxLine-1]='\0';
//process line if it it not a comment
if(lineBuffer[0]!=';'){
// gracefully handle win32 \r\n line endings
size_t len= strlen(lineBuffer);
if(len > 0 && lineBuffer[len-1] == '\r'){
lineBuffer[len-1]= 0;
}
line= lineBuffer;
pos= line.find('=');
if(pos != string::npos){
key= line.substr(0, pos);
value= line.substr(pos+1);
propertyMap.insert(PropertyPair(key, value));
propertyVector.push_back(PropertyPair(key, value));
}
}
}
fileStream.close();
}
void Properties::save(const string &path){
ofstream fileStream;
fileStream.open(path.c_str(), ios_base::out | ios_base::trunc);
fileStream << "; === propertyMap File === \n";
fileStream << '\n';
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); ++pi){
fileStream << pi->first << '=' << pi->second << '\n';
}
fileStream.close();
}
void Properties::clear(){
propertyMap.clear();
propertyVector.clear();
}
bool Properties::getBool(const string &key, const char *defaultValueIfNotFound) const{
try{
return strToBool(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path+"\n[" + e.what() + "]");
}
}
int Properties::getInt(const string &key,const char *defaultValueIfNotFound) const{
try{
return strToInt(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n[" + e.what() + "]");
}
}
int Properties::getInt(const string &key, int min, int max,const char *defaultValueIfNotFound) const{
int i= getInt(key,defaultValueIfNotFound);
if(i<min || i>max){
throw runtime_error("Value out of range: " + key + ", min: " + intToStr(min) + ", max: " + intToStr(max));
}
return i;
}
float Properties::getFloat(const string &key, const char *defaultValueIfNotFound) const{
try{
return strToFloat(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + key + " in: " + path + "\n[" + e.what() + "]");
}
}
float Properties::getFloat(const string &key, float min, float max, const char *defaultValueIfNotFound) const{
float f= getFloat(key,defaultValueIfNotFound);
if(f<min || f>max){
throw runtime_error("Value out of range: " + key + ", min: " + floatToStr(min) + ", max: " + floatToStr(max));
}
return f;
}
const string Properties::getString(const string &key, const char *defaultValueIfNotFound) const{
PropertyMap::const_iterator it;
it= propertyMap.find(key);
if(it==propertyMap.end()){
if(defaultValueIfNotFound != NULL) {
return string(defaultValueIfNotFound);
}
else {
throw runtime_error("Value not found in propertyMap: " + key + ", loaded from: " + path);
}
}
else{
return it->second;
}
}
void Properties::setInt(const string &key, int value){
setString(key, intToStr(value));
}
void Properties::setBool(const string &key, bool value){
setString(key, boolToStr(value));
}
void Properties::setFloat(const string &key, float value){
setString(key, floatToStr(value));
}
void Properties::setString(const string &key, const string &value){
propertyMap.erase(key);
propertyMap.insert(PropertyPair(key, value));
}
string Properties::toString(){
string rStr;
for(PropertyMap::iterator pi= propertyMap.begin(); pi!=propertyMap.end(); pi++)
rStr+= pi->first + "=" + pi->second + "\n";
return rStr;
}
bool Properties::getBool(const char *key, const char *defaultValueIfNotFound) const{
try{
return strToBool(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + string(key) + " in: " + path+"\n[" + e.what() + "]");
}
}
int Properties::getInt(const char *key,const char *defaultValueIfNotFound) const{
try{
return strToInt(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + string(key) + " in: " + path + "\n[" + e.what() + "]");
}
}
float Properties::getFloat(const char *key, const char *defaultValueIfNotFound) const{
try{
return strToFloat(getString(key,defaultValueIfNotFound));
}
catch(exception &e){
throw runtime_error("Error accessing value: " + string(key) + " in: " + path + "\n[" + e.what() + "]");
}
}
const string Properties::getString(const char *key, const char *defaultValueIfNotFound) const{
PropertyMap::const_iterator it;
it= propertyMap.find(key);
if(it==propertyMap.end()){
if(defaultValueIfNotFound != NULL) {
return string(defaultValueIfNotFound);
}
else {
throw runtime_error("Value not found in propertyMap: " + string(key) + ", loaded from: " + path);
}
}
else{
return it->second;
}
}
}}//end namepsace