Compare commits

..

1 Commits

40 changed files with 1608 additions and 703 deletions

3
.gitignore vendored
View File

@ -9,8 +9,7 @@
/stderr.txt /stderr.txt
/sdl_keymap.h /sdl_keymap.h
/sdl_keymap.cc /sdl_keymap.cc
/cfs.cc /ag_lua.cc
/cfs.h
# /libsrc/ # /libsrc/
/libsrc/*.blend1 /libsrc/*.blend1

15
.gitmodules vendored
View File

@ -1,15 +0,0 @@
[submodule "cfs_gen"]
path = cfs_gen
url = ../util/cfs_gen.git
[submodule "wfobj"]
path = wfobj
url = ../util/wfobj.git
[submodule "refptr"]
path = refptr
url = ../util/refptr.git
[submodule "TextureCache"]
path = TextureCache
url = ../util/TextureCache.git
[submodule "glslUtil"]
path = glslUtil
url = ../util/glslUtil.git

88
FileLoader/FileLoader.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef FILELOADER_H
#define FILELOADER_H FILELOADER_H
#include <string>
#include <iostream>
class FileLoader
{
public:
class Path
{
public:
std::string fullPath;
std::string shortPath;
Path() { }
Path(const std::string & full_path,
const std::string & short_path)
: fullPath(full_path), shortPath(short_path) { }
std::string toString() const
{
std::string ret;
if (shortPath != "")
ret += shortPath + ",";
if (fullPath != "")
ret += fullPath;
return ret;
}
};
class Buffer
{
public:
char * data;
int size;
Buffer(int sz)
{
size = sz;
data = new char[size];
_refcnt = new int;
*_refcnt = 1;
m_alloced = true;
}
Buffer(char * data, int sz)
{
size = sz;
this->data = data;
m_alloced = false;
}
void copy(const Buffer & other)
{
data = other.data;
size = other.size;
m_alloced = other.m_alloced;
if (m_alloced)
{
_refcnt = other._refcnt;
(*_refcnt)++;
}
}
Buffer(const Buffer & other) { copy(other); }
Buffer & operator=(const Buffer & other)
{
copy(other);
return *this;
}
~Buffer()
{
if (m_alloced)
{
(*_refcnt)--;
if (*_refcnt < 1)
{
delete _refcnt;
delete data;
}
}
}
protected:
int * _refcnt;
bool m_alloced;
};
virtual int getSize(const Path & path) = 0;
virtual Buffer load(const Path & path) = 0;
};
#endif

View File

@ -41,9 +41,12 @@ PhyObj::Geom::Geom(PhyObj::GeomType type, refptr< vector<float> > args)
/********** PhyObj functions **********/ /********** PhyObj functions **********/
void PhyObj::load(const unsigned char *data, unsigned int size) void PhyObj::load(FileLoader * fileLoader, const FileLoader::Path & path)
{ {
string str((char *) data, size); FileLoader::Buffer buff = fileLoader->load(path);
if (buff.size <= 0)
return;
string str(buff.data, buff.size);
stringstream istr(str, ios_base::in); stringstream istr(str, ios_base::in);
while (!istr.eof()) while (!istr.eof())
{ {

View File

@ -3,6 +3,7 @@
#define PHYOBJ_H #define PHYOBJ_H
#include "refptr/refptr.h" #include "refptr/refptr.h"
#include "FileLoader/FileLoader.h"
#include <vector> #include <vector>
class PhyObj class PhyObj
@ -28,7 +29,7 @@ class PhyObj
}; };
/* Methods */ /* Methods */
void load(const unsigned char *data, unsigned int size); void load(FileLoader * fileLoader, const FileLoader::Path & path);
size_t getNumGeoms() { return m_geoms.size(); } size_t getNumGeoms() { return m_geoms.size(); }
refptr<Geom> getGeom(int i) { return m_geoms[i]; } refptr<Geom> getGeom(int i) { return m_geoms[i]; }

View File

@ -16,6 +16,7 @@ if os.sep == '\\':
platform = 'PLATFORM_WINDOWS' platform = 'PLATFORM_WINDOWS'
else: else:
platform = 'PLATFORM_LINUX' platform = 'PLATFORM_LINUX'
subdirs = ['WFObj', 'PhyObj', 'TextureCache', 'OdeWorld']
env = Environment() env = Environment()
env.ParseConfig('pkg-config --cflags --libs lua5.1') env.ParseConfig('pkg-config --cflags --libs lua5.1')
@ -30,46 +31,44 @@ if platform == 'PLATFORM_WINDOWS':
if platform == 'PLATFORM_LINUX': if platform == 'PLATFORM_LINUX':
env.Append(LIBS = ['GL', 'GLU']) env.Append(LIBS = ['GL', 'GLU'])
env.Append(CPPFLAGS = ['-D'+platform, '-I.', '-DGL_GLEXT_PROTOTYPES']) env.Append(CPPFLAGS = ['-D'+platform, '-I.'])
env.Append(LIBS = ['SDL_image', 'SDL_sound', 'vorbisfile']) env.Append(LIBS = ['SDL_image', 'SDL_sound', 'vorbisfile'])
env.Append(CCFLAGS = ['-O2', '-Wall']) env.Append(CCFLAGS = ['-O2', '-Wall'])
if DEBUG: if DEBUG:
env.Append(CCFLAGS = ['-g']) env.Append(CCFLAGS = ['-g'])
sources = [ sources = [Glob('src/*.cc'), 'ag_lua.cc', 'sdl_keymap.cc']
'cfs.cc', for sd in subdirs:
'sdl_keymap.cc', sources += [Glob(sd + '/*.c'), Glob(sd + '/*.cc')]
Glob('src/*.cc'),
'OdeWorld/OdeWorld.cc',
'PhyObj/PhyObj.cc',
'TextureCache/TextureCache.cc',
'wfobj/WFObj.cc',
'glslUtil/glslUtil.c',
]
def CFS(target, source, env): def F2C(target, source, env):
source_list = [] f = open(str(target[0]), 'w')
for s in source: for s in source:
source_list.append(str(s)) c_name = re.sub(r'\W', '_', str(s).split('/')[-1])
Popen(['./cfs_gen/cfs_gen.py', str(target[0])] + source_list).wait() f.write('unsigned char %s[] = {' % c_name)
src = open(str(s), 'r')
s_len = 0
while 1:
if s_len % 12 == 0:
f.write('\n ')
ch = src.read(1)
if len(ch) < 1:
break
s_len += 1
f.write('0x%02x, ' % ord(ch))
f.write('0x00\n')
src.close()
f.write('};\n')
f.write('unsigned int %s_len = %d;\n' % (c_name, s_len))
f.close()
return None return None
def CFS_emitter(target, source, env):
target.append(re.sub(r'\.cc?', '.h', str(target[0])))
return target, source
def bt(cmd): def bt(cmd):
return Popen(cmd, shell = True, stdout = PIPE).communicate()[0] return Popen(cmd, shell = True, stdout = PIPE).communicate()[0]
env.Append(BUILDERS = {'CFS' : Builder(action = CFS, emitter = CFS_emitter)}) env.Append(BUILDERS = {'F2C' : Builder(action = F2C)})
cfs_sources = [ env.F2C('ag_lua.cc', 'src/ag.lua')
'src/ag.lua',
Glob('shaders/*'),
]
env.CFS('cfs.cc', cfs_sources)
env.Depends('cfs.cc', 'cfs_gen/cfs_gen.py')
env.Command('sdl_keymap.cc', 'gen-sdl-keymap.pl', 'perl gen-sdl-keymap.pl') env.Command('sdl_keymap.cc', 'gen-sdl-keymap.pl', 'perl gen-sdl-keymap.pl')
env.Program(target, sources) env.Program(target, sources)

@ -1 +0,0 @@
Subproject commit 60b16263424cd3828db389e1730eae87439cfe03

12
TextureCache/Makefile Normal file
View File

@ -0,0 +1,12 @@
TARGET := TextureCache.o
SOURCES := $(wildcard *.cc)
HEADERS := $(wildcard *.h)
all: $(TARGET)
$(TARGET): $(SOURCES) $(HEADERS)
$(CXX) -c -o $@ $(CXXFLAGS) $(SOURCES)
clean:
-rm -f *~ *.o

View File

@ -0,0 +1,143 @@
#include <SDL.h>
#include <SDL_image.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <iostream>
#include "TextureCache.h"
#include "TextureLoader/TextureLoader.h"
#include "FileLoader/FileLoader.h"
using namespace std;
//#define DEBUG_GL_ERROR
#ifdef DEBUG_GL_ERROR
#define checkGLError() checkGLErrorLine(__FUNCTION__, __LINE__)
static void checkGLErrorLine(const char * function, int line)
{
GLenum err = glGetError();
if (err != 0)
{
cerr << "gl error in " << function
<< ": " << err << " (0x" << hex << err << ") at line "
<< dec << line << endl;
}
}
#else
#define checkGLError()
#endif
TextureCache::~TextureCache()
{
}
GLuint TextureCache::load(const FileLoader::Path & path,
FileLoader & fileLoader, bool mipmaps,
int mode, int quality)
{
string filename = path.shortPath;
if (filename == "")
filename = path.fullPath;
if (filename == "")
return 0;
map<string,GLuint>::iterator it = m_cache.find(filename);
if (it != m_cache.end())
{
return it->second;
}
GLuint tex = loadTexture(path, fileLoader, mipmaps, mode, quality);
if (tex > 0)
{
m_cache[filename] = tex;
}
return tex;
}
GLuint TextureCache::loadTexture(const FileLoader::Path & path,
FileLoader & fileLoader, bool mipmaps,
int mode, int quality)
{
checkGLError();
GLuint texture;
FileLoader::Buffer buff = fileLoader.load(path);
if (buff.size <= 0)
return 0;
SDL_RWops * ops = SDL_RWFromMem(buff.data, buff.size);
SDL_Surface * temp = IMG_Load_RW(ops, true);
if (!temp)
{
cerr << "Failed to load image ('" << path.fullPath << "', '"
<< path.shortPath << "'): " << IMG_GetError() << endl;
return 0;
}
SDL_PixelFormat fmt;
fmt.palette = NULL;
fmt.BitsPerPixel = 32;
fmt.BytesPerPixel = 4;
fmt.Rmask = 0x000000FF;
fmt.Gmask = 0x0000FF00;
fmt.Bmask = 0x00FF0000;
fmt.Amask = 0xFF000000;
fmt.Rshift = 0;
fmt.Gshift = 8;
fmt.Bshift = 16;
fmt.Ashift = 24;
SDL_Surface * texsurf = SDL_ConvertSurface(temp, &fmt, SDL_SWSURFACE);
SDL_FreeSurface(temp);
if (!texsurf)
{
cerr << "Image was not converted properly!" << endl;
return 0;
}
unsigned int * pixels = new unsigned int[texsurf->w * texsurf->h];
int y;
unsigned int dstOffset = texsurf->w * (texsurf->h - 1);
unsigned int srcOffset = 0;
for (y = 0; y < texsurf->h; y++)
{
memcpy(pixels + dstOffset,
((unsigned int *)texsurf->pixels) + srcOffset,
texsurf->w << 2);
dstOffset -= texsurf->w;
srcOffset += texsurf->w;
}
glGenTextures(1, &texture);
checkGLError();
glBindTexture(GL_TEXTURE_2D, texture);
checkGLError();
glTexImage2D(GL_TEXTURE_2D, 0, 4, texsurf->w, texsurf->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels);
if (quality > 0)
{
checkGLError();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
checkGLError();
}
else
{
checkGLError();
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
checkGLError();
}
checkGLError();
if (mipmaps)
{
checkGLError();
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,
texsurf->w, texsurf->h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
checkGLError();
}
SDL_FreeSurface(texsurf);
delete[] pixels;
checkGLError();
return texture;
}

View File

@ -0,0 +1,30 @@
#ifndef TEXTURECACHE_H
#define TEXTURECACHE_H TEXTURECACHE_H
#include <SDL.h>
#include <GL/gl.h>
#include <map>
#include <string>
#include "TextureLoader/TextureLoader.h"
#include "FileLoader/FileLoader.h"
class TextureCache : public TextureLoader
{
public:
virtual ~TextureCache();
virtual GLuint load(const FileLoader::Path & path,
FileLoader & fileLoader, bool mipmaps = true,
int mode = GL_DECAL, int quality = 1);
protected:
/* methods */
GLuint loadTexture(const FileLoader::Path & path,
FileLoader & fileLoader, bool mipmaps,
int mode, int quality);
/* data */
std::map< std::string, GLuint > m_cache;
};
#endif

View File

@ -0,0 +1,18 @@
#ifndef TEXTURELOADER_H
#define TEXTURELOADER_H TEXTURELOADER_H
#include <string>
#include <GL/gl.h>
#include "FileLoader/FileLoader.h"
class TextureLoader
{
public:
virtual GLuint load(
const FileLoader::Path & path,
FileLoader & fileLoader, bool mipmaps = true,
int mode = GL_DECAL, int quality = 1) = 0;
};
#endif

10
WFObj/Makefile Normal file
View File

@ -0,0 +1,10 @@
TARGET := WFObj.o
all: $(TARGET)
%.o: %.cc
$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $<
clean:
-rm -f *~ *.o

18
WFObj/Makefile.driver Normal file
View File

@ -0,0 +1,18 @@
CXX := g++
CXXFLAGS := -O2
SOURCE := WFObj.cc driver.cc
OBJS := $(SOURCE:.cc=.o)
LDFLAGS := -lGL
TARGET := driver
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) -o $@ $^ $(LDFLAGS)
%.o: %.cc %.hh
$(CXX) -c -o $@ $< $(CXXFLAGS)
clean:
-rm -f *~ *.o $(TARGET)

703
WFObj/WFObj.cc Normal file
View File

@ -0,0 +1,703 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h> // isspace()
#include <string.h> // strlen()
#include <GL/gl.h>
#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
#include "WFObj.h"
using namespace std;
#define WHITESPACE " \n\r\t\v"
//#define DEBUGGL
/****** static functions ******/
static string trimString(string s)
{
size_t lastpos = s.find_last_not_of(WHITESPACE);
if (lastpos == string::npos)
return "";
s.erase(lastpos + 1);
s.erase(0, s.find_first_not_of(WHITESPACE));
return s;
}
static string stripFirstToken(string & input)
{
size_t firstnonspace = input.find_first_not_of(WHITESPACE);
if (firstnonspace == string::npos)
return "";
size_t spaceafter = input.find_first_of(WHITESPACE, firstnonspace);
string token = input.substr(firstnonspace, spaceafter - firstnonspace);
input.erase(0, spaceafter);
return token;
}
static vector<string> splitString(const string & str, char delim)
{
vector<string> ret;
string s = str;
size_t pos;
while ( (pos = s.find(delim)) != string::npos )
{
string t = s.substr(0, pos);
ret.push_back(t);
s.erase(0, pos + 1);
}
if (s != "")
ret.push_back(s);
return ret;
}
static string basePath(const string & str)
{
string path = str;
size_t pos;
if ( (pos = path.find_last_of("/\\")) != string::npos )
{
path.erase(pos + 1);
return path;
}
return "";
}
//#define DEBUG_GL_ERROR
#ifdef DEBUG_GL_ERROR
#define checkGLError() checkGLErrorLine(__FUNCTION__, __LINE__)
static void checkGLErrorLine(const char * function, int line)
{
GLenum err = glGetError();
if (err != 0)
{
cerr << "gl error in " << function
<< ": " << err << " (0x" << hex << err << ") at line "
<< dec << line << endl;
}
}
#else
#define checkGLError()
#endif
/****** WFObj functions ******/
WFObj::WFObj()
{
init();
}
WFObj::WFObj(FileLoader & fileLoader)
{
init(&fileLoader);
}
WFObj::WFObj(TextureLoader & textureLoader)
{
init(NULL, &textureLoader);
}
WFObj::WFObj(FileLoader & fileLoader, TextureLoader & textureLoader)
{
init(&fileLoader, &textureLoader);
}
void WFObj::init (FileLoader * fileLoader,
TextureLoader * textureLoader)
{
m_fileLoader = fileLoader;
if (m_fileLoader == NULL)
{
m_fileLoader = new WFFileLoader();
m_iCreatedFileLoader = true;
}
else
{
m_iCreatedFileLoader = false;
}
m_textureLoader = textureLoader;
}
WFObj::~WFObj()
{
if (m_iCreatedFileLoader)
delete m_fileLoader;
}
void WFObj::clear()
{
m_data = std::vector< std::vector<std::string> >();
m_loadedVertex = false;
}
bool WFObj::load(const FileLoader::Path & path)
{
clear();
FileLoader::Buffer buff = m_fileLoader->load(path);
if (buff.size <= 0)
return false;
m_path = path;
string str(buff.data, buff.size);
stringstream istr(str, ios_base::in);
load(istr, buff.size);
return true;
}
bool WFObj::load(std::istream & istr, unsigned int size)
{
char buf[size+1];
string buildup;
while (istr.good())
{
istr.getline(buf, size+1);
string input = trimString(buf);
int sz = input.size();
if (sz == 0 || input[0] == '#')
continue;
if (input[sz-1] == '\\')
{
input[sz-1] = ' ';
buildup = input;
continue;
}
if (buildup != "")
input = buildup + input;
buildup = "";
processInputLine(input);
}
return true;
}
void WFObj::processInputLine(const std::string & input)
{
string line = input;
vector<string> lineParts;
for (;;)
{
string token = stripFirstToken(line);
if (token == "")
break;
lineParts.push_back(token);
}
if (lineParts.size() > 0)
m_data.push_back(lineParts);
}
GLuint WFObj::render(bool doTextureInfo, bool enableBlending)
{
checkGLError();
GLuint list = glGenLists(1);
glNewList(list, GL_COMPILE);
int len = m_data.size();
enum { VERTEX, VERTEX_TEXTURE, VERTEX_NORMAL, VERTEX_TYPES };
vector<Vertex> vertices[VERTEX_TYPES];
int numVertsLast = 0;
bool inFace = false;
bool inMaterial = false;
string currentMaterialName;
WFMtl material(this);
for (int i = 0; i < len; i++)
{
string type = m_data[i][0];
if (type == "v")
{
Vertex v = readVertex(m_data[i]);
updateAABB(v.getData());
vertices[VERTEX].push_back(v);
}
else if (type == "vt")
vertices[VERTEX_TEXTURE].push_back(readVertex(m_data[i]));
else if (type == "vn")
vertices[VERTEX_NORMAL].push_back(readVertex(m_data[i]));
else if (type == "f")
{
int numVerts = m_data[i].size() - 1;
if (inFace && (numVerts != numVertsLast || numVertsLast > 4))
{
#ifdef DEBUGGL
cout << "glEnd()" << endl;
#endif
glEnd();
inFace = false;
}
if (!inFace)
{
if (numVerts == 3)
{
#ifdef DEBUGGL
cout << "glBegin(GL_TRIANGLES)" << endl;
#endif
glBegin(GL_TRIANGLES);
}
else if (numVerts == 4)
{
#ifdef DEBUGGL
cout << "glBegin(GL_QUADS)" << endl;
#endif
glBegin(GL_QUADS);
}
else
{
#ifdef DEBUGGL
cout << "glBegin(GL_POLYGON)" << endl;
#endif
glBegin(GL_POLYGON);
}
inFace = true;
}
for (int v = 1; v <= numVerts; v++)
{
int vertexIndices[3] = {0, 0, 0};
parseVertexIndices(m_data[i][v], vertexIndices);
for (int j = 0; j < 3; j++)
{
if (vertexIndices[j] < 0)
vertexIndices[j] += vertices[j].size() + 1;
}
bool valid = true;
for (int j = 0; j < 3; j++)
{
if (vertexIndices[j] > (int) vertices[j].size())
{
valid = false;
break;
}
}
if (vertexIndices[VERTEX] <= 0)
valid = false;
if (!valid)
continue;
if (vertexIndices[VERTEX_NORMAL] != 0)
{
/* a normal is present */
#ifdef DEBUGGL
cout << " glNormal3f(" <<
vertices[VERTEX_NORMAL][vertexIndices[VERTEX_NORMAL]-1]
[0] << ", " <<
vertices[VERTEX_NORMAL][vertexIndices[VERTEX_NORMAL]-1]
[1] << ", " <<
vertices[VERTEX_NORMAL][vertexIndices[VERTEX_NORMAL]-1]
[2] << ")" << endl;
#endif
glNormal3fv(vertices[VERTEX_NORMAL]
[vertexIndices[VERTEX_NORMAL]-1].getData());
}
if (vertexIndices[VERTEX_TEXTURE] != 0)
{
/* a texture coordinate is present */
#ifdef DEBUGGL
cout << " glTexCoord2f(" <<
vertices[VERTEX_TEXTURE][vertexIndices[VERTEX_TEXTURE]-1]
[0] << ", " <<
vertices[VERTEX_TEXTURE][vertexIndices[VERTEX_TEXTURE]-1]
[1] << ')' << endl;
#endif
glTexCoord2fv(vertices[VERTEX_TEXTURE]
[vertexIndices[VERTEX_TEXTURE]-1].getData());
}
#ifdef DEBUGGL
cout << " glVertex3f(" <<
vertices[VERTEX][vertexIndices[VERTEX]-1][0] << ", " <<
vertices[VERTEX][vertexIndices[VERTEX]-1][1] << ", " <<
vertices[VERTEX][vertexIndices[VERTEX]-1][2] << ")" <<
" [" << vertexIndices[VERTEX] << "]" << endl;
#endif
glVertex3fv(vertices[VERTEX][vertexIndices[VERTEX]-1].getData());
}
numVertsLast = numVerts;
}
else if (type == "usemtl")
{
if (inFace)
{
#ifdef DEBUGGL
cout << "glEnd()" << endl;
#endif
glEnd();
inFace = false;
}
if (inMaterial)
{
material.renderEnd(currentMaterialName, doTextureInfo,
enableBlending);
inMaterial = false;
}
if (m_data[i].size() >= 2)
{
currentMaterialName = m_data[i][1];
material.renderBegin(currentMaterialName, doTextureInfo,
enableBlending);
inMaterial = true;
}
}
else if (type == "mtllib")
{
if (m_data[i].size() >= 2)
{
FileLoader::Path path(
basePath(m_path.fullPath) + m_data[i][1],
m_data[i][1]);
material.load(path);
}
}
}
if (inFace)
{
#ifdef DEBUGGL
cout << "glEnd()" << endl;
#endif
glEnd();
inFace = false;
}
if (inMaterial)
{
material.renderEnd(currentMaterialName, doTextureInfo, enableBlending);
inMaterial = false;
}
glEndList();
checkGLError();
return list;
}
void WFObj::updateAABB(const float * const vertex)
{
if (m_loadedVertex)
{
if (vertex[0] < m_aabb[0])
m_aabb[0] = vertex[0];
else if (vertex[0] > m_aabb[3])
m_aabb[3] = vertex[0];
if (vertex[1] < m_aabb[1])
m_aabb[1] = vertex[1];
else if (vertex[1] > m_aabb[4])
m_aabb[4] = vertex[1];
if (vertex[2] < m_aabb[2])
m_aabb[2] = vertex[2];
else if (vertex[2] > m_aabb[5])
m_aabb[5] = vertex[2];
}
else
{
m_aabb[0] = m_aabb[3] = vertex[0];
m_aabb[1] = m_aabb[4] = vertex[1];
m_aabb[2] = m_aabb[5] = vertex[2];
m_loadedVertex = true;
}
}
WFObj::Vertex WFObj::readVertex(const vector<string> & parts)
{
int partslen = parts.size();
Vertex v;
for (int i = 1; i < partslen && i <= 4; i++)
{
sscanf(parts[i].c_str(), "%f", &v[i - 1]);
}
return v;
}
void WFObj::parseVertexIndices(const string & vtxref, int * ret)
{
vector<string> parts = splitString(vtxref, '/');
int num = parts.size();
for (int i = 0; i < num && i < 3; i++)
sscanf(parts[i].c_str(), "%d", ret + i);
}
/****** WFMtl functions ******/
void WFObj::WFMtl::clear()
{
m_data = map< string, vector< vector<string> > >();
m_currentMaterialName = "";
m_attributesPushed = false;
}
bool WFObj::WFMtl::load(const FileLoader::Path & path)
{
clear();
FileLoader::Buffer buff = m_obj->m_fileLoader->load(path);
if (buff.size <= 0)
return false;
m_path = path;
string str(buff.data, buff.size);
stringstream istr(str, ios_base::in);
load(istr, buff.size);
return true;
}
bool WFObj::WFMtl::load(std::istream & istr, unsigned int size)
{
char buf[size+1];
string buildup;
while (istr.good())
{
istr.getline(buf, size+1);
string input = trimString(buf);
int sz = input.size();
if (sz == 0 || input[0] == '#')
continue;
if (input[sz-1] == '\\')
{
input[sz-1] = ' ';
buildup = input;
continue;
}
if (buildup != "")
input = buildup + input;
buildup = "";
processInputLine(input);
}
return true;
}
void WFObj::WFMtl::processInputLine(const std::string & input)
{
string line = input;
vector<string> lineParts;
for (;;)
{
string token = stripFirstToken(line);
if (token == "")
break;
lineParts.push_back(token);
}
if (lineParts.size() > 0)
{
if ( (lineParts.size() >= 2) && (lineParts[0] == "newmtl") )
{
m_currentMaterialName = lineParts[1];
}
else if (m_currentMaterialName != "")
{
m_data[m_currentMaterialName].push_back(lineParts);
}
}
}
void WFObj::WFMtl::renderBegin(const string & mtlname, bool doTextureInfo,
bool enableBlending)
{
map< string, vector< vector<string> > >::iterator it = m_data.find(mtlname);
if (it == m_data.end())
return;
vector< vector<string> > & stmts = it->second;
int num_stmts = stmts.size();
bool foundTexture = false;
bool didSomething = false;
checkGLError();
for (int i = 0; i < num_stmts; i++)
{
string & type = stmts[i][0];
if (type == "Ka") /* set ambient color */
{
if ( (stmts[i].size() == 4) && (stmts[i][1] != "spectral") )
{
pushAttributes();
float mat[4] = {0.0f, 0.0f, 0.0f, 1.0f};
for (int j = 0; j < 3; j++)
sscanf(stmts[i][j+1].c_str(), "%f", &mat[j]);
#ifdef DEBUGGL
cout << " glMaterialfv(GL_FRONT, GL_AMBIENT, {";
for (int j = 0; j < 4; j++)
cout << mat[j] << (j < 3 ? ", " : "})");
cout << endl;
#endif
glMaterialfv(GL_FRONT, GL_AMBIENT, mat);
didSomething = true;
}
}
else if (type == "Kd") /* set diffuse color */
{
if ( (stmts[i].size() == 4) && (stmts[i][1] != "spectral") )
{
pushAttributes();
float mat[4] = {0.0f, 0.0f, 0.0f, 1.0f};
for (int j = 0; j < 3; j++)
sscanf(stmts[i][j+1].c_str(), "%f", &mat[j]);
#ifdef DEBUGGL
cout << " glMaterialfv(GL_FRONT, GL_DIFFUSE, {";
for (int j = 0; j < 4; j++)
cout << mat[j] << (j < 3 ? ", " : "})");
cout << endl;
#endif
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat);
didSomething = true;
}
}
else if (type == "Ks") /* set specular color */
{
if ( (stmts[i].size() == 4) && (stmts[i][1] != "spectral") )
{
pushAttributes();
float mat[4] = {0.0f, 0.0f, 0.0f, 1.0f};
for (int j = 0; j < 3; j++)
sscanf(stmts[i][j+1].c_str(), "%f", &mat[j]);
#ifdef DEBUGGL
cout << " glMaterialfv(GL_FRONT, GL_SPECULAR, {";
for (int j = 0; j < 4; j++)
cout << mat[j] << (j < 3 ? ", " : "})");
cout << endl;
#endif
glMaterialfv(GL_FRONT, GL_SPECULAR, mat);
didSomething = true;
}
}
else if (type == "Ns") /* set shininess */
{
if (stmts[i].size() == 2)
{
pushAttributes();
GLfloat shininess = 0.0f;
sscanf(stmts[i][1].c_str(), "%f", &shininess);
#ifdef DEBUGGL
cout << " glMaterialf(GL_FRONT, GL_SHININESS, "
<< shininess << ")" << endl;
#endif
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
didSomething = true;
}
}
else if (type == "map_Kd") /* load a diffuse texture */
{
if (doTextureInfo)
{
if (stmts[i].size() == 2)
{
if (m_obj->m_textureLoader != NULL)
{
FileLoader::Path path(
basePath(m_path.fullPath + stmts[i][1]),
stmts[i][1]);
GLuint tex = m_obj->m_textureLoader->load(path,
*m_obj->m_fileLoader);
if (tex > 0)
{
pushAttributes(); /* jh 2009-11-16 */
#ifdef DEBUGGL
cout << " glBindTexture(GL_TEXTURE_2D, " << tex << ")" << endl;
#endif
glBindTexture(GL_TEXTURE_2D, tex);
foundTexture = true;
didSomething = true;
}
}
}
}
}
}
checkGLError();
if (didSomething)
{
pushAttributes();
if (doTextureInfo)
{
if (enableBlending)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}
if (foundTexture)
{
#ifdef DEBUGGL
cout << " glEnable(GL_TEXTURE_2D)" << endl;
#endif
glEnable(GL_TEXTURE_2D);
}
else
{
#ifdef DEBUGGL
cout << " glDisable(GL_TEXTURE_2D)" << endl;
#endif
glDisable(GL_TEXTURE_2D);
}
}
}
checkGLError();
}
void WFObj::WFMtl::pushAttributes()
{
if (m_attributesPushed)
return;
m_attributesPushed = true;
#ifdef DEBUGGL
cout << " glPushAttrib(GL_LIGHTING_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT)"
<< endl;
#endif
checkGLError();
glPushAttrib(GL_LIGHTING_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
checkGLError();
}
void WFObj::WFMtl::renderEnd(const string & mtlname, bool doTextureInfo,
bool enableBlending)
{
map< string, vector< vector<string> > >::iterator it = m_data.find(mtlname);
if (it == m_data.end())
return;
if (m_attributesPushed)
{
#ifdef DEBUGGL
cout << " glPopAttrib()" << endl;
#endif
checkGLError();
glPopAttrib();
checkGLError();
m_attributesPushed = false;
}
}
/****** WFFileLoader functions ******/
int WFObj::WFFileLoader::getSize(const Path & path)
{
struct stat st;
if (path.fullPath == "")
return -1;
if (stat(path.fullPath.c_str(), &st))
return -2;
return st.st_size;
}
FileLoader::Buffer WFObj::WFFileLoader::load(const Path & path)
{
int size = getSize(path);
if (size > 0)
{
int fd = open(path.fullPath.c_str(), O_RDONLY);
if (fd > 0)
{
Buffer buf(size);
int num_read = read(fd, buf.data, size);
close(fd);
if (num_read > 0)
return buf;
}
}
return Buffer(0);
}

92
WFObj/WFObj.h Normal file
View File

@ -0,0 +1,92 @@
#ifndef WFOBJ_H
#define WFOBJ_H
#include "FileLoader/FileLoader.h"
#include "TextureLoader/TextureLoader.h"
#include <GL/gl.h>
#include <vector>
#include <string>
#include <map>
class WFObj
{
public:
WFObj();
WFObj(FileLoader & fileLoader);
WFObj(TextureLoader & textureLoader);
WFObj(FileLoader & fileLoader, TextureLoader & textureLoader);
~WFObj();
class WFMtl
{
public:
WFMtl(WFObj * obj) { m_obj = obj; }
bool load(const FileLoader::Path & path);
void renderBegin(const std::string & mtlname,
bool doTextureInfo = true,
bool enableBlending = false);
void renderEnd(const std::string & mtlname,
bool doTextureInfo = true,
bool enableBlending = false);
protected:
/* methods */
void clear();
void processInputLine(const std::string & input);
void pushAttributes();
bool load(std::istream & istr, unsigned int size);
/* variables */
std::map< std::string, std::vector< std::vector<std::string> > > m_data;
std::string m_currentMaterialName;
bool m_attributesPushed;
FileLoader::Path m_path;
WFObj * m_obj;
};
class WFFileLoader : public FileLoader
{
public:
virtual int getSize(const Path & path);
virtual Buffer load(const Path & path);
};
bool load(const FileLoader::Path & path);
GLuint render(bool doTextureInfo = true,
bool enableBlending = false);
const float * const getAABB() { return m_aabb; }
protected:
/* types */
class Vertex
{
public:
float operator[](int idx) const { return data[idx]; }
float & operator[](int idx) { return data[idx]; }
float * getData() { return data; }
private:
float data[4];
};
/* methods */
void init(FileLoader * fileLoader = NULL,
TextureLoader * textureLoader = NULL);
void clear();
void processInputLine(const std::string & input);
Vertex readVertex(const std::vector<std::string> & parts);
void parseVertexIndices(const std::string & vtxref, int * ret);
void updateAABB(const float * const vertex);
bool load(std::istream & istr, unsigned int size);
/* variables */
std::vector< std::vector<std::string> > m_data;
FileLoader::Path m_path;
float m_aabb[6];
bool m_loadedVertex;
FileLoader * m_fileLoader;
TextureLoader * m_textureLoader;
bool m_iCreatedFileLoader;
};
#endif

@ -1 +0,0 @@
Subproject commit 6954147f53d57724b7666bf4a1226e17ca64f734

@ -1 +0,0 @@
Subproject commit 0d78e3cf4f606953087cdccae989f805e07ac0e3

0
lib/dwlogo.mtl Normal file → Executable file
View File

0
lib/dwlogo.obj Normal file → Executable file
View File

0
lib/dwlogo.phy Normal file → Executable file
View File

0
libsrc/dwlogo.blend Normal file → Executable file
View File

0
libsrc/dwlogo_phy.blend Normal file → Executable file
View File

1
refptr

@ -1 +0,0 @@
Subproject commit d5c4876ff8bd674c9d788dfa58eeae35249f3edc

99
refptr/refptr.h Normal file
View File

@ -0,0 +1,99 @@
#ifndef REFPTR_H
#define REFPTR_H REFPTR_H
/* Author: Josh Holtrop
* Purpose: Provide a reference-counting pointer-like first order
* C++ object that will free the object it is pointing to when
* all references to it have been destroyed.
* This implementation does not solve the circular reference problem.
* I was not concerned with that when developing this class.
*/
#include <stdlib.h> /* NULL */
template <typename T>
class refptr
{
public:
refptr<T>();
refptr<T>(T * ptr);
refptr<T>(const refptr<T> & orig);
refptr<T> & operator=(const refptr<T> & orig);
refptr<T> & operator=(T * ptr);
~refptr<T>();
T & operator*() const { return *m_ptr; }
T * operator->() const { return m_ptr; }
bool isNull() const { return m_ptr == NULL; }
private:
void cloneFrom(const refptr<T> & orig);
void destroy();
T * m_ptr;
int * m_refCount;
};
template <typename T> refptr<T>::refptr()
{
m_ptr = NULL;
m_refCount = NULL;
}
template <typename T> refptr<T>::refptr(T * ptr)
{
m_ptr = ptr;
m_refCount = new int;
*m_refCount = 1;
}
template <typename T> refptr<T>::refptr(const refptr<T> & orig)
{
cloneFrom(orig);
}
template <typename T> refptr<T> & refptr<T>::operator=(const refptr<T> & orig)
{
destroy();
cloneFrom(orig);
return *this;
}
template <typename T> refptr<T> & refptr<T>::operator=(T * ptr)
{
destroy();
m_ptr = ptr;
m_refCount = new int;
*m_refCount = 1;
return *this;
}
template <typename T> void refptr<T>::cloneFrom(const refptr<T> & orig)
{
this->m_ptr = orig.m_ptr;
this->m_refCount = orig.m_refCount;
if (m_refCount != NULL)
(*m_refCount)++;
}
template <typename T> refptr<T>::~refptr()
{
destroy();
}
template <typename T> void refptr<T>::destroy()
{
if (m_refCount != NULL)
{
if (*m_refCount <= 1)
{
delete m_ptr;
delete m_refCount;
}
else
{
(*m_refCount)--;
}
}
}
#endif

View File

@ -1,39 +0,0 @@
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform vec4 ambient, diffuse, specular;
uniform float shininess;
varying vec3 pos_i;
varying vec3 normal_i;
void main(void)
{
vec3 n, lightDir;
vec4 color;
float NdotL, RdotEye;
lightDir = normalize(vec3(-0.4, 0, -0.9));
color = vec4(0.2, 0.2, 0.2, 1.0) * ambient; /* ambient light */
n = normalize(normal_i);
NdotL = max(dot(n, -lightDir), 0.0);
if (NdotL > 0.0)
{
/* diffuse component */
color += diffuse * NdotL;
/* specular component */
RdotEye = dot(normalize(-pos_i), normalize(reflect(-lightDir, n)));
if (RdotEye > 0.0)
{
color += clamp(specular * pow(RdotEye, shininess), 0.0, 1.0);
}
}
gl_FragColor = color;
}

View File

@ -1,13 +0,0 @@
attribute vec3 pos;
attribute vec3 normal;
varying vec3 pos_i;
varying vec3 normal_i;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1);
pos_i = gl_Position.xyz;
normal_i = gl_NormalMatrix * normal;
}

