1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 19:19:56 +00:00

NIF: implemented NiNode and NiTriShape

This commit is contained in:
Nicolay Korslund 2010-01-06 15:00:08 +01:00
parent 2d92d39f05
commit 4128462add
5 changed files with 193 additions and 13 deletions

View file

@ -53,14 +53,17 @@ void NIFFile::parse()
{
SString rec = getString();
cout << i << ": " << rec.toString() << endl;
cout << endl << i << ": " << rec.toString() << endl;
Node r;
r.read(this);
cout << r.name.toString() << endl;
cout << r.extra.getIndex() << endl;
cout << r.controller.getIndex() << endl;
Record *r;
break;
// This can be heavily optimized later if needed. For example, a
// hash table or a FSM-based parser could be used to look up
// node names.
if(rec == "NiNode") r = new NiNode;
else if(rec == "NiTriShape") r = new NiTriShape;
else break;
r->read(this);
}
}

View file

@ -35,6 +35,7 @@
#include <assert.h>
#include "record.h"
#include "nif_types.h"
using namespace Mangle::Stream;
@ -107,7 +108,9 @@ class NIFFile
****************************************************/
template<class X> X getType() { return *((X*)inp->getPtr(sizeof(X))); }
template<class X> const X* getPtr() { return (const X*)inp->getPtr(sizeof(X)); }
template<class X> X getType() { return *getPtr<X>(); }
unsigned short getUshort() { return getType<unsigned short>(); }
int getInt() { return getType<int>(); }
template<class X>
@ -119,6 +122,11 @@ class NIFFile
SString getString() { return getArray<char>(); }
const Vector *getVector() { return getPtr<Vector>(); }
const Matrix *getMatrix() { return getPtr<Matrix>(); }
const Transformation *getTrafo() { return getPtr<Transformation>(); }
// For fixed-size strings where you already know the size
const char *getString(int size)
{ return (const char*)inp->getPtr(size); }
};

66
nif/nif_types.h Normal file
View file

@ -0,0 +1,66 @@
/*
OpenMW - The completely unofficial reimplementation of Morrowind
Copyright (C) 2008-2010 Nicolay Korslund
Email: < korslund@gmail.com >
WWW: http://openmw.sourceforge.net/
This file (nif_types.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 _NIF_TYPES_H_
#define _NIF_TYPES_H_
// Common types used in NIF files
namespace Nif
{
/* These packing #pragmas aren't really necessary on 32 bit
machines. I haven't tested on 64 bit yet. In any case it doesn't
hurt to include them. We can't allow any compiler-generated padding
in any of these structs, since they are used to interface directly
with raw data from the NIF files.
*/
#pragma pack(push)
#pragma pack(1)
struct Vector
{
float array[3];
};
struct Vector4
{
float array[4];
};
struct Matrix
{
Vector v[3];
};
struct Transformation
{
Vector pos;
Matrix rotation;
float scale;
Vector velocity;
};
#pragma pack(pop)
} // Namespace
#endif

View file

@ -35,11 +35,59 @@ namespace Nif
*/
struct Node : Named
{
// Not done
// Node flags. Interpretation depends somewhat on the type of node.
int flags;
const Transformation *trafo;
PropertyList props;
// Bounding box info
bool hasBounds;
const Vector *boundPos;
const Matrix *boundRot;
const Vector *boundXYZ;
void read(NIFFile *nif)
{
Named::read(nif);
flags = nif->getUshort();
trafo = nif->getTrafo();
props.read(nif);
hasBounds = nif->getInt();
if(hasBounds)
{
nif->getInt();
boundPos = nif->getVector();
boundRot = nif->getMatrix();
boundXYZ = nif->getVector();
}
}
};
struct NiNode : Node
{
NodeList children;
NodeList effects;
void read(NIFFile *nif)
{
Node::read(nif);
children.read(nif);
effects.read(nif);
}
};
struct NiTriShape : Node
{
NiTriShapeDataPtr data;
NiSkinInstancePtr skin;
void read(NIFFile *nif)
{
Node::read(nif);
data.read(nif);
skin.read(nif);
}
};

View file

@ -25,9 +25,15 @@
#define _NIF_RECORD_PTR_H_
#include "nif_file.h"
#include <vector>
namespace Nif
{
/** A reference to another record. It is read as an index from the
NIF, and later looked up in the index table to get an actual
pointer.
*/
template <class X>
class RecordPtrT
{
@ -53,7 +59,7 @@ class RecordPtrT
}
/// Look up the actual object from the index
X* operator->()
X* getPtr()
{
// Have we found the pointer already?
if(ptr == NULL)
@ -69,20 +75,69 @@ class RecordPtrT
return ptr;
}
/// Syntactic sugar
X* operator->() { return getPtr(); }
X& get() { return *getPtr(); }
/// Pointers are allowed to be empty
bool empty() { return index == -1; }
int getIndex() { return index; }
};
/** A list of references to other records. These are read as a list,
and later converted to pointers as needed. Not an optimized
implementation.
*/
template <class X>
class RecordListT
{
typedef RecordPtrT<X> Ptr;
std::vector<Ptr> list;
public:
void read(NIFFile *nif)
{
int len = nif->getInt();
list.resize(len);
assert(len >= 0 && len < 1000);
for(int i=0;i<len;i++)
list[i].read(nif);
}
X& operator[](int index)
{
assert(index >= 0 && index < list.size());
return list[index].get();
}
bool has(int index)
{
assert(index >= 0 && index < list.size());
return !list[index].empty();
}
int length() { return list.size(); }
};
class Extra;
class Controller;
class Node;
class Extra;
class Property;
class Controller;
class NiTriShapeData;
class NiSkinInstance;
typedef RecordPtrT<Node> NodePtr;
typedef RecordPtrT<Extra> ExtraPtr;
typedef RecordPtrT<Controller> ControllerPtr;
typedef RecordPtrT<Node> NodePtr;
typedef RecordPtrT<NiTriShapeData> NiTriShapeDataPtr;
typedef RecordPtrT<NiSkinInstance> NiSkinInstancePtr;
typedef RecordListT<Node> NodeList;
typedef RecordListT<Property> PropertyList;
} // Namespace
#endif