Completed Ogre mesh insertion, started working on material decoding.

actorid
Nicolay Korslund 15 years ago
parent 14b91fb271
commit 9b7c995ae6

@ -81,7 +81,7 @@ void NIFFile::parse()
else if(rec == "NiCamera") { r = new NiCamera; r->recType = RC_NiCamera; }
// 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 == "NiZBufferProperty") { r = new NiZBufferProperty; r->recType = RC_NiZBufferProperty; }
else if(rec == "NiAlphaProperty") { r = new NiAlphaProperty; r->recType = RC_NiAlphaProperty; }

@ -37,7 +37,7 @@ enum RecordType
RC_NiRotatingParticles,
RC_NiAutoNormalParticles,
RC_NiCamera,
RC_NitexturingProperty,
RC_NiTexturingProperty,
RC_NiMaterialProperty,
RC_NiZBufferProperty,
RC_NiAlphaProperty,

@ -27,6 +27,8 @@
#include "../mangle/vfs/servers/ogre_vfs.h"
#include "../nif/nif_file.h"
#include "../nif/node.h"
#include "../nif/data.h"
#include "../nif/property.h"
// For warning messages
#include <iostream>
@ -49,6 +51,94 @@ static void warn(const string &msg)
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)
{
// Interpret flags
@ -68,13 +158,56 @@ static void handleNiTriShape(Mesh *mesh, NiTriShape *shape, int flags)
if(flags & 0x800)
{ collide = false; bbcollide = false; }
if(!collide && !bbcollide && hidden)
// This mesh apparently isn't being used for anything, so don't
// bother setting it up.
return;
// Material name for this submesh, if any
String material;
// Skip the entire material phase for hidden nodes
if(hidden) goto nomaterial;
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;
}
nomaterial:
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
// the flags we currently use, at least.
@ -85,7 +218,7 @@ static void handleNode(Mesh* mesh, Node *node, int flags)
while(!e->extra.empty())
{
// Get the next extra data in the list
e = e.extra.getPtr();
e = e->extra.getPtr();
assert(e != NULL);
if(e->recType == RC_NiStringExtraData)
@ -159,7 +292,11 @@ void NIFLoader::loadResource(Resource *resource)
}
// 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)

@ -81,7 +81,7 @@ int main(int argc, char**args)
SceneNode *node = mgr->getRootSceneNode()->createChildSceneNode("node");
Entity *ent = mgr->createEntity("Mesh1", mesh);
node->attachObject(ent);
node->setPosition(0,0,8);
node->setPosition(0,0,100);
// Render loop
if(render)

Loading…
Cancel
Save