View File

@ -1,41 +0,0 @@
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
uniform vec4 ambient, specular;
uniform float shininess;
uniform sampler2D tex;
varying vec3 pos_i;
varying vec3 normal_i;
varying vec2 tex_coord_i;
void main(void)
{
vec3 n, lightDir;
vec4 color;
float NdotL, RdotEye;
lightDir = normalize(vec3(-0.1, 0, -0.9));
color = vec4(0.2, 0.2, 0.2, 1.0) * ambient; /* ambient light */
n = normalize(normal_i);
NdotL = max(dot(n, -lightDir), 0.0);
if (NdotL > 0.0)
{
/* diffuse component */
color += texture2D(tex, tex_coord_i) * NdotL;
/* specular component */
RdotEye = dot(normalize(-pos_i), normalize(reflect(-lightDir, n)));
if (RdotEye > 0.0)
{
color += clamp(specular * pow(RdotEye, shininess), 0.0, 1.0);
}
}
gl_FragColor = color;
}

View File

@ -1,16 +0,0 @@
attribute vec3 pos;
attribute vec3 normal;
attribute vec2 tex_coord;
varying vec3 pos_i;
varying vec3 normal_i;
varying vec2 tex_coord_i;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 1);
pos_i = gl_Position.xyz;
tex_coord_i = tex_coord;
normal_i = gl_NormalMatrix * normal;
}

