Made combined ogre/bsa/nif test, started working on NIFLoader

This commit is contained in:
Nicolay Korslund 2010-01-12 14:46:44 +01:00
parent cbb5252387
commit 908ef1c6ca
13 changed files with 235 additions and 110 deletions

View file

@ -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 <OgreArchive.h>
#include <OgreArchiveFactory.h>
#include <OgreArchiveManager.h>
#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");
}

44
bsa/bsa_archive.h Normal file
View file

@ -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

View file

@ -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

View file

@ -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";

View file

@ -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);
}
}

View file

@ -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(); }
/* ************************************************

View file

@ -32,6 +32,9 @@ class NIFFile;
/// Base class for all records
struct Record
{
// Record type name
SString recType;
virtual void read(NIFFile *nif) = 0;
/*

View file

@ -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 <Ogre.h>
#include "../mangle/vfs/servers/ogre_vfs.h"
#include "../nif/nif_file.h"
// For warning messages
#include <iostream>
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<Mesh*>(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);
}

50
nifogre/ogre_nif_loader.h Normal file
View file

@ -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 <OgreResource.h>
#include <OgreMesh.h>
#include <assert.h>
/** 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

View file

@ -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:

View file

@ -2,10 +2,19 @@
#include <iostream>
#include <assert.h>
/*
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)

View file

@ -1,74 +1,11 @@
#include <Ogre.h>
#include <iostream>
#include <assert.h>
#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<Mesh*>(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)

View file

@ -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