diff --git a/nif/node.h b/nif/node.h index 39e9d9d46..5a4adea7f 100644 --- a/nif/node.h +++ b/nif/node.h @@ -74,11 +74,10 @@ struct Node : Named // Bone weight info, from NiSkinData const NiSkinData::BoneInfo *boneInfo; - // Bone index. If -1, this node is either not a bone, or the root - // bone in the skeleton. + // Bone index. If -1, this node is either not a bone, or if + // boneTrafo is set it is the root bone in the skeleton. short boneIndex; - // Make this the root animation bone void makeRootBone(const NiSkinData::BoneTrafo *tr) { boneTrafo = tr; diff --git a/nifogre/ogre_nif_loader.cpp b/nifogre/ogre_nif_loader.cpp index 5a595b4c1..72dc8ec15 100644 --- a/nifogre/ogre_nif_loader.cpp +++ b/nifogre/ogre_nif_loader.cpp @@ -41,8 +41,6 @@ using namespace Ogre; using namespace Nif; using namespace Mangle::VFS; -#define TRANSLATE 1 - // 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.) It's also used to @@ -395,7 +393,6 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags) } } - if(TRANSLATE) // TODO FIXME TEMP { /* Do in-place transformation of all the vertices and normals. This is pretty messy stuff, but we need it to make the sub-meshes @@ -467,7 +464,6 @@ static void handleNode(Mesh* mesh, Nif::Node *node, int flags, const Transformat // Apply the parent transformation to this node. We overwrite the // existing data with the final transformation. - if(TRANSLATE) // TODO FIXME TEMP if(trafo) { // Get a non-const reference to the node's data, since we're diff --git a/nifogre/ogre_nif_loader.h b/nifogre/ogre_nif_loader.h index c7c41b41c..846457c92 100644 --- a/nifogre/ogre_nif_loader.h +++ b/nifogre/ogre_nif_loader.h @@ -38,7 +38,9 @@ NIFLoader::load("somemesh.nif"); Afterwards, you can use the mesh name "somemesh.nif" normally to - create entities etc. + create entities and so on. The mesh isn't loaded from disk until + OGRE needs it for rendering. Thus the above load() command is not + very resource intensive. */ struct NIFLoader : Ogre::ManualResourceLoader { diff --git a/nifogre/tests/Makefile b/nifogre/tests/Makefile index cb93e5652..a7c50d100 100644 --- a/nifogre/tests/Makefile +++ b/nifogre/tests/Makefile @@ -1,6 +1,6 @@ GCC=g++ -all: ogre_manualresource_test ogre_nif_test +all: ogre_manualresource_test ogre_nif_test ogre_skeleton_test I_OGRE=$(shell pkg-config --cflags OGRE) L_OGRE=$(shell pkg-config --libs OGRE) @@ -8,6 +8,9 @@ L_OGRE=$(shell pkg-config --libs OGRE) ogre_manualresource_test: ogre_manualresource_test.cpp $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) +ogre_skeleton_test: ogre_skeleton_test.cpp + $(GCC) $^ -o $@ $(I_OGRE) $(L_OGRE) + 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) diff --git a/nifogre/tests/ogre_common.cpp b/nifogre/tests/ogre_common.cpp new file mode 100644 index 000000000..949c91c4f --- /dev/null +++ b/nifogre/tests/ogre_common.cpp @@ -0,0 +1,98 @@ +#include +#include +#include + +using namespace std; +using namespace Ogre; + +Root *root; +RenderWindow *window; +SceneManager *mgr; + +int shot = 0; + +// Lets you quit by closing the window +struct QuitListener : FrameListener +{ + bool frameStarted(const FrameEvent& evt) + { +#ifdef SCREENSHOT + if(shot == 1) window->writeContentsToFile("nif.png"); + if(shot < 2) shot++; +#endif + + if(window->isClosed()) + return false; + return true; + } +} qlistener; + +// This has to be packaged in a struct because C++ sucks +struct C +{ + static void doTest(); +}; + +int main(int argc, char**args) +{ + // Disable Ogre logging + new LogManager; + Log *log = LogManager::getSingleton().createLog(""); + log->setDebugOutputEnabled(false); + + // Set up Root. + root = new Root("plugins.cfg","ogre.cfg",""); + + if(!root->restoreConfig()) + { + cout << "WARNING: we do NOT recommend fullscreen mode!\n"; + if(!root->showConfigDialog()) + return 1; + } + + mgr = root->createSceneManager(ST_GENERIC); + + // Only render if there are arguments on the command line (we don't + // care what they are.) + bool render = (argc>=2); + + // Create a window + window = root->initialise(true, "Test"); + if(render) + { + // More initialization + Camera *cam = mgr->createCamera("cam"); + Viewport *vp = window->addViewport(cam); + cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight())); + cam->setFOVy(Degree(55)); + cam->setPosition(0,0,0); + cam->lookAt(0,0,10); + cam->setNearClipDistance(1); + + root->addFrameListener(&qlistener); + + // Background color + vp->setBackgroundColour(ColourValue(0.5,0.5,0.5)); + + mgr->setAmbientLight(ColourValue(1,1,1)); + } + + // Run the actual test + C::doTest(); + + // Render loop + if(render) + { + cout << "Rendering. Close the window to exit.\n"; + root->startRendering(); + } + + // Cleanup + delete root; + return 0; +} + +void doTest() +{ + cout << "hello\n"; +} diff --git a/nifogre/tests/ogre_manualresource_test.cpp b/nifogre/tests/ogre_manualresource_test.cpp index 1b87be6f4..75e169d54 100644 --- a/nifogre/tests/ogre_manualresource_test.cpp +++ b/nifogre/tests/ogre_manualresource_test.cpp @@ -1,7 +1,3 @@ -#include -#include -#include - /* This is a test of the manual resource loader interface to Ogre, applied to manually created meshes. It defines a simple mesh @@ -12,139 +8,14 @@ loader. */ -using namespace std; -using namespace Ogre; +#include "ogre_mesh_common.cpp" -struct MyMeshLoader : ManualResourceLoader +void C::doTest() { - 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 -struct QuitListener : FrameListener -{ - bool frameStarted(const FrameEvent& evt) - { - if(window->isClosed()) - return false; - return true; - } -} qlistener; - -int main(int argc, char**args) -{ - // When the test is done, consider disabling the rendering part - // unless a command line parameter is given (and write a note about - // this to console.) This allows you to run the test from scripts - // and still do some meaningful testing, even if you can't inpsect - // the result visually. - - // Disable Ogre logging - new LogManager; - Log *log = LogManager::getSingleton().createLog(""); - log->setDebugOutputEnabled(false); - - // Set up Root. - Root *root = new Root("plugins.cfg","ogre.cfg",""); - - if(!root->restoreConfig()) - { - cout << "WARNING: we do NOT recommend fullscreen mode!\n"; - if(!root->showConfigDialog()) - return 1; - } - - SceneManager *mgr = root->createSceneManager(ST_GENERIC); - - // Only render if there are arguments on the command line (we don't - // care what they are.) - bool render = (argc>=2); - - // Create a window - window = root->initialise(true, "Test"); - if(render) - { - // More initialization - Camera *cam = mgr->createCamera("cam"); - Viewport *vp = window->addViewport(cam); - cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight())); - cam->setFOVy(Degree(55)); - cam->setPosition(0,0,0); - cam->lookAt(0,0,10); - cam->setNearClipDistance(1); - - root->addFrameListener(&qlistener); - - // Background color - vp->setBackgroundColour(ColourValue(0.5,0.5,0.5)); - - 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); + makeMesh("mesh1.mm"); + makeMesh("mesh2.mm"); + makeMesh("mesh3.mm"); // Display the meshes { @@ -166,15 +37,4 @@ int main(int argc, char**args) node->attachObject(ent); node->setPosition(0,-2,8); } - - // Render loop - if(render) - { - cout << "Rendering. Close the window to exit.\n"; - root->startRendering(); - } - - // Cleanup - delete root; - return 0; } diff --git a/nifogre/tests/ogre_mesh_common.cpp b/nifogre/tests/ogre_mesh_common.cpp new file mode 100644 index 000000000..1cf3f42ef --- /dev/null +++ b/nifogre/tests/ogre_mesh_common.cpp @@ -0,0 +1,69 @@ +#include "ogre_common.cpp" + +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; + +MeshPtr makeMesh(const string &name) +{ + return MeshManager::getSingleton().createManual(name, "General", &mml); +} diff --git a/nifogre/tests/ogre_nif_test.cpp b/nifogre/tests/ogre_nif_test.cpp index 752ea686b..379ba4220 100644 --- a/nifogre/tests/ogre_nif_test.cpp +++ b/nifogre/tests/ogre_nif_test.cpp @@ -1,84 +1,17 @@ -#include - #include "../ogre_nif_loader.h" #include "../../bsa/bsa_archive.h" -using namespace std; -using namespace Ogre; +//#define SCREENSHOT -RenderWindow *window; +#include "ogre_common.cpp" //const char* mesh = "meshes\\a\\towershield_steel.nif"; //const char* mesh = "meshes\\r\\bonelord.nif"; //const char* mesh = "meshes\\m\\text_scroll_open_01.nif"; const char* mesh = "meshes\\f\\ex_ashl_a_banner_r.nif"; -int shot = 0; - -// Lets you quit by closing the window -struct QuitListener : FrameListener +void C::doTest() { - bool frameStarted(const FrameEvent& evt) - { - if(shot == 1) window->writeContentsToFile("nif.png"); - if(shot < 2) shot++; - - if(window->isClosed()) - return false; - return true; - } -} qlistener; - -int main(int argc, char**args) -{ - // When the test is done, consider disabling the rendering part - // unless a command line parameter is given (and write a note about - // this to console.) This allows you to run the test from scripts - // and still do some meaningful testing, even if you can't inpsect - // the result visually. - - // Disable Ogre logging - new LogManager; - Log *log = LogManager::getSingleton().createLog(""); - log->setDebugOutputEnabled(false); - - // Set up Root. - Root *root = new Root("plugins.cfg","ogre.cfg",""); - - if(!root->restoreConfig()) - { - cout << "WARNING: we do NOT recommend fullscreen mode!\n"; - if(!root->showConfigDialog()) - return 1; - } - - SceneManager *mgr = root->createSceneManager(ST_GENERIC); - - // Only render if there are arguments on the command line (we don't - // care what they are.) - bool render = (argc>=2); - - // Create a window - window = root->initialise(true, "Test"); - if(render) - { - // More initialization - Camera *cam = mgr->createCamera("cam"); - Viewport *vp = window->addViewport(cam); - cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight())); - cam->setFOVy(Degree(55)); - cam->setPosition(0,0,0); - cam->lookAt(0,0,10); - cam->setNearClipDistance(1); - - root->addFrameListener(&qlistener); - - // Background color - vp->setBackgroundColour(ColourValue(0.5,0.5,0.5)); - - mgr->setAmbientLight(ColourValue(1,1,1)); - } - // Add Morrowind.bsa resource location addBSA("../../data/Morrowind.bsa"); @@ -114,15 +47,4 @@ int main(int argc, char**args) node->setPosition(-2*sep,0,0); node->yaw(Degree(180)); //*/ - - // Render loop - if(render) - { - cout << "Rendering. Close the window to exit.\n"; - root->startRendering(); - } - - // Cleanup - delete root; - return 0; } diff --git a/nifogre/tests/ogre_skeleton_test.cpp b/nifogre/tests/ogre_skeleton_test.cpp new file mode 100644 index 000000000..5fd0c8d58 --- /dev/null +++ b/nifogre/tests/ogre_skeleton_test.cpp @@ -0,0 +1,14 @@ +#include "ogre_mesh_common.cpp" + +void C::doTest() +{ + MeshPtr msh = makeMesh("mesh1"); + + // Display the mesh + { + SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node"); + Entity *ent = mgr->createEntity("Mesh1", "mesh1"); + node->attachObject(ent); + node->setPosition(0,0,4); + } +}