View File

@ -238,13 +238,13 @@ void AV::playCallback(Uint8 * stream, int len)
/******************** AV::Sound ********************/ /******************** AV::Sound ********************/
AV::Sound::Sound(AV & av) AV::Sound::Sound(AV & av)
: m_av(av) : m_av(av),
m_buff(1)
{ {
m_rwops = NULL; m_rwops = NULL;
m_ss = NULL; m_ss = NULL;
m_buff_bytes_left = 0; m_buff_bytes_left = 0;
m_volume = 1.0f; m_volume = 1.0f;
m_data = NULL;
} }
AV::Sound::~Sound() AV::Sound::~Sound()
@ -253,28 +253,31 @@ AV::Sound::~Sound()
{ {
Sound_FreeSample(m_ss); Sound_FreeSample(m_ss);
} }
if (m_data != NULL)
{
delete[] m_data;
}
} }
bool AV::Sound::load(const unsigned char *data, unsigned int size) bool AV::Sound::load(FileLoader & fileLoader, const FileLoader::Path & path)
{ {
m_data = new unsigned char[size]; m_buff = fileLoader.load(path);
memcpy(m_data, data, size); if (m_buff.size > 0)
m_rwops = SDL_RWFromMem(m_data, size);
Sound_AudioInfo desired;
desired.channels = CHANNELS;
desired.format = AUDIO_S16SYS;
desired.rate = SOUND_RATE;
m_ss = Sound_NewSample(m_rwops, NULL, &desired,
CALLBACK_SAMPLES * BYTES_PER_SAMPLE);
if (m_ss != NULL)
{ {
return true; m_rwops = SDL_RWFromMem(m_buff.data, m_buff.size);
Sound_AudioInfo desired;
desired.channels = CHANNELS;
desired.format = AUDIO_S16SYS;
desired.rate = SOUND_RATE;
m_ss = Sound_NewSample(m_rwops, NULL, &desired,
CALLBACK_SAMPLES * BYTES_PER_SAMPLE);
if (m_ss != NULL)
{
return true;
}
else
{
cerr << "Error loading sound " << path.toString() << ": "
<< Sound_GetError() << endl;
m_rwops = NULL;
}
} }
m_rwops = NULL;
return false; return false;
} }

