- attempt to add "some" VBO rendering for static models (need to test if this improves performance in different environments)
This commit is contained in:
parent
2dc0d97f55
commit
dab57fcb34
|
@ -98,6 +98,7 @@ const char *GAME_ARGS[] = {
|
|||
"--log-path",
|
||||
"--show-ini-settings",
|
||||
"--disable-backtrace",
|
||||
"--disable-vbo",
|
||||
"--verbose"
|
||||
|
||||
};
|
||||
|
@ -120,6 +121,7 @@ enum GAME_ARG_TYPE {
|
|||
GAME_ARG_LOG_PATH,
|
||||
GAME_ARG_SHOW_INI_SETTINGS,
|
||||
GAME_ARG_DISABLE_BACKTRACE,
|
||||
GAME_ARG_DISABLE_VBO,
|
||||
GAME_ARG_VERBOSE_MODE
|
||||
};
|
||||
|
||||
|
@ -1576,6 +1578,12 @@ int glestMain(int argc, char** argv) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Explicitly disable VBO's
|
||||
if(config.getBool("DisableVBO","false") == true || hasCommandArgument(argc, argv,GAME_ARGS[GAME_ARG_DISABLE_VBO]) == true) {
|
||||
setVBOSupported(false);
|
||||
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("**WARNING** Disabling VBO's\n");
|
||||
}
|
||||
|
||||
// Setup the file crc thread
|
||||
std::auto_ptr<FileCRCPreCacheThread> preCacheThread;
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ void ObjectType::init(int modelCount, int objectClass, bool walkable, int height
|
|||
|
||||
void ObjectType::loadModel(const string &path){
|
||||
Model *model= Renderer::getInstance().newModel(rsGame);
|
||||
model->setIsStaticModel(true);
|
||||
model->load(path);
|
||||
color= Vec3f(0.f);
|
||||
if(model->getMeshCount()>0 && model->getMesh(0)->getTexture(0) != NULL) {
|
||||
|
|
|
@ -77,7 +77,6 @@ void ResourceType::load(const string &dir, Checksum* checksum, Checksum *techtre
|
|||
string path=dir+"/" + modelNode->getAttribute("path")->getRestrictedValue();
|
||||
|
||||
model= renderer.newModel(rsGame);
|
||||
model->setIsStaticModel(true);
|
||||
model->load(path);
|
||||
|
||||
//default resources
|
||||
|
|
|
@ -42,8 +42,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
void renderMesh(Mesh *mesh, bool isStaticModel);
|
||||
void renderMeshNormals(Mesh *mesh, bool isStaticModel);
|
||||
void renderMesh(Mesh *mesh);
|
||||
void renderMeshNormals(Mesh *mesh);
|
||||
};
|
||||
|
||||
}}}//end namespace
|
||||
|
|
|
@ -30,6 +30,10 @@ using Util::intToStr;
|
|||
// Globals
|
||||
// =====================================================
|
||||
|
||||
bool getVBOSupported();
|
||||
void setVBOSupported(bool value);
|
||||
|
||||
void overrideGlExtensionSupport(const char *extensionName,bool value);
|
||||
bool isGlExtensionSupported(const char *extensionName);
|
||||
bool isGlVersionSupported(int major, int minor, int release);
|
||||
const char *getGlVersion();
|
||||
|
|
|
@ -25,8 +25,6 @@ using std::string;
|
|||
using std::map;
|
||||
using std::pair;
|
||||
|
||||
//#define ENABLE_VBO_CODE
|
||||
|
||||
namespace Shared { namespace Graphics {
|
||||
|
||||
class Model;
|
||||
|
@ -74,14 +72,12 @@ private:
|
|||
InterpolationData *interpolationData;
|
||||
TextureManager *textureManager;
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
// Vertex Buffer Object Names
|
||||
bool hasBuiltVBOs;
|
||||
uint32 m_nVBOVertices; // Vertex VBO Name
|
||||
uint32 m_nVBOTexCoords; // Texture Coordinate VBO Name
|
||||
uint32 m_nVBONormals; // Normal VBO Name
|
||||
uint32 m_nVBOIndexes; // Indexes VBO Name
|
||||
#endif
|
||||
|
||||
public:
|
||||
//init & end
|
||||
|
@ -99,17 +95,13 @@ public:
|
|||
uint32 getIndexCount() const {return indexCount;}
|
||||
uint32 getTriangleCount() const;
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
uint32 getVBOVertices() const { return m_nVBOVertices;}
|
||||
uint32 getVBOTexCoords() const { return m_nVBOTexCoords;}
|
||||
uint32 getVBONormals() const { return m_nVBONormals;}
|
||||
uint32 getVBOIndexes() const { return m_nVBOIndexes;}
|
||||
|
||||
bool hasBuiltVBOEntities() const { return hasBuiltVBOs;}
|
||||
|
||||
void BuildVBOs();
|
||||
void ReleaseVBOs();
|
||||
#endif
|
||||
|
||||
//data
|
||||
const Vec3f *getVertices() const {return vertices;}
|
||||
|
@ -169,7 +161,6 @@ private:
|
|||
bool lastCycleVertex;
|
||||
|
||||
string fileName;
|
||||
bool isStaticModel;
|
||||
|
||||
public:
|
||||
//constructor & destructor
|
||||
|
@ -201,9 +192,6 @@ public:
|
|||
void setTextureManager(TextureManager *textureManager) {this->textureManager= textureManager;}
|
||||
void deletePixels();
|
||||
|
||||
bool getIsStaticModel() const { return isStaticModel; }
|
||||
void setIsStaticModel(bool value) { isStaticModel = value; }
|
||||
|
||||
string getFileName() const { return fileName; }
|
||||
|
||||
private:
|
||||
|
|
|
@ -107,7 +107,7 @@ void ModelRendererGl::render(Model *model) {
|
|||
//render every mesh
|
||||
//if(model->getIsStaticModel() == true) {
|
||||
for(uint32 i = 0; i < model->getMeshCount(); ++i) {
|
||||
renderMesh(model->getMeshPtr(i),model->getIsStaticModel());
|
||||
renderMesh(model->getMeshPtr(i));
|
||||
}
|
||||
//}
|
||||
//assertions
|
||||
|
@ -122,7 +122,7 @@ void ModelRendererGl::renderNormalsOnly(Model *model) {
|
|||
//render every mesh
|
||||
//if(model->getIsStaticModel() == true) {
|
||||
for(uint32 i=0; i<model->getMeshCount(); ++i) {
|
||||
renderMeshNormals(model->getMeshPtr(i),model->getIsStaticModel());
|
||||
renderMeshNormals(model->getMeshPtr(i));
|
||||
}
|
||||
//}
|
||||
|
||||
|
@ -132,7 +132,7 @@ void ModelRendererGl::renderNormalsOnly(Model *model) {
|
|||
|
||||
// ===================== PRIVATE =======================
|
||||
|
||||
void ModelRendererGl::renderMesh(Mesh *mesh, bool isStaticModel) {
|
||||
void ModelRendererGl::renderMesh(Mesh *mesh) {
|
||||
|
||||
//assertions
|
||||
assertGl();
|
||||
|
@ -183,11 +183,11 @@ void ModelRendererGl::renderMesh(Mesh *mesh, bool isStaticModel) {
|
|||
//assertions
|
||||
assertGl();
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
if(isStaticModel == true) {
|
||||
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() );
|
||||
|
@ -231,46 +231,10 @@ void ModelRendererGl::renderMesh(Mesh *mesh, bool isStaticModel) {
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
|
||||
/*
|
||||
//normals
|
||||
if(renderNormals) {
|
||||
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh->getVBONormals() );
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glNormalPointer(GL_FLOAT, 0, (char *) NULL);
|
||||
}
|
||||
else {
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
}
|
||||
//printf("Rendering Mesh WITHOUT VBO's\n");
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
else {
|
||||
if(duplicateTexCoords) {
|
||||
glActiveTexture(GL_TEXTURE0 + secondaryTexCoordUnit);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//vertices
|
||||
glVertexPointer(3, GL_FLOAT, 0, mesh->getInterpolationData()->getVertices());
|
||||
|
||||
|
@ -305,17 +269,14 @@ void ModelRendererGl::renderMesh(Mesh *mesh, bool isStaticModel) {
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
if(isStaticModel == true) {
|
||||
if(getVBOSupported() == true && mesh->getFrameCount() == 1) {
|
||||
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 );
|
||||
|
||||
//glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
else {
|
||||
//draw model
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount-1, indexCount, GL_UNSIGNED_INT, mesh->getIndices());
|
||||
}
|
||||
|
@ -324,7 +285,36 @@ void ModelRendererGl::renderMesh(Mesh *mesh, bool isStaticModel) {
|
|||
assertGl();
|
||||
}
|
||||
|
||||
void ModelRendererGl::renderMeshNormals(Mesh *mesh,bool isStaticModel) {
|
||||
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 );
|
||||
}
|
||||
else {
|
||||
//printf("Rendering Mesh Normals WITHOUT VBO's\n");
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for(unsigned int i = 0; i < mesh->getIndexCount(); ++i) {
|
||||
|
@ -336,5 +326,6 @@ void ModelRendererGl::renderMeshNormals(Mesh *mesh,bool isStaticModel) {
|
|||
}
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
}}}//end namespace
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ==============================================================
|
||||
// This file is part of Glest Shared Library (www.glest.org)
|
||||
//
|
||||
// Copyright (C) 2001-2008 Martiño Figueroa
|
||||
// Copyright (C) 2001-2008 Marti<EFBFBD>o Figueroa
|
||||
//
|
||||
// You can redistribute this code and/or modify it under
|
||||
// the terms of the GNU General Public License as published
|
||||
|
@ -16,32 +16,60 @@
|
|||
#include "graphics_interface.h"
|
||||
#include "context_gl.h"
|
||||
#include "gl_wrap.h"
|
||||
#include <map>
|
||||
#include "util.h"
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::Util;
|
||||
using namespace std;
|
||||
|
||||
namespace Shared { namespace Graphics { namespace Gl {
|
||||
|
||||
std::map<string,bool> cacheExtensionCheckList;
|
||||
static int vboEnabled = 0;
|
||||
|
||||
// =====================================================
|
||||
// class Globals
|
||||
// =====================================================
|
||||
|
||||
bool getVBOSupported() {
|
||||
if(vboEnabled == 0) {
|
||||
bool value = isGlExtensionSupported("GL_ARB_vertex_buffer_object");
|
||||
vboEnabled = (value == true ? 1 : -1);
|
||||
}
|
||||
return (vboEnabled == 1);
|
||||
}
|
||||
void setVBOSupported(bool value) {
|
||||
vboEnabled = (value == true ? 1 : -1);
|
||||
};
|
||||
|
||||
void overrideGlExtensionSupport(const char *extensionName,bool value) {
|
||||
cacheExtensionCheckList[extensionName]=value;
|
||||
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("OpenGL Extension [%s] supported status FORCED TO = %d\n",extensionName,cacheExtensionCheckList[extensionName]);
|
||||
}
|
||||
|
||||
bool isGlExtensionSupported(const char *extensionName) {
|
||||
if(cacheExtensionCheckList.find(extensionName) != cacheExtensionCheckList.end()) {
|
||||
return cacheExtensionCheckList[extensionName];
|
||||
}
|
||||
const GLubyte *extensionStr= glGetString(GL_EXTENSIONS);
|
||||
const char *s= reinterpret_cast<const char *>(extensionStr);
|
||||
size_t len= strlen(extensionName);
|
||||
|
||||
cacheExtensionCheckList[extensionName]=false;
|
||||
if(s != NULL) {
|
||||
while ((s = strstr (s, extensionName)) != NULL) {
|
||||
s+= len;
|
||||
if((*s == ' ') || (*s == '\0')) {
|
||||
return true;
|
||||
cacheExtensionCheckList[extensionName] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("OpenGL Extension [%s] supported status = %d\n",extensionName,cacheExtensionCheckList[extensionName]);
|
||||
return cacheExtensionCheckList[extensionName];
|
||||
}
|
||||
|
||||
bool isGlVersionSupported(int major, int minor, int release) {
|
||||
|
|
|
@ -19,17 +19,12 @@
|
|||
#include "conversion.h"
|
||||
#include "util.h"
|
||||
#include "platform_common.h"
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
|
||||
#include "opengl.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "leak_dumper.h"
|
||||
|
||||
using namespace Shared::Platform;
|
||||
using namespace Shared::PlatformCommon;
|
||||
using namespace Shared::Graphics::Gl;
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -65,15 +60,12 @@ Mesh::Mesh() {
|
|||
twoSided= false;
|
||||
customColor= false;
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
hasBuiltVBOs = false;
|
||||
// Vertex Buffer Object Names
|
||||
m_nVBOVertices = 0;
|
||||
m_nVBOTexCoords = 0;
|
||||
m_nVBONormals = 0;
|
||||
m_nVBOIndexes = 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Mesh::~Mesh() {
|
||||
|
@ -88,10 +80,7 @@ void Mesh::init() {
|
|||
}
|
||||
|
||||
void Mesh::end() {
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
void ReleaseVBOs();
|
||||
#endif
|
||||
ReleaseVBOs();
|
||||
|
||||
delete [] vertices;
|
||||
delete [] normals;
|
||||
|
@ -127,9 +116,8 @@ void Mesh::updateInterpolationVertices(float t, bool cycle) {
|
|||
interpolationData->updateVertices(t, cycle);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_VBO_CODE)
|
||||
|
||||
void Mesh::BuildVBOs() {
|
||||
if(getVBOSupported() == true) {
|
||||
if(hasBuiltVBOs == false) {
|
||||
//printf("In [%s::%s Line: %d] setting up a VBO...\n",__FILE__,__FUNCTION__,__LINE__);
|
||||
|
||||
|
@ -170,8 +158,10 @@ void Mesh::BuildVBOs() {
|
|||
hasBuiltVBOs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::ReleaseVBOs() {
|
||||
if(getVBOSupported() == true) {
|
||||
if(hasBuiltVBOs == true) {
|
||||
glDeleteBuffersARB( 1, &m_nVBOVertices ); // Get A Valid Name
|
||||
glDeleteBuffersARB( 1, &m_nVBOTexCoords ); // Get A Valid Name
|
||||
|
@ -179,8 +169,7 @@ void Mesh::ReleaseVBOs() {
|
|||
glDeleteBuffersARB( 1, &m_nVBOIndexes ); // Get A Valid Name
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ==================== load ====================
|
||||
|
||||
|
@ -465,7 +454,6 @@ Model::Model(){
|
|||
lastCycleData = false;
|
||||
lastTVertex = -1;
|
||||
lastCycleVertex = false;
|
||||
isStaticModel = false;
|
||||
}
|
||||
|
||||
Model::~Model() {
|
||||
|
@ -486,7 +474,6 @@ void Model::updateInterpolationData(float t, bool cycle) {
|
|||
for(unsigned int i = 0; i < meshCount; ++i) {
|
||||
meshes[i].updateInterpolationData(t, cycle);
|
||||
}
|
||||
//if(isStaticModel) printf("In [%s::%s Line: %d] filename [%s] t = [%f] cycle = [%d] lastTData = [%f] lastCycleData [%d]\n",__FILE__,__FUNCTION__,__LINE__,this->fileName.c_str(),t,cycle,lastTData,lastCycleData);
|
||||
lastTData = t;
|
||||
lastCycleData = cycle;
|
||||
}
|
||||
|
@ -497,7 +484,6 @@ void Model::updateInterpolationVertices(float t, bool cycle) {
|
|||
for(unsigned int i = 0; i < meshCount; ++i) {
|
||||
meshes[i].updateInterpolationVertices(t, cycle);
|
||||
}
|
||||
//if(isStaticModel) printf("In [%s::%s Line: %d] filename [%s] t = [%f] cycle = [%d] lastTData = [%f] lastCycleData [%d]\n",__FILE__,__FUNCTION__,__LINE__,this->fileName.c_str(),t,cycle,lastTData,lastCycleData);
|
||||
lastTVertex = t;
|
||||
lastCycleVertex = cycle;
|
||||
}
|
||||
|
@ -620,15 +606,6 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad) {
|
|||
meshes[i].load(dir, f, textureManager,deletePixMapAfterLoad);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
|
||||
//#if defined(ENABLE_VBO_CODE)
|
||||
// if(isStaticModel == true) {
|
||||
// this->updateInterpolationData(0.f, true);
|
||||
// for(uint32 i=0; i<meshCount; ++i){
|
||||
// meshes[i].BuildVBOs();
|
||||
// }
|
||||
// }
|
||||
//#endif
|
||||
}
|
||||
//version 3
|
||||
else if(fileHeader.version==3){
|
||||
|
@ -639,15 +616,6 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad) {
|
|||
meshes[i].loadV3(dir, f, textureManager,deletePixMapAfterLoad);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
|
||||
//#if defined(ENABLE_VBO_CODE)
|
||||
// if(isStaticModel == true) {
|
||||
// this->updateInterpolationData(0.f, true);
|
||||
// for(uint32 i=0; i<meshCount; ++i){
|
||||
// meshes[i].BuildVBOs();
|
||||
// }
|
||||
// }
|
||||
//#endif
|
||||
}
|
||||
//version 2
|
||||
else if(fileHeader.version==2) {
|
||||
|
@ -657,15 +625,6 @@ void Model::loadG3d(const string &path, bool deletePixMapAfterLoad) {
|
|||
meshes[i].loadV2(dir, f, textureManager,deletePixMapAfterLoad);
|
||||
meshes[i].buildInterpolationData();
|
||||
}
|
||||
|
||||
//#if defined(ENABLE_VBO_CODE)
|
||||
// if(isStaticModel == true) {
|
||||
// this->updateInterpolationData(0.f, true);
|
||||
// for(uint32 i=0; i<meshCount; ++i){
|
||||
// meshes[i].BuildVBOs();
|
||||
// }
|
||||
// }
|
||||
//#endif
|
||||
}
|
||||
else {
|
||||
throw runtime_error("Invalid model version: "+ intToStr(fileHeader.version));
|
||||
|
|
Loading…
Reference in New Issue
Block a user