diff --git a/bsa/bsa_archive.cpp b/bsa/bsa_archive.cpp index 2b04177d03..a08937c9eb 100644 --- a/bsa/bsa_archive.cpp +++ b/bsa/bsa_archive.cpp @@ -21,16 +21,11 @@ */ -#ifndef _BSA_ARCHIVE_H_ -#define _BSA_ARCHIVE_H_ - - -/* This file inserts an archive manager for .bsa files into the OGRE - resource loading system. -*/ +#include "bsa_archive.h" #include #include +#include #include "bsa_file.h" #include "../mangle/stream/clients/ogre_datastream.h" @@ -156,4 +151,21 @@ public: void destroyInstance( Archive* arch) { delete arch; } }; -#endif +static bool init = false; + +// This is the only publicly exposed part in this file +void insertBSAFactory() +{ + if(!init) + { + ArchiveManager::getSingleton().addArchiveFactory( new BSAArchiveFactory ); + init = true; + } +} + +void addBSA(const char* name, const char* group) +{ + insertBSAFactory(); + ResourceGroupManager::getSingleton(). + addResourceLocation(name, "BSA", "General"); +} diff --git a/bsa/bsa_archive.h b/bsa/bsa_archive.h new file mode 100644 index 0000000000..a85508d54a --- /dev/null +++ b/bsa/bsa_archive.h @@ -0,0 +1,44 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008-2010 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.sourceforge.net/ + + This file (cpp_bsaarchive.h) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + +#ifndef _BSA_ARCHIVE_H_ +#define _BSA_ARCHIVE_H_ + +/** Insert the archive manager for .bsa files into the OGRE resource + loading system. You only need to call this function once. + + After calling it, you can do: + + ResourceGroupManager::getSingleton(). + addResourceLocation("Morrowind.bsa", "BSA", "General"); + + or add BSA files to resources.cfg, etc. You can also use the + shortcut addBSA() below, which will call insertBSAFactory() for + you. +*/ +void insertBSAFactory(); + +/// Add the given BSA file to the Ogre resource system. +void addBSA(const char* file, const char* group="General"); + +#endif diff --git a/bsa/tests/Makefile b/bsa/tests/Makefile index 483f0c336e..bc2bf4e50f 100644 --- a/bsa/tests/Makefile +++ b/bsa/tests/Makefile @@ -8,7 +8,7 @@ L_OGRE=$(shell pkg-config --libs OGRE) bsa_file_test: bsa_file_test.cpp ../bsa_file.cpp $(GCC) $^ -o $@ -ogre_archive_test: ogre_archive_test.cpp ../bsa_file.cpp +ogre_archive_test: ogre_archive_test.cpp ../bsa_file.cpp ../bsa_archive.cpp $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) bsatool: bsatool.cpp ../bsa_file.cpp bsatool_cmd.c diff --git a/bsa/tests/ogre_archive_test.cpp b/bsa/tests/ogre_archive_test.cpp index 09db3accc1..a5b3b75249 100644 --- a/bsa/tests/ogre_archive_test.cpp +++ b/bsa/tests/ogre_archive_test.cpp @@ -3,7 +3,7 @@ // This is a test of the BSA archive handler for OGRE. -#include "../bsa_archive.cpp" +#include "../bsa_archive.h" using namespace Ogre; using namespace std; @@ -18,12 +18,8 @@ int main() // Set up Root Root *root = new Root("","",""); - // Add the archive manager - ArchiveManager::getSingleton().addArchiveFactory( new BSAArchiveFactory ); - - // Add Morrowind.bsa - ResourceGroupManager::getSingleton(). - addResourceLocation("../../data/Morrowind.bsa", "BSA", "General"); + // Add the BSA + addBSA("../../data/Morrowind.bsa"); // Pick a sample file String tex = "textures\\tx_natural_cavern_wall13.dds"; diff --git a/nif/nif_file.cpp b/nif/nif_file.cpp index 32b26eb067..3a4c2f37f8 100644 --- a/nif/nif_file.cpp +++ b/nif/nif_file.cpp @@ -141,6 +141,9 @@ void NIFFile::parse() else fail("Unknown record type " + rec.toString()); + assert(r != NULL); + r->recType = rec; + records[i] = r; r->read(this); } } diff --git a/nif/nif_file.h b/nif/nif_file.h index 68fd6edcac..4943e4e795 100644 --- a/nif/nif_file.h +++ b/nif/nif_file.h @@ -93,6 +93,7 @@ class NIFFile parse(); } + /// Get a given record Record *getRecord(int index) { assert(index >= 0 && index < records.size()); @@ -101,6 +102,8 @@ class NIFFile return res; } + /// Number of records + int numRecords() { return records.size(); } /* ************************************************ diff --git a/nif/record.h b/nif/record.h index 0fb64ed3a9..07a7cc82df 100644 --- a/nif/record.h +++ b/nif/record.h @@ -32,6 +32,9 @@ class NIFFile; /// Base class for all records struct Record { + // Record type name + SString recType; + virtual void read(NIFFile *nif) = 0; /* diff --git a/nifogre/ogre_nif_loader.cpp b/nifogre/ogre_nif_loader.cpp new file mode 100644 index 0000000000..680637fd54 --- /dev/null +++ b/nifogre/ogre_nif_loader.cpp @@ -0,0 +1,81 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008-2010 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.sourceforge.net/ + + This file (ogre_nif_loader.cpp) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + +#include "ogre_nif_loader.h" +#include + +#include "../mangle/vfs/servers/ogre_vfs.h" +#include "../nif/nif_file.h" + +// For warning messages +#include + +using namespace std; +using namespace Ogre; +using namespace Nif; +using namespace Mangle::VFS; + +// This is the interface to the Ogre resource system. It allows us to +// load NIFs from BSAs, in the file system and in any other place we +// tell Ogre to look (eg. in zip or rar files.) +OgreVFS *vfs; + +// Singleton instance used by load() +static NIFLoader g_sing; + +static void warn(const string &msg) +{ + cout << "WARNING (NIF): " << msg << endl; +} + +void NIFLoader::loadResource(Resource *resource) +{ + // Set up the VFS if it hasn't been done already + if(!vfs) vfs = new OgreVFS("General"); + + // Get the mesh + Mesh *mesh = dynamic_cast(resource); + assert(mesh); + + // Look it up + const String &name = mesh->getName(); + if(!vfs->isFile(name)) + { + warn("File not found: " + name); + return; + } + + // Load the NIF + cout << "Loading " << name << endl; + NIFFile nif(vfs->open(name), name); + + int n = nif.numRecords(); + cout << "Number of records: " << n << endl; + if(n) + cout << "First record type: " << nif.getRecord(0)->recType.toString() << endl; +} + +MeshPtr NIFLoader::load(const char* name, const char* group) +{ + return MeshManager::getSingleton().createManual(name, group, &g_sing); +} diff --git a/nifogre/ogre_nif_loader.h b/nifogre/ogre_nif_loader.h new file mode 100644 index 0000000000..c7c41b41c2 --- /dev/null +++ b/nifogre/ogre_nif_loader.h @@ -0,0 +1,50 @@ +/* + OpenMW - The completely unofficial reimplementation of Morrowind + Copyright (C) 2008-2010 Nicolay Korslund + Email: < korslund@gmail.com > + WWW: http://openmw.sourceforge.net/ + + This file (ogre_nif_loader.h) is part of the OpenMW package. + + OpenMW is distributed as free software: you can redistribute it + and/or modify it under the terms of the GNU General Public License + version 3, as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + version 3 along with this program. If not, see + http://www.gnu.org/licenses/ . + + */ + +#ifndef _OGRE_NIF_LOADER_H_ +#define _OGRE_NIF_LOADER_H_ + +#include +#include +#include + +/** Manual resource loader for NIF meshes. This is the main class + responsible for translating the internal NIF mesh structure into + something Ogre can use. Later it will also handle the insertion of + collision meshes into Bullet / OgreBullet. + + You have to insert meshes manually into Ogre like this: + + NIFLoader::load("somemesh.nif"); + + Afterwards, you can use the mesh name "somemesh.nif" normally to + create entities etc. + */ +struct NIFLoader : Ogre::ManualResourceLoader +{ + void loadResource(Ogre::Resource *resource); + + static Ogre::MeshPtr load(const char* name, const char* group="General"); +}; + +#endif diff --git a/nifogre/tests/Makefile b/nifogre/tests/Makefile index 9e8284df2a..cb93e56529 100644 --- a/nifogre/tests/Makefile +++ b/nifogre/tests/Makefile @@ -8,7 +8,7 @@ L_OGRE=$(shell pkg-config --libs OGRE) ogre_manualresource_test: ogre_manualresource_test.cpp $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) -ogre_nif_test: ogre_nif_test.cpp ../../nif/nif_file.cpp ../../bsa/bsa_file.cpp ../../tools/stringops.cpp +ogre_nif_test: ogre_nif_test.cpp ../../nif/nif_file.cpp ../../bsa/bsa_file.cpp ../../bsa/bsa_archive.cpp ../../tools/stringops.cpp ../../mangle/vfs/servers/ogre_vfs.cpp ../ogre_nif_loader.cpp $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) clean: diff --git a/nifogre/tests/ogre_manualresource_test.cpp b/nifogre/tests/ogre_manualresource_test.cpp index 0d40eb6ae0..1b87be6f48 100644 --- a/nifogre/tests/ogre_manualresource_test.cpp +++ b/nifogre/tests/ogre_manualresource_test.cpp @@ -2,10 +2,19 @@ #include #include +/* + This is a test of the manual resource loader interface to Ogre, + applied to manually created meshes. It defines a simple mesh + consisting of two triangles, and creates three instances of it as + different meshes using the same loader. It is a precursor to the NIF + loading code. If the Ogre interface changes and you have to change + this test, then you will also have to change parts of the NIF + loader. + */ + using namespace std; using namespace Ogre; -// Why doesn't it work? Bad code, BAD! struct MyMeshLoader : ManualResourceLoader { void loadResource(Resource *resource) diff --git a/nifogre/tests/ogre_nif_test.cpp b/nifogre/tests/ogre_nif_test.cpp index 0d40eb6ae0..e132ca6b70 100644 --- a/nifogre/tests/ogre_nif_test.cpp +++ b/nifogre/tests/ogre_nif_test.cpp @@ -1,74 +1,11 @@ #include -#include -#include + +#include "../ogre_nif_loader.h" +#include "../../bsa/bsa_archive.h" using namespace std; using namespace Ogre; -// Why doesn't it work? Bad code, BAD! -struct MyMeshLoader : ManualResourceLoader -{ - void loadResource(Resource *resource) - { - Mesh *mesh = dynamic_cast(resource); - assert(mesh); - - const String& name = mesh->getName(); - cout << "Manually loading mesh " << name << endl; - - // Create the mesh here - int numVerts = 4; - int numFaces = 2*3; - const float vertices[] = - { -1,-1,0, 1,-1,0, - 1,1,0, -1,1,0 }; - - const short faces[] = - { 0,2,1, 0,3,2 }; - - mesh->sharedVertexData = new VertexData(); - mesh->sharedVertexData->vertexCount = numVerts; - - VertexDeclaration* decl = mesh->sharedVertexData->vertexDeclaration; - - decl->addElement(0, 0, VET_FLOAT3, VES_POSITION); - - HardwareVertexBufferSharedPtr vbuf = - HardwareBufferManager::getSingleton().createVertexBuffer( - VertexElement::getTypeSize(VET_FLOAT3), - numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); - - // Upload the vertex data to the card - vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); - - // Set vertex buffer binding so buffer 0 is bound to our vertex buffer - VertexBufferBinding* bind = mesh->sharedVertexData->vertexBufferBinding; - bind->setBinding(0, vbuf); - - /// Allocate index buffer of the requested number of faces - HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). - createIndexBuffer(HardwareIndexBuffer::IT_16BIT, - numFaces, - HardwareBuffer::HBU_STATIC_WRITE_ONLY); - - /// Upload the index data to the card - ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true); - - SubMesh* sub = mesh->createSubMesh(name+"tris"); - sub->useSharedVertices = true; - - /// Set parameters of the submesh - sub->indexData->indexBuffer = ibuf; - sub->indexData->indexCount = numFaces; - sub->indexData->indexStart = 0; - - mesh->_setBounds(AxisAlignedBox(-1.1,-1.1,-1.1,1.1,1.1,1.1)); - mesh->_setBoundingSphereRadius(2); - } -}; - -MyMeshLoader mml; - RenderWindow *window; // Lets you quit by closing the window @@ -132,31 +69,18 @@ int main(int argc, char**args) mgr->setAmbientLight(ColourValue(1,1,1)); } - // Create a couple of manual meshes - MeshManager::getSingleton().createManual("mesh1.mm", "General", &mml); - MeshManager::getSingleton().createManual("mesh2.mm", "General", &mml); - MeshManager::getSingleton().createManual("mesh3.mm", "General", &mml); + // Add Morrowind.bsa resource location + addBSA("../../data/Morrowind.bsa"); - // Display the meshes - { - SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node"); - Entity *ent = mgr->createEntity("Mesh1", "mesh1.mm"); - node->attachObject(ent); - node->setPosition(3,1,8); - } + // Insert the mesh + const char* mesh = "meshes\\a\\towershield_steel.nif"; + NIFLoader::load(mesh); - { - SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node2"); - Entity *ent = mgr->createEntity("Mesh2", "mesh2.mm"); - node->attachObject(ent); - node->setPosition(-3,1,8); - } - { - SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node3"); - Entity *ent = mgr->createEntity("Mesh3", "mesh3.mm"); - node->attachObject(ent); - node->setPosition(0,-2,8); - } + // Display it + SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node"); + Entity *ent = mgr->createEntity("Mesh1", mesh); + node->attachObject(ent); + node->setPosition(0,0,8); // Render loop if(render) diff --git a/nifogre/tests/output/ogre_nif_test.out b/nifogre/tests/output/ogre_nif_test.out index 2eab2d50dd..84e3ef87dc 100644 --- a/nifogre/tests/output/ogre_nif_test.out +++ b/nifogre/tests/output/ogre_nif_test.out @@ -1,3 +1,3 @@ -Manually loading mesh mesh1.mm -Manually loading mesh mesh2.mm -Manually loading mesh mesh3.mm +Loading meshes\a\towershield_steel.nif +Number of records: 10 +First record type: NiNode