View File

@ -8,6 +8,7 @@
#include <set> #include <set>
#include "FileLoader/FileLoader.h"
#include "refptr/refptr.h" #include "refptr/refptr.h"
#define AV_SOUND_FORMAT AUDIO_S16SYS #define AV_SOUND_FORMAT AUDIO_S16SYS
@ -27,7 +28,8 @@ class AV
public: public:
Sound(AV & av); Sound(AV & av);
~Sound(); ~Sound();
bool load(const unsigned char *data, unsigned int size); bool load(FileLoader & fileLoader,
const FileLoader::Path & path);
void play(); void play();
void resume(); void resume();
void stop(); void stop();
@ -38,9 +40,9 @@ class AV
void setVolume(float v); void setVolume(float v);
protected: protected:
AV & m_av; AV & m_av;
unsigned char *m_data;
SDL_RWops * m_rwops; SDL_RWops * m_rwops;
Sound_Sample * m_ss; Sound_Sample * m_ss;
FileLoader::Buffer m_buff;
int m_loop_count; int m_loop_count;
int m_buff_bytes_left; int m_buff_bytes_left;
float m_volume; float m_volume;

View File

@ -20,8 +20,6 @@
#include "AV.h" #include "AV.h"
#include "PhyObj/PhyObj.h" #include "PhyObj/PhyObj.h"
#include "sdl_keymap.h" #include "sdl_keymap.h"
#include "cfs.h"
#include "glslUtil/glslUtil.h"
using namespace std; using namespace std;
@ -98,16 +96,6 @@ static vector<string> split(const string & str, char delim)
return ret; return ret;
} }
static bool loadWFObjFile(const char *fname, WFObj::Buffer & buff)
{
return g_engine->loadWFObjFile(fname, buff);
}
static GLuint loadTexture(const char *fname)
{
return g_engine->loadTexture(fname);
}
/******** Engine functions ********/ /******** Engine functions ********/
@ -128,6 +116,7 @@ Engine::Engine(const string & path, AV & av)
m_autoStartFrame = true; m_autoStartFrame = true;
m_autoEndFrame = true; m_autoEndFrame = true;
m_autoDrawObjects = true; m_autoDrawObjects = true;
m_fileLoader = new EngineFileLoader(this);
m_event_time = 0; m_event_time = 0;
m_font = NULL; m_font = NULL;
m_engine_cursor_visible = m_av.getCursorVisible(); m_engine_cursor_visible = m_av.getCursorVisible();
@ -157,64 +146,6 @@ Engine::Engine(const string & path, AV & av)
m_luaState = lua_open(); m_luaState = lua_open();
registerLibraries(); registerLibraries();
{
const char *obj_v_src = (const char *) getFile("shaders/obj.vp", NULL);
const char *obj_f_src = (const char *) getFile("shaders/obj.fp", NULL);
const static guAttribBinding obj_bindings[] = {
{ATTRIBUTE_OBJ_POS, "pos"},
{ATTRIBUTE_OBJ_NORMAL, "normal"},
{0, NULL}
};
if (obj_v_src != NULL && obj_f_src != NULL)
{
m_programs[PROG_OBJ] = guMakeProgramFromSource(obj_v_src, obj_f_src,
obj_bindings);
}
else
{
m_programs[PROG_OBJ] = 0;
cerr << "Error: Could not obtain 'obj' shader sources" << endl;
}
guUniformLocation uniforms_obj[] = {
{&m_uniforms_obj[UNIFORM_OBJ_AMBIENT], "ambient"},
{&m_uniforms_obj[UNIFORM_OBJ_DIFFUSE], "diffuse"},
{&m_uniforms_obj[UNIFORM_OBJ_SPECULAR], "specular"},
{&m_uniforms_obj[UNIFORM_OBJ_SHININESS], "shininess"},
{NULL, NULL}
};
guGetUniformLocations(m_programs[PROG_OBJ], uniforms_obj);
}
{
const char *obj_tex_v_src =
(const char *) getFile("shaders/obj_tex.vp", NULL);
const char *obj_tex_f_src =
(const char *) getFile("shaders/obj_tex.fp", NULL);
const static guAttribBinding obj_tex_bindings[] = {
{ATTRIBUTE_OBJ_TEX_POS, "pos"},
{ATTRIBUTE_OBJ_TEX_NORMAL, "normal"},
{ATTRIBUTE_OBJ_TEX_TEX_COORD, "tex_coord"},
{0, NULL}
};
if (obj_tex_v_src != NULL && obj_tex_f_src != NULL)
{
m_programs[PROG_OBJ_TEX] = guMakeProgramFromSource(obj_tex_v_src,
obj_tex_f_src, obj_tex_bindings);
}
else
{
m_programs[PROG_OBJ_TEX] = 0;
cerr << "Error: Could not obtain 'obj_tex' shader sources" << endl;
}
guUniformLocation uniforms_obj_tex[] = {
{&m_uniforms_obj_tex[UNIFORM_OBJ_TEX_AMBIENT], "ambient"},
{&m_uniforms_obj_tex[UNIFORM_OBJ_TEX_SPECULAR], "specular"},
{&m_uniforms_obj_tex[UNIFORM_OBJ_TEX_SHININESS], "shininess"},
{NULL, NULL}
};
guGetUniformLocations(m_programs[PROG_OBJ_TEX], uniforms_obj_tex);
}
} }
Engine::~Engine() Engine::~Engine()
@ -226,6 +157,7 @@ Engine::~Engine()
{ {
delete it->second; delete it->second;
} }
delete m_fileLoader;
if (m_font != NULL) if (m_font != NULL)
delete m_font; delete m_font;
} }
@ -304,17 +236,24 @@ void Engine::checkForAllHandlerFunctions()
checkForFunction("mouse_motion_event", mouse_motion); checkForFunction("mouse_motion_event", mouse_motion);
} }
bool Engine::validatePath(const string & path) bool Engine::validatePath(string & path)
{ {
if (path[0] == '/') if (path.find_first_not_of(FILENAME_SAFE_CHARS) != string::npos)
return false; return false;
vector<string> parts = split(path, '/'); if (path[0] == ':')
return false;
vector<string> parts = split(path, ':');
path = "";
bool multiple = false;
for (int i = 0, sz = parts.size(); i < sz; i++) for (int i = 0, sz = parts.size(); i < sz; i++)
{ {
if (parts[i].find_first_not_of(FILENAME_SAFE_CHARS) != string::npos) if (parts[i].find_first_not_of(".") != string::npos)
return false; {
if (parts[i].find_first_not_of(".") == string::npos) if (multiple)
return false; path += "/";
path += parts[i];
multiple = true;
}
} }
return true; return true;
} }
@ -347,9 +286,7 @@ void Engine::registerLibraries()
string Engine::locateResource(const string & shortname) string Engine::locateResource(const string & shortname)
{ {
string try_path = shortname; string try_path;
if (fileExists(try_path))
return try_path;
/* look for the resource relative to the loaded script's directory */ /* look for the resource relative to the loaded script's directory */
try_path = m_program_directory + "/" + shortname; try_path = m_program_directory + "/" + shortname;
@ -378,7 +315,7 @@ int Engine::addObject(WFObj * obj, bool is_static, bool is_reference,
bool enable_blending, float scale) bool enable_blending, float scale)
{ {
Object * o = new Object(is_static, is_reference, enable_blending, Object * o = new Object(is_static, is_reference, enable_blending,
m_world, *this, obj, scale); m_world, obj, scale);
int id = m_objects.add(o); int id = m_objects.add(o);
o->setID(id); o->setID(id);
return id; return id;
@ -388,7 +325,7 @@ int Engine::addObject(bool is_static, bool is_reference, bool enable_blending,
OdeWorld::GeomType geom_type, refptr< vector<float> > args) OdeWorld::GeomType geom_type, refptr< vector<float> > args)
{ {
Object * o = new Object(is_static, is_reference, enable_blending, Object * o = new Object(is_static, is_reference, enable_blending,
m_world, *this, geom_type, args); m_world, geom_type, args);
int id = m_objects.add(o); int id = m_objects.add(o);
o->setID(id); o->setID(id);
return id; return id;
@ -655,23 +592,19 @@ int Engine::loadModel(const string & name, bool is_static, bool is_reference,
string path = name; string path = name;
if (validatePath(path)) if (validatePath(path))
{ {
string model_path = path + ".obj"; FileLoader::Path model_path("", path + ".obj");
string phys_path = path + ".phy"; FileLoader::Path phys_path("", path + ".phy");
WFObj * obj = new WFObj(); WFObj * obj = new WFObj(*m_fileLoader, m_textureCache);
if (obj->load(model_path.c_str(), &::loadWFObjFile, &::loadTexture)) if (obj->load(model_path))
{ {
int id = addObject(obj, is_static, is_reference, enable_blending, int id = addObject(obj, is_static, is_reference, enable_blending,
scale); scale);
Engine::Object * engine_obj = getObject(id); Engine::Object * engine_obj = getObject(id);
if (engine_obj != NULL) if (engine_obj != NULL)
{ {
unsigned int size; engine_obj->loadPhy(m_fileLoader, phys_path);
const unsigned char *phy_data =
loadFile(phys_path.c_str(), &size);
engine_obj->loadPhy(phy_data, size);
free((void *) phy_data);
} }
return id; return id;
} }
@ -686,22 +619,21 @@ int Engine::loadModel(const string & name, bool is_static, bool is_reference,
int Engine::loadSound(const string & name) int Engine::loadSound(const string & name)
{ {
if (validatePath(name)) string nm = name;
if (validatePath(nm))
{ {
string nm = locateResource(name.c_str()); FileLoader::Path path("", nm);
refptr<AV::Sound> avs = m_av.createSound(); refptr<AV::Sound> avs = m_av.createSound();
unsigned int size; if (avs->load(*m_fileLoader, path))
const unsigned char *data = loadFile(nm.c_str(), &size);
if (data != NULL)
{ {
bool loaded = avs->load(data, size); return addSound(avs);
delete[] data; }
if (loaded) else
return addSound(avs); {
cerr << "error loading sound '" << name << "'" << endl;
} }
cerr << "error loading sound '" << name << "'" << endl;
} }
return 0; return 0;
} }
@ -747,6 +679,12 @@ bool Engine::importFullPath(const char * path)
return false; return false;
} }
GLuint Engine::loadTexture(const char * name)
{
FileLoader::Path path("", name);
return m_textureCache.load(path, *m_fileLoader);
}
GLuint Engine::startList() GLuint Engine::startList()
{ {
GLuint list = glGenLists(1); GLuint list = glGenLists(1);
@ -1322,73 +1260,54 @@ void Engine::drawObjects()
} }
} }
int Engine::getFileSize(const char *fname) /******** Engine::EngineFileLoader functions ********/
Engine::EngineFileLoader::EngineFileLoader(Engine * engine)
{
m_engine = engine;
}
int Engine::EngineFileLoader::getSize(const Path & path)
{ {
struct stat st; struct stat st;
string file_path = resolvePath(path);
if (stat(fname, &st)) if (file_path == "")
return -1;
if (stat(file_path.c_str(), &st))
return -2; return -2;
return st.st_size; return st.st_size;
} }
const unsigned char *Engine::loadFile(const char *fname, unsigned int *len) FileLoader::Buffer Engine::EngineFileLoader::load(const Path & path)
{ {
string file_path = locateResource(fname); string file_path = resolvePath(path);
unsigned int size = getFileSize(file_path.c_str()); int size = getSize(path);
if (size > 0) if (size > 0)
{ {
FILE * fp = fopen(file_path.c_str(), "rb"); FILE * fp = fopen(file_path.c_str(), "rb");
if (fp != NULL) if (fp != NULL)
{ {
unsigned char *data = new unsigned char[size]; Buffer buf(size);
int num_read = fread(data, size, 1, fp); int num_read = fread(buf.data, size, 1, fp);
fclose(fp); fclose(fp);
if (num_read > 0) if (num_read > 0)
{ {
if (len != NULL) return buf;
*len = size;
return data;
} }
} }
} }
return NULL; return Buffer(0);
} }
bool Engine::loadWFObjFile(const char *fname, WFObj::Buffer & buff) string Engine::EngineFileLoader::resolvePath(const Path & path)
{ {
unsigned int size; string file_path = m_engine->locateResource(path.shortPath);
const unsigned char *data = loadFile(fname, &size); if (file_path == "")
if (data != NULL) file_path = path.fullPath;
{ return file_path;
buff.alloc(size);
memcpy(buff.data, data, size);
delete[] data;
return true;
}
return false;
} }
GLuint Engine::loadTexture(const char *fname)
{
string path = locateResource(fname);
GLuint id = m_textureCache.load(path.c_str());
if (id != 0)
{
int width, height;
glBindTexture(GL_TEXTURE_2D, id);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
char *data = (char *) malloc(4 * width * height);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA,
GL_UNSIGNED_BYTE, data);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
free(data);
}
return id;
}
/******** Engine::PickedObject functions ********/ /******** Engine::PickedObject functions ********/

View File

@ -9,7 +9,8 @@
#include <SDL.h> #include <SDL.h>
#include "OdeWorld/OdeWorld.h" #include "OdeWorld/OdeWorld.h"
#include "TextureCache/TextureCache.h" #include "TextureCache/TextureCache.h"
#include "wfobj/WFObj.h" #include "FileLoader/FileLoader.h"
#include "WFObj/WFObj.h"
#include "AV.h" #include "AV.h"
#include "refptr/refptr.h" #include "refptr/refptr.h"
#include "ftgl.h" #include "ftgl.h"
@ -23,18 +24,17 @@ class Engine
{ {
public: public:
Object(bool is_static, bool is_reference, bool enable_blending, Object(bool is_static, bool is_reference, bool enable_blending,
OdeWorld & world, Engine & e, WFObj * wfobj, OdeWorld & world, WFObj * wfobj,
float scale = 1.0f); float scale = 1.0f);
Object(bool is_static, bool is_reference, bool enable_blending, Object(bool is_static, bool is_reference, bool enable_blending,
OdeWorld & world, Engine & e, OdeWorld & world, OdeWorld::GeomType geom_type,
OdeWorld::GeomType geom_type,
refptr< std::vector<float> > args); refptr< std::vector<float> > args);
Object(const Object & orig); Object(const Object & orig);
~Object(); ~Object();
void setPosition(double x, double y, double z); void setPosition(double x, double y, double z);
void getPosition(double * x, double * y, double * z); void getPosition(double * x, double * y, double * z);
void loadPhy(const unsigned char *data, unsigned int size); void loadPhy(FileLoader * fl, const FileLoader::Path & path);
void instantiatePhy(); void instantiatePhy();
void setVisible(bool visible) { m_is_visible = visible; } void setVisible(bool visible) { m_is_visible = visible; }
bool getVisible() { return m_is_visible; } bool getVisible() { return m_is_visible; }
@ -103,7 +103,6 @@ class Engine
void createManagedObject(); void createManagedObject();
void render(); void render();
Engine & m_engine;
OdeWorld::Object * m_ode_object; OdeWorld::Object * m_ode_object;
GLuint m_display_list; GLuint m_display_list;
bool m_is_visible; bool m_is_visible;
@ -122,8 +121,7 @@ class Engine
bool m_enable_blending; bool m_enable_blending;
/* for "pre-loaded" objects */ /* for "pre-loaded" objects */
WFObj * m_obj; int * m_display_list_refcnt;
int * m_obj_refcnt;
/* for "managed" objects */ /* for "managed" objects */
OdeWorld::GeomType m_geom_type; OdeWorld::GeomType m_geom_type;
@ -133,6 +131,17 @@ class Engine
float m_texture_scale; float m_texture_scale;
}; };
class EngineFileLoader : public FileLoader
{
public:
EngineFileLoader(Engine * engine);
virtual int getSize(const Path & path);
virtual Buffer load(const Path & path);
protected:
std::string resolvePath(const Path & path);
Engine * m_engine;
};
class PickedObject class PickedObject
{ {
public: public:
@ -255,8 +264,6 @@ class Engine
void exit(); void exit();
bool import(const char * name); bool import(const char * name);
bool importFullPath(const char * path); bool importFullPath(const char * path);
const unsigned char *loadFile(const char *fname, unsigned int *len);
bool loadWFObjFile(const char *fname, WFObj::Buffer & buff);
GLuint loadTexture(const char * name); GLuint loadTexture(const char * name);
void debug_hook(lua_Debug * debug); void debug_hook(lua_Debug * debug);
void setGravity(float gx, float gy, float gz) void setGravity(float gx, float gy, float gz)
@ -327,14 +334,14 @@ class Engine
m_av.setCursorVisible( m_av.setCursorVisible(
m_engine_cursor_visible || m_script_cursor_visible); m_engine_cursor_visible || m_script_cursor_visible);
} }
bool validatePath(const std::string & path); bool validatePath(std::string & path);
int getFileSize(const char *fname);
AV & m_av; AV & m_av;
bool m_engine_cursor_visible; bool m_engine_cursor_visible;
bool m_script_cursor_visible; bool m_script_cursor_visible;
bool m_input_grabbed; bool m_input_grabbed;
TextureCache m_textureCache; TextureCache m_textureCache;
EngineFileLoader * m_fileLoader;
lua_State * m_luaState; lua_State * m_luaState;
std::string m_program_path; std::string m_program_path;
std::string m_program_directory; std::string m_program_directory;
@ -368,35 +375,6 @@ class Engine
bool m_event_mousebutton_down_present; bool m_event_mousebutton_down_present;
bool m_event_mousebutton_up_present; bool m_event_mousebutton_up_present;
bool m_event_mouse_motion_present; bool m_event_mouse_motion_present;
enum { PROG_OBJ, PROG_OBJ_TEX, PROG_COUNT };
GLuint m_programs[PROG_COUNT];
enum {
UNIFORM_OBJ_AMBIENT,
UNIFORM_OBJ_DIFFUSE,
UNIFORM_OBJ_SPECULAR,
UNIFORM_OBJ_SHININESS,
UNIFORM_OBJ_COUNT
};
enum {
ATTRIBUTE_OBJ_POS,
ATTRIBUTE_OBJ_NORMAL,
ATTRIBUTE_OBJ_COUNT
};
GLint m_uniforms_obj[UNIFORM_OBJ_COUNT];
enum {
UNIFORM_OBJ_TEX_AMBIENT,
UNIFORM_OBJ_TEX_SPECULAR,
UNIFORM_OBJ_TEX_SHININESS,
UNIFORM_OBJ_TEX_COUNT
};
enum {
ATTRIBUTE_OBJ_TEX_POS,
ATTRIBUTE_OBJ_TEX_NORMAL,
ATTRIBUTE_OBJ_TEX_TEX_COORD,
ATTRIBUTE_OBJ_TEX_COUNT
};
GLint m_uniforms_obj_tex[UNIFORM_OBJ_TEX_COUNT];
}; };
extern Engine * g_engine; extern Engine * g_engine;

View File

@ -27,8 +27,8 @@ static void checkGLErrorLine(const char * function, int line)
/* used for objects loaded directly from model files */ /* used for objects loaded directly from model files */
Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending, Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending,
OdeWorld & world, Engine & e, WFObj * obj, float scale) OdeWorld & world, WFObj * obj, float scale)
: m_engine(e), m_world(world) : m_world(world)
{ {
m_is_reference = is_reference; m_is_reference = is_reference;
if (m_is_reference) if (m_is_reference)
@ -42,28 +42,26 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending,
} }
m_is_static = is_static; m_is_static = is_static;
m_enable_blending = enable_blending; m_enable_blending = enable_blending;
m_display_list = obj->render(true, enable_blending);
const float * obj_aabb = obj->getAABB(); const float * obj_aabb = obj->getAABB();
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
m_aabb[i] = scale * obj_aabb[i]; m_aabb[i] = scale * obj_aabb[i];
m_display_list_refcnt = new int;
*m_display_list_refcnt = 1;
m_is_visible = true; m_is_visible = true;
m_scale = scale; m_scale = scale;
m_is_scaled = ! (fabs(scale - 1.0) < 0.0001); m_is_scaled = ! (fabs(scale - 1.0) < 0.0001);
m_display_list = 0;
m_is_managed = false; m_is_managed = false;
m_mass = 0.0; m_mass = 0.0;
m_mass_is_set = false; m_mass_is_set = false;
m_gravity_mode = true; m_gravity_mode = true;
m_obj = obj;
m_obj_refcnt = new int;
*m_obj_refcnt = 1;
} }
/* used for "managed" objects with one geom */ /* used for "managed" objects with one geom */
Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending, Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending,
OdeWorld & world, Engine & e, OdeWorld & world, OdeWorld::GeomType geom_type,
OdeWorld::GeomType geom_type,
refptr< std::vector<float> > args) refptr< std::vector<float> > args)
: m_engine(e), m_world(world) : m_world(world)
{ {
m_is_reference = is_reference; m_is_reference = is_reference;
m_enable_blending = enable_blending; m_enable_blending = enable_blending;
@ -72,6 +70,7 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending,
m_scale = 1.0f; m_scale = 1.0f;
m_is_scaled = false; m_is_scaled = false;
m_display_list = 0; m_display_list = 0;
m_display_list_refcnt = NULL;
if (m_is_reference) if (m_is_reference)
{ {
m_ode_object = NULL; m_ode_object = NULL;
@ -93,13 +92,11 @@ Engine::Object::Object(bool is_static, bool is_reference, bool enable_blending,
m_mass = 0.0; m_mass = 0.0;
m_mass_is_set = false; m_mass_is_set = false;
m_gravity_mode = true; m_gravity_mode = true;
m_obj = NULL;
m_obj_refcnt = NULL;
} }
/* used to clone objects */ /* used to clone objects */
Engine::Object::Object(const Engine::Object & orig) Engine::Object::Object(const Engine::Object & orig)
: m_engine(orig.m_engine), m_world(orig.m_world) : m_world(orig.m_world)
{ {
m_is_reference = false; m_is_reference = false;
m_is_visible = orig.m_is_visible; m_is_visible = orig.m_is_visible;
@ -109,7 +106,13 @@ Engine::Object::Object(const Engine::Object & orig)
m_is_scaled = orig.m_is_scaled; m_is_scaled = orig.m_is_scaled;
m_phy = orig.m_phy; m_phy = orig.m_phy;
m_is_managed = orig.m_is_managed; m_is_managed = orig.m_is_managed;
m_display_list = 0; if (m_is_managed)
m_display_list = 0;
else
m_display_list = orig.m_display_list;
m_display_list_refcnt = orig.m_display_list_refcnt;
if (m_display_list_refcnt != NULL)
(*m_display_list_refcnt)++;
m_geom_type = orig.m_geom_type; m_geom_type = orig.m_geom_type;
m_args = orig.m_args; m_args = orig.m_args;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -139,27 +142,26 @@ Engine::Object::Object(const Engine::Object & orig)
} }
m_gravity_mode = orig.m_gravity_mode; m_gravity_mode = orig.m_gravity_mode;
setGravityMode(m_gravity_mode); setGravityMode(m_gravity_mode);
m_obj = orig.m_obj;
m_obj_refcnt = orig.m_obj_refcnt;
if (m_obj_refcnt)
(*m_obj_refcnt)++;
memcpy(m_aabb, orig.m_aabb, sizeof(m_aabb));
} }
Engine::Object::~Object() Engine::Object::~Object()
{ {
if (m_ode_object != NULL) if (m_ode_object != NULL)
delete m_ode_object; delete m_ode_object;
if (m_display_list != 0) if (m_display_list_refcnt != NULL)
{
(*m_display_list_refcnt)--;
if (*m_display_list_refcnt < 1)
{
/* we hold the last reference to the OpenGL display list */
delete m_display_list_refcnt;
glDeleteLists(m_display_list, 1);
}
}
else
{ {
glDeleteLists(m_display_list, 1); glDeleteLists(m_display_list, 1);
} }
if (m_obj_refcnt != NULL)
{
(*m_obj_refcnt)--;
if (*m_obj_refcnt < 1)
delete m_obj;
}
} }
void Engine::Object::createManagedObject() void Engine::Object::createManagedObject()
@ -452,10 +454,10 @@ void Engine::Object::getPosition(double * x, double * y, double * z)
*x = *y = *z = 0.0; *x = *y = *z = 0.0;
} }
void Engine::Object::loadPhy(const unsigned char *data, unsigned int size) void Engine::Object::loadPhy(FileLoader * fl, const FileLoader::Path & path)
{ {
m_phy = new PhyObj(); m_phy = new PhyObj();
m_phy->load(data, size); m_phy->load(fl, path);
if (!m_is_managed) if (!m_is_managed)
instantiatePhy(); instantiatePhy();
} }
@ -520,104 +522,7 @@ void Engine::Object::draw()
} }
checkGLError(); checkGLError();
glCallList(m_display_list);
if (m_is_managed)
{
glCallList(m_display_list);
}
else
{
m_obj->bindBuffers();
GLuint program = m_engine.m_programs[PROG_OBJ];
glUseProgram(program);
glEnableVertexAttribArray(ATTRIBUTE_OBJ_POS);
glEnableVertexAttribArray(ATTRIBUTE_OBJ_NORMAL);
int stride = m_obj->getStride();
glVertexAttribPointer(ATTRIBUTE_OBJ_POS, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj->getVertexOffset());
glVertexAttribPointer(ATTRIBUTE_OBJ_NORMAL, 3, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj->getNormalOffset());
if (m_obj->doTextures())
{
glVertexAttribPointer(ATTRIBUTE_OBJ_TEX_TEX_COORD,
2, GL_FLOAT, GL_FALSE,
stride, (GLvoid *) m_obj->getTextureCoordOffset());
}
for (map<string, WFObj::Material>::iterator it =
m_obj->getMaterials().begin();
it != m_obj->getMaterials().end();
it++)
{
WFObj::Material & m = it->second;
if (m.flags & WFObj::Material::TEXTURE_BIT)
{
glBindTexture(GL_TEXTURE_2D, m.texture);
if (program != m_engine.m_programs[PROG_OBJ_TEX])
{
program = m_engine.m_programs[PROG_OBJ_TEX];
glUseProgram(program);
glEnableVertexAttribArray(ATTRIBUTE_OBJ_TEX_TEX_COORD);
}
}
else
{
if (program != m_engine.m_programs[PROG_OBJ])
{
program = m_engine.m_programs[PROG_OBJ];
glUseProgram(program);
glDisableVertexAttribArray(ATTRIBUTE_OBJ_TEX_TEX_COORD);
}
}
if (m.flags & WFObj::Material::SHININESS_BIT)
{
if (program == m_engine.m_programs[PROG_OBJ_TEX])
glUniform1f(m_engine.m_uniforms_obj_tex[
UNIFORM_OBJ_TEX_SHININESS],
m.shininess);
else
glUniform1f(m_engine.m_uniforms_obj[
UNIFORM_OBJ_SHININESS],
m.shininess);
}
if (m.flags & WFObj::Material::AMBIENT_BIT)
{
if (program == m_engine.m_programs[PROG_OBJ_TEX])
glUniform4fv(m_engine.m_uniforms_obj_tex[
UNIFORM_OBJ_TEX_AMBIENT],
1, &m.ambient[0]);
else
glUniform4fv(m_engine.m_uniforms_obj[
UNIFORM_OBJ_AMBIENT],
1, &m.ambient[0]);
}
if (m.flags & WFObj::Material::DIFFUSE_BIT)
{
if (program != m_engine.m_programs[PROG_OBJ_TEX])
glUniform4fv(m_engine.m_uniforms_obj[
UNIFORM_OBJ_DIFFUSE],
1, &m.diffuse[0]);
}
if (m.flags & WFObj::Material::SPECULAR_BIT)
{
if (program == m_engine.m_programs[PROG_OBJ_TEX])
glUniform4fv(m_engine.m_uniforms_obj_tex[
UNIFORM_OBJ_TEX_SPECULAR],
1, &m.specular[0]);
else
glUniform4fv(m_engine.m_uniforms_obj[
UNIFORM_OBJ_SPECULAR],
1, &m.specular[0]);
}
glDrawElements(GL_TRIANGLES, m.num_vertices,
GL_UNSIGNED_SHORT,
(GLvoid *) (sizeof(GLushort) * m.first_vertex));
}
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glUseProgram(0);
}
checkGLError(); checkGLError();
if (m_is_scaled) if (m_is_scaled)

