forked from teamnwah/openmw-tes3coop
Completed Ogre mesh insertion, started working on material decoding.
This commit is contained in:
parent
14b91fb271
commit
9b7c995ae6
4 changed files with 146 additions and 9 deletions
|
@ -81,7 +81,7 @@ void NIFFile::parse()
|
||||||
else if(rec == "NiCamera") { r = new NiCamera; r->recType = RC_NiCamera; }
|
else if(rec == "NiCamera") { r = new NiCamera; r->recType = RC_NiCamera; }
|
||||||
|
|
||||||
// Properties
|
// Properties
|
||||||
else if(rec == "NiTexturingProperty") { r = new NiTexturingProperty; r->recType = RC_NitexturingProperty; }
|
else if(rec == "NiTexturingProperty") { r = new NiTexturingProperty; r->recType = RC_NiTexturingProperty; }
|
||||||
else if(rec == "NiMaterialProperty") { r = new NiMaterialProperty; r->recType = RC_NiMaterialProperty; }
|
else if(rec == "NiMaterialProperty") { r = new NiMaterialProperty; r->recType = RC_NiMaterialProperty; }
|
||||||
else if(rec == "NiZBufferProperty") { r = new NiZBufferProperty; r->recType = RC_NiZBufferProperty; }
|
else if(rec == "NiZBufferProperty") { r = new NiZBufferProperty; r->recType = RC_NiZBufferProperty; }
|
||||||
else if(rec == "NiAlphaProperty") { r = new NiAlphaProperty; r->recType = RC_NiAlphaProperty; }
|
else if(rec == "NiAlphaProperty") { r = new NiAlphaProperty; r->recType = RC_NiAlphaProperty; }
|
||||||
|
|
|
@ -37,7 +37,7 @@ enum RecordType
|
||||||
RC_NiRotatingParticles,
|
RC_NiRotatingParticles,
|
||||||
RC_NiAutoNormalParticles,
|
RC_NiAutoNormalParticles,
|
||||||
RC_NiCamera,
|
RC_NiCamera,
|
||||||
RC_NitexturingProperty,
|
RC_NiTexturingProperty,
|
||||||
RC_NiMaterialProperty,
|
RC_NiMaterialProperty,
|
||||||
RC_NiZBufferProperty,
|
RC_NiZBufferProperty,
|
||||||
RC_NiAlphaProperty,
|
RC_NiAlphaProperty,
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
#include "../mangle/vfs/servers/ogre_vfs.h"
|
#include "../mangle/vfs/servers/ogre_vfs.h"
|
||||||
#include "../nif/nif_file.h"
|
#include "../nif/nif_file.h"
|
||||||
#include "../nif/node.h"
|
#include "../nif/node.h"
|
||||||
|
#include "../nif/data.h"
|
||||||
|
#include "../nif/property.h"
|
||||||
|
|
||||||
// For warning messages
|
// For warning messages
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -49,6 +51,94 @@ static void warn(const string &msg)
|
||||||
cout << "WARNING (NIF): " << msg << endl;
|
cout << "WARNING (NIF): " << msg << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert Nif::NiTriShape to Ogre::SubMesh, attached the given mesh.
|
||||||
|
static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material)
|
||||||
|
{
|
||||||
|
NiTriShapeData *data = shape->data.getPtr();
|
||||||
|
SubMesh *sub = mesh->createSubMesh(shape->name.toString());
|
||||||
|
|
||||||
|
int nextBuf = 0;
|
||||||
|
|
||||||
|
// This function is just one long stream of Ogre-barf, but it works
|
||||||
|
// great.
|
||||||
|
|
||||||
|
// Add vertices
|
||||||
|
int numVerts = data->vertices.length / 3;
|
||||||
|
sub->vertexData = new VertexData();
|
||||||
|
sub->vertexData->vertexCount = numVerts;
|
||||||
|
sub->useSharedVertices = false;
|
||||||
|
VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
|
||||||
|
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION);
|
||||||
|
HardwareVertexBufferSharedPtr vbuf =
|
||||||
|
HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
|
VertexElement::getTypeSize(VET_FLOAT3),
|
||||||
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
|
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true);
|
||||||
|
VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
|
||||||
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
|
||||||
|
// Vertex normals
|
||||||
|
if(data->normals.length)
|
||||||
|
{
|
||||||
|
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL);
|
||||||
|
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
|
VertexElement::getTypeSize(VET_FLOAT3),
|
||||||
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
|
vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true);
|
||||||
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex colors
|
||||||
|
if(data->colors.length)
|
||||||
|
{
|
||||||
|
const float *colors = data->colors.ptr;
|
||||||
|
RenderSystem* rs = Root::getSingleton().getRenderSystem();
|
||||||
|
RGBA colorsRGB[numVerts];
|
||||||
|
RGBA *pColour = colorsRGB;
|
||||||
|
for(int i=0; i<numVerts; i++)
|
||||||
|
{
|
||||||
|
rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2],
|
||||||
|
colors[3]),pColour++);
|
||||||
|
colors += 4;
|
||||||
|
}
|
||||||
|
decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE);
|
||||||
|
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
|
VertexElement::getTypeSize(VET_COLOUR),
|
||||||
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
|
vbuf->writeData(0, vbuf->getSizeInBytes(), colorsRGB, true);
|
||||||
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texture UV coordinates
|
||||||
|
if(data->uvlist.length)
|
||||||
|
{
|
||||||
|
decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
|
||||||
|
vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(
|
||||||
|
VertexElement::getTypeSize(VET_FLOAT2),
|
||||||
|
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
|
|
||||||
|
vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true);
|
||||||
|
bind->setBinding(nextBuf++, vbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Triangle faces
|
||||||
|
int numFaces = data->triangles.length;
|
||||||
|
if(numFaces)
|
||||||
|
{
|
||||||
|
HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
|
||||||
|
createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
|
||||||
|
numFaces,
|
||||||
|
HardwareBuffer::HBU_STATIC_WRITE_ONLY);
|
||||||
|
ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true);
|
||||||
|
sub->indexData->indexBuffer = ibuf;
|
||||||
|
sub->indexData->indexCount = numFaces;
|
||||||
|
sub->indexData->indexStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set material if one was given
|
||||||
|
if(!material.empty()) sub->setMaterialName(material);
|
||||||
|
}
|
||||||
|
|
||||||
static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags)
|
static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags)
|
||||||
{
|
{
|
||||||
// Interpret flags
|
// Interpret flags
|
||||||
|
@ -68,13 +158,56 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags)
|
||||||
if(flags & 0x800)
|
if(flags & 0x800)
|
||||||
{ collide = false; bbcollide = false; }
|
{ collide = false; bbcollide = false; }
|
||||||
|
|
||||||
// Skip the entire material phase for hidden nodes
|
if(!collide && !bbcollide && hidden)
|
||||||
if(hidden) goto nomaterial;
|
// This mesh apparently isn't being used for anything, so don't
|
||||||
|
// bother setting it up.
|
||||||
|
return;
|
||||||
|
|
||||||
nomaterial:
|
// Material name for this submesh, if any
|
||||||
|
String material;
|
||||||
|
|
||||||
|
// Skip the entire material phase for hidden nodes
|
||||||
|
if(!hidden)
|
||||||
|
{
|
||||||
|
// These are set below if present
|
||||||
|
NiTexturingProperty *p = NULL;
|
||||||
|
NiMaterialProperty *m = NULL;
|
||||||
|
NiAlphaProperty *a = NULL;
|
||||||
|
|
||||||
|
// Scan the property list for material information
|
||||||
|
PropertyList &list = shape->props;
|
||||||
|
int n = list.length();
|
||||||
|
for(int i=0; i<n; i++)
|
||||||
|
{
|
||||||
|
if(!list.has(i)) continue;
|
||||||
|
Property *pr = &list[i];
|
||||||
|
|
||||||
|
if(pr->recType == RC_NiTexturingProperty)
|
||||||
|
p = (NiTexturingProperty*)pr;
|
||||||
|
else if(pr->recType == RC_NiMaterialProperty)
|
||||||
|
m = (NiMaterialProperty*)pr;
|
||||||
|
else if(pr->recType == RC_NiAlphaProperty)
|
||||||
|
a = (NiAlphaProperty*)pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p) cout << "texture present\n";
|
||||||
|
if(m) cout << "material present\n";
|
||||||
|
if(a) cout << "alpha present\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Do in-place transformation of all the vertices and
|
||||||
|
// normals. This is pretty messy stuff, but we need it to make the
|
||||||
|
// sub-meshes appear in the correct place. We also need to do it
|
||||||
|
// anyway for collision meshes. Since all the pointers in the NIF
|
||||||
|
// structures are pointing to an internal temporary memory buffer,
|
||||||
|
// it's OK to overwrite them (even though the pointers technically
|
||||||
|
// are const.)
|
||||||
|
|
||||||
|
if(!hidden)
|
||||||
|
createOgreMesh(mesh, shape, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleNode(Mesh* mesh, Node *node, int flags)
|
static void handleNode(Mesh* mesh, Nif::Node *node, int flags)
|
||||||
{
|
{
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// Accumulate the flags from all the child nodes. This works for all
|
||||||
// the flags we currently use, at least.
|
// the flags we currently use, at least.
|
||||||
|
@ -85,7 +218,7 @@ static void handleNode(Mesh* mesh, Node *node, int flags)
|
||||||
while(!e->extra.empty())
|
while(!e->extra.empty())
|
||||||
{
|
{
|
||||||
// Get the next extra data in the list
|
// Get the next extra data in the list
|
||||||
e = e.extra.getPtr();
|
e = e->extra.getPtr();
|
||||||
assert(e != NULL);
|
assert(e != NULL);
|
||||||
|
|
||||||
if(e->recType == RC_NiStringExtraData)
|
if(e->recType == RC_NiStringExtraData)
|
||||||
|
@ -159,7 +292,11 @@ void NIFLoader::loadResource(Resource *resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the node
|
// Handle the node
|
||||||
handleNode(mesh, (Node*)r, 0);
|
handleNode(mesh, (Nif::Node*)r, 0);
|
||||||
|
|
||||||
|
// Finally, set the bounding value. Just use bogus info right now.
|
||||||
|
mesh->_setBounds(AxisAlignedBox(-10,-10,-10,10,10,10));
|
||||||
|
mesh->_setBoundingSphereRadius(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshPtr NIFLoader::load(const char* name, const char* group)
|
MeshPtr NIFLoader::load(const char* name, const char* group)
|
||||||
|
|
|
@ -81,7 +81,7 @@ int main(int argc, char**args)
|
||||||
SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node");
|
SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node");
|
||||||
Entity *ent = mgr->createEntity("Mesh1", mesh);
|
Entity *ent = mgr->createEntity("Mesh1", mesh);
|
||||||
node->attachObject(ent);
|
node->attachObject(ent);
|
||||||
node->setPosition(0,0,8);
|
node->setPosition(0,0,100);
|
||||||
|
|
||||||
// Render loop
|
// Render loop
|
||||||
if(render)
|
if(render)
|
||||||
|
|
Loading…
Reference in a new issue