View File

@ -13,9 +13,10 @@
#include <string> #include <string>
#include "ag.h" #include "ag.h"
#include "cfs.h" #include "ag_lua.h"
#include "anaglym.h" #include "anaglym.h"
#include "Engine.h" #include "Engine.h"
#include "WFObj/WFObj.h"
#include "AV.h" #include "AV.h"
using namespace std; using namespace std;
@ -85,7 +86,8 @@ namespace ag
}; };
luaL_register(L, "ag", functions); luaL_register(L, "ag", functions);
luaL_loadstring(L, (const char *) getFile("src/ag.lua", NULL)); ag_lua[ag_lua_len - 1] = '\0';
luaL_loadstring(L, (const char *) ag_lua);
lua_pcall(L, 0, 0, 0); lua_pcall(L, 0, 0, 0);
} }

8
src/ag_lua.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef AG_LUA_H
#define AG_LUA_H
extern unsigned char ag_lua[];
extern unsigned int ag_lua_len;
#endif

View File

@ -6,6 +6,7 @@
#include <stdlib.h> /* exit(), srand() */ #include <stdlib.h> /* exit(), srand() */
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <unistd.h>
using namespace std; using namespace std;
static void usage(); static void usage();

BIN
tests/boxarena.blend Normal file → Executable file

Binary file not shown.

View File

@ -1,12 +1,12 @@
# Blender3D MTL File: boxarena.blend # Blender3D MTL File: boxarena.blend
# Material Count: 1 # Material Count: 1
newmtl Material newmtl Material
Ns 96.078431 Ns 96.078431
Ka 0.000000 0.000000 0.000000 Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000 Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000 Ks 0.500000 0.500000 0.500000
Ni 1.000000 Ni 1.000000
d 1.000000 d 1.000000
illum 2 illum 2

View File

@ -1,197 +1,198 @@
# Blender3D v249 OBJ File: boxarena.blend # Blender3D v248 OBJ File: boxarena.blend
# www.blender3d.org # www.blender3d.org
mtllib boxarena.mtl mtllib boxarena.mtl
v 0.000000 10.000000 8.000000 v 0.000000 10.000000 8.000000
v 0.000000 8.000000 8.000000 v 0.000000 8.000000 8.000000
v -10.000000 8.000000 8.000000 v -10.000001 8.000000 8.000000
v -9.999998 10.000000 8.000000 v -9.999998 10.000000 8.000000
v 0.000002 9.999999 10.000000 v 0.000002 9.999999 10.000000
v -0.000003 8.000000 10.000000 v -0.000003 8.000000 10.000000
v -10.000002 8.000000 10.000000 v -10.000002 8.000000 10.000000
v -10.000000 10.000000 10.000000 v -10.000000 10.000000 10.000000
vn 0.000000 0.000000 -1.000000 vn 0.000000 0.000000 -1.000000
vn 0.000000 -0.000000 1.000000 vn 0.000000 0.000000 1.000000
vn 1.000000 -0.000001 0.000000 vn 1.000000 -0.000001 0.000000
vn -0.000000 -1.000000 -0.000000 vn -0.000000 -1.000000 -0.000000
vn -1.000000 0.000001 -0.000001 vn -1.000000 0.000001 -0.000001
vn 0.000000 1.000000 0.000000 vn 0.000000 1.000000 0.000000
usemtl Material usemtl (null)
s off s off
f 1//1 2//1 3//1 4//1 f 1//1 2//1 3//1 4//1
f 5//2 8//2 7//2 6//2 f 5//2 8//2 7//2 6//2
f 1//3 5//3 6//3 2//3 f 1//3 5//3 6//3 2//3
f 2//4 6//4 7//4 3//4 f 2//4 6//4 7//4 3//4
f 3//5 7//5 8//5 4//5 f 3//5 7//5 8//5 4//5
f 5//6 1//6 4//6 8//6 f 5//6 1//6 4//6 8//6
v 0.000000 10.000000 6.000000 v 0.000000 10.000000 6.000000
v 0.000000 6.000000 6.000000 v 0.000000 6.000000 6.000000
v -10.000000 6.000000 6.000000 v -10.000001 6.000000 6.000000
v -9.999998 10.000001 6.000000 v -9.999998 10.000001 6.000000
v 0.000002 9.999999 8.000000 v 0.000002 9.999999 8.000000
v -0.000003 5.999999 8.000000 v -0.000003 5.999999 8.000000
v -10.000002 6.000001 8.000000 v -10.000002 6.000001 8.000000
v -10.000000 10.000000 8.000000 v -10.000000 10.000000 8.000000
vn -1.000000 0.000000 -0.000001 usemtl (null)
usemtl Material s off
s off f 9//1 10//1 11//1 12//1
f 9//1 10//1 11//1 12//1 f 13//2 16//2 15//2 14//2
f 13//2 16//2 15//2 14//2 f 9//3 13//3 14//3 10//3
f 9//3 13//3 14//3 10//3 f 10//4 14//4 15//4 11//4
f 10//4 14//4 15//4 11//4 f 11//5 15//5 16//5 12//5
f 11//7 15//7 16//7 12//7 f 13//6 9//6 12//6 16//6
f 13//6 9//6 12//6 16//6 v 0.000000 10.000000 4.000000
v 0.000000 10.000000 4.000000 v 0.000000 4.000000 4.000000
v 0.000000 4.000000 4.000000 v -10.000001 4.000000 4.000000
v -10.000000 4.000000 4.000000 v -9.999998 10.000001 4.000000
v -9.999998 10.000001 4.000000 v 0.000002 9.999998 6.000000
v 0.000002 9.999998 6.000000 v -0.000003 3.999998 6.000000
v -0.000003 3.999998 6.000000 v -10.000002 4.000001 6.000000
v -10.000002 4.000001 6.000000 v -10.000000 10.000000 6.000000
v -10.000000 10.000000 6.000000 vn 1.000000 -0.000000 0.000000
vn 1.000000 -0.000000 0.000000 vn -1.000000 0.000000 -0.000001
vn 0.000000 1.000000 0.000001 vn 0.000000 1.000000 0.000001
usemtl Material usemtl (null)
s off s off
f 17//1 18//1 19//1 20//1 f 17//1 18//1 19//1 20//1
f 21//2 24//2 23//2 22//2 f 21//2 24//2 23//2 22//2
f 17//8 21//8 22//8 18//8 f 17//7 21//7 22//7 18//7
f 18//4 22//4 23//4 19//4 f 18//4 22//4 23//4 19//4
f 19//7 23//7 24//7 20//7 f 19//8 23//8 24//8 20//8
f 21//9 17//9 20//9 24//9 f 21//9 17//9 20//9 24//9
v 0.000000 10.000000 2.000000 v 0.000000 10.000000 2.000000
v 0.000000 2.000000 2.000000 v 0.000000 2.000000 2.000000
v -10.000000 2.000001 2.000000 v -10.000001 2.000001 2.000000
v -9.999998 10.000002 2.000000 v -9.999998 10.000002 2.000000
v 0.000002 9.999998 4.000000 v 0.000002 9.999998 4.000000
v -0.000003 1.999998 4.000000 v -0.000003 1.999998 4.000000
v -10.000002 2.000001 4.000000 v -10.000002 2.000001 4.000000
v -10.000000 10.000000 4.000000 v -10.000000 10.000000 4.000000
usemtl Material usemtl (null)
s off s off
f 25//1 26//1 27//1 28//1 f 25//1 26//1 27//1 28//1
f 29//2 32//2 31//2 30//2 f 29//2 32//2 31//2 30//2
f 25//8 29//8 30//8 26//8 f 25//7 29//7 30//7 26//7
f 26//4 30//4 31//4 27//4 f 26//4 30//4 31//4 27//4
f 27//7 31//7 32//7 28//7 f 27//8 31//8 32//8 28//8
f 29//9 25//9 28//9 32//9 f 29//9 25//9 28//9 32//9
v 0.000000 10.000000 0.000000 v 0.000000 10.000000 0.000000
v 0.000000 0.000000 0.000000 v 0.000000 0.000000 0.000000
v -10.000000 0.000001 0.000000 v -10.000001 0.000001 0.000000
v -9.999998 10.000002 0.000000 v -9.999998 10.000002 0.000000
v 0.000002 9.999997 2.000000 v 0.000002 9.999997 2.000000
v -0.000003 -0.000003 2.000000 v -0.000003 -0.000003 2.000000
v -10.000002 0.000002 2.000000 v -10.000002 0.000002 2.000000
v -10.000000 10.000000 2.000000 v -10.000000 10.000000 2.000000
usemtl Material vn -0.000000 -1.000000 -0.000001
s off usemtl (null)
f 33//1 34//1 35//1 36//1 s off
f 37//2 40//2 39//2 38//2 f 33//1 34//1 35//1 36//1
f 33//8 37//8 38//8 34//8 f 37//2 40//2 39//2 38//2
f 34//4 38//4 39//4 35//4 f 33//7 37//7 38//7 34//7
f 35//7 39//7 40//7 36//7 f 34//10 38//10 39//10 35//10
f 37//9 33//9 36//9 40//9 f 35//8 39//8 40//8 36//8
v 10.000000 9.999999 20.000000 f 37//9 33//9 36//9 40//9
v 10.000000 -10.000000 20.000000 v 10.000000 9.999999 20.000000
v -10.000001 -9.999998 20.000000 v 10.000000 -10.000000 20.000000
v -9.999996 10.000004 20.000000 v -10.000001 -9.999998 20.000000
v 10.000005 9.999994 21.000000 v -9.999996 10.000004 20.000000
v 9.999993 -10.000006 21.000000 v 10.000005 9.999994 21.000000
v -10.000004 -9.999996 21.000000 v 9.999993 -10.000006 21.000000
v -9.999999 10.000000 21.000000 v -10.000004 -9.999996 21.000000
vn 1.000000 -0.000000 0.000001 v -9.999999 10.000000 21.000000
vn -0.000000 -1.000000 -0.000002 vn 1.000000 -0.000000 0.000001
vn -1.000000 0.000000 -0.000003 vn -0.000000 -1.000000 -0.000002
vn 0.000000 1.000000 0.000004 vn -1.000000 0.000000 -0.000003
usemtl Material vn 0.000000 1.000000 0.000004
s off usemtl Material
f 41//1 42//1 43//1 44//1 s off
f 45//2 48//2 47//2 46//2 f 41//1 42//1 43//1 44//1
f 41//10 45//10 46//10 42//10 f 45//2 48//2 47//2 46//2
f 42//11 46//11 47//11 43//11 f 41//11 45//11 46//11 42//11
f 43//12 47//12 48//12 44//12 f 42//12 46//12 47//12 43//12
f 45//13 41//13 44//13 48//13 f 43//13 47//13 48//13 44//13
v 9.999999 -11.000000 0.000000 f 45//14 41//14 44//14 48//14
v -10.000000 -11.000000 0.000000 v 9.999999 -11.000000 0.000000
v -9.999998 -10.000000 0.000000 v -10.000000 -11.000000 0.000000
v 10.000004 -10.000001 0.000000 v -9.999998 -9.999999 0.000000
v 9.999994 -11.000001 20.000000 v 10.000004 -10.000001 0.000000
v -10.000006 -10.999999 20.000000 v 9.999994 -11.000001 20.000000
v -9.999996 -9.999999 20.000000 v -10.000006 -10.999999 20.000000
v 10.000000 -10.000000 20.000000 v -9.999996 -9.999999 20.000000
vn -1.000000 0.000006 -0.000000 v 10.000000 -10.000000 20.000000
vn 1.000000 -0.000005 0.000000 vn -1.000000 0.000006 -0.000000
usemtl Material vn 1.000000 -0.000005 0.000000
s off usemtl Material
f 49//1 50//1 51//1 52//1 s off
f 53//2 56//2 55//2 54//2 f 49//1 50//1 51//1 52//1
f 49//4 53//4 54//4 50//4 f 53//2 56//2 55//2 54//2
f 50//14 54//14 55//14 51//14 f 49//4 53//4 54//4 50//4
f 51//6 55//6 56//6 52//6 f 50//15 54//15 55//15 51//15
f 53//15 49//15 52//15 56//15 f 51//6 55//6 56//6 52//6
v 9.999999 10.000000 0.000000 f 53//16 49//16 52//16 56//16
v -10.000000 10.000000 0.000000 v 9.999999 10.000000 0.000000
v -9.999998 11.000000 0.000000 v -10.000000 10.000000 0.000000
v 10.000004 10.999999 0.000000 v -9.999998 11.000001 0.000000
v 9.999994 9.999999 20.000000 v 10.000004 10.999999 0.000000
v -10.000006 10.000001 20.000000 v 9.999994 9.999999 20.000000
v -9.999996 11.000001 20.000000 v -10.000006 10.000001 20.000000
v 10.000000 11.000000 20.000000 v -9.999996 11.000001 20.000000
usemtl Material v 10.000000 11.000000 20.000000
s off usemtl Material
f 57//1 58//1 59//1 60//1 s off
f 61//2 64//2 63//2 62//2 f 57//1 58//1 59//1 60//1
f 57//4 61//4 62//4 58//4 f 61//2 64//2 63//2 62//2
f 58//14 62//14 63//14 59//14 f 57//4 61//4 62//4 58//4
f 59//6 63//6 64//6 60//6 f 58//15 62//15 63//15 59//15
f 61//15 57//15 60//15 64//15 f 59//6 63//6 64//6 60//6
v 11.000000 9.999999 0.000000 f 61//16 57//16 60//16 64//16
v 11.000000 -10.000000 0.000000 v 11.000000 9.999999 0.000000
v 10.000000 -9.999998 0.000000 v 11.000000 -10.000000 0.000000
v 10.000000 10.000004 0.000000 v 10.000000 -9.999998 0.000000
v 11.000000 9.999994 20.000000 v 10.000000 10.000004 0.000000
v 11.000000 -10.000006 20.000000 v 11.000000 9.999994 20.000000
v 10.000000 -9.999996 20.000000 v 11.000000 -10.000006 20.000000
v 10.000000 10.000000 20.000000 v 10.000000 -9.999996 20.000000
vn -0.000006 -1.000000 -0.000000 v 10.000000 10.000000 20.000000
vn -1.000000 -0.000000 0.000000 vn -0.000006 -1.000000 -0.000000
vn 0.000005 1.000000 0.000000 vn -1.000000 0.000000 0.000000
usemtl Material vn 0.000005 1.000000 0.000000
s off usemtl Material
f 65//1 66//1 67//1 68//1 s off
f 69//2 72//2 71//2 70//2 f 65//1 66//1 67//1 68//1
f 65//8 69//8 70//8 66//8 f 69//2 72//2 71//2 70//2
f 66//16 70//16 71//16 67//16 f 65//7 69//7 70//7 66//7
f 67//17 71//17 72//17 68//17 f 66//17 70//17 71//17 67//17
f 69//18 65//18 68//18 72//18 f 67//18 71//18 72//18 68//18
v -10.000000 9.999999 0.000000 f 69//19 65//19 68//19 72//19
v -10.000000 -10.000000 0.000000 v -10.000000 9.999999 0.000000
v -11.000000 -9.999998 0.000000 v -10.000000 -10.000000 0.000000
v -11.000000 10.000004 0.000000 v -11.000000 -9.999998 0.000000
v -10.000000 9.999994 20.000000 v -11.000000 10.000004 0.000000
v -10.000000 -10.000006 20.000000 v -10.000000 9.999994 20.000000
v -11.000000 -9.999996 20.000000 v -10.000000 -10.000006 20.000000
v -11.000000 10.000000 20.000000 v -11.000000 -9.999996 20.000000
usemtl Material v -11.000000 10.000000 20.000000
s off usemtl Material
f 73//1 74//1 75//1 76//1 s off
f 77//2 80//2 79//2 78//2 f 73//1 74//1 75//1 76//1
f 73//8 77//8 78//8 74//8 f 77//2 80//2 79//2 78//2
f 74//16 78//16 79//16 75//16 f 73//7 77//7 78//7 74//7
f 75//17 79//17 80//17 76//17 f 74//17 78//17 79//17 75//17
f 77//18 73//18 76//18 80//18 f 75//18 79//18 80//18 76//18
v 10.000000 9.999999 -1.000000 f 77//19 73//19 76//19 80//19
v 10.000000 -10.000000 -1.000000 v 10.000000 9.999999 -1.000000
v -10.000001 -9.999998 -1.000000 v 10.000000 -10.000000 -1.000000
v -9.999996 10.000004 -1.000000 v -10.000001 -9.999998 -1.000000
v 10.000005 9.999994 0.000000 v -9.999996 10.000004 -1.000000
v 9.999993 -10.000006 0.000000 v 10.000005 9.999994 0.000000
v -10.000004 -9.999996 0.000000 v 9.999993 -10.000006 0.000000
v -9.999999 10.000000 0.000000 v -10.000004 -9.999996 0.000000
usemtl Material v -9.999999 10.000000 0.000000
s off usemtl Material
f 81//1 82//1 83//1 84//1 s off
f 85//2 88//2 87//2 86//2 f 81//1 82//1 83//1 84//1
f 81//10 85//10 86//10 82//10 f 85//2 88//2 87//2 86//2
f 82//11 86//11 87//11 83//11 f 81//11 85//11 86//11 82//11
f 83//12 87//12 88//12 84//12 f 82//12 86//12 87//12 83//12
f 85//13 81//13 84//13 88//13 f 83//13 87//13 88//13 84//13
f 85//14 81//14 84//14 88//14

1
wfobj

@ -1 +0,0 @@
Subproject commit e4dc0f4d3627ab08e20d1be2dce41981e5771cca