forked from mirror/openmw-tes3mp
NIF: implemented NiNode and NiTriShape
This commit is contained in:
parent
2d92d39f05
commit
4128462add
5 changed files with 193 additions and 13 deletions
|
@ -53,14 +53,17 @@ void NIFFile::parse()
|
||||||
{
|
{
|
||||||
SString rec = getString();
|
SString rec = getString();
|
||||||
|
|
||||||
cout << i << ": " << rec.toString() << endl;
|
cout << endl << i << ": " << rec.toString() << endl;
|
||||||
|
|
||||||
Node r;
|
Record *r;
|
||||||
r.read(this);
|
|
||||||
cout << r.name.toString() << endl;
|
|
||||||
cout << r.extra.getIndex() << endl;
|
|
||||||
cout << r.controller.getIndex() << endl;
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "record.h"
|
#include "record.h"
|
||||||
|
#include "nif_types.h"
|
||||||
|
|
||||||
using namespace Mangle::Stream;
|
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>(); }
|
int getInt() { return getType<int>(); }
|
||||||
|
|
||||||
template<class X>
|
template<class X>
|
||||||
|
@ -119,6 +122,11 @@ class NIFFile
|
||||||
|
|
||||||
SString getString() { return getArray<char>(); }
|
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)
|
const char *getString(int size)
|
||||||
{ return (const char*)inp->getPtr(size); }
|
{ return (const char*)inp->getPtr(size); }
|
||||||
};
|
};
|
||||||
|
|
66
nif/nif_types.h
Normal file
66
nif/nif_types.h
Normal 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
|
50
nif/node.h
50
nif/node.h
|
@ -35,11 +35,59 @@ namespace Nif
|
||||||
*/
|
*/
|
||||||
struct Node : Named
|
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)
|
void read(NIFFile *nif)
|
||||||
{
|
{
|
||||||
Named::read(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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,15 @@
|
||||||
#define _NIF_RECORD_PTR_H_
|
#define _NIF_RECORD_PTR_H_
|
||||||
|
|
||||||
#include "nif_file.h"
|
#include "nif_file.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Nif
|
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>
|
template <class X>
|
||||||
class RecordPtrT
|
class RecordPtrT
|
||||||
{
|
{
|
||||||
|
@ -53,7 +59,7 @@ class RecordPtrT
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up the actual object from the index
|
/// Look up the actual object from the index
|
||||||
X* operator->()
|
X* getPtr()
|
||||||
{
|
{
|
||||||
// Have we found the pointer already?
|
// Have we found the pointer already?
|
||||||
if(ptr == NULL)
|
if(ptr == NULL)
|
||||||
|
@ -69,20 +75,69 @@ class RecordPtrT
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Syntactic sugar
|
||||||
|
X* operator->() { return getPtr(); }
|
||||||
|
X& get() { return *getPtr(); }
|
||||||
|
|
||||||
/// Pointers are allowed to be empty
|
/// Pointers are allowed to be empty
|
||||||
bool empty() { return index == -1; }
|
bool empty() { return index == -1; }
|
||||||
|
|
||||||
int getIndex() { return index; }
|
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 Node;
|
||||||
|
class Extra;
|
||||||
|
class Property;
|
||||||
|
class Controller;
|
||||||
|
class NiTriShapeData;
|
||||||
|
class NiSkinInstance;
|
||||||
|
|
||||||
|
typedef RecordPtrT<Node> NodePtr;
|
||||||
typedef RecordPtrT<Extra> ExtraPtr;
|
typedef RecordPtrT<Extra> ExtraPtr;
|
||||||
typedef RecordPtrT<Controller> ControllerPtr;
|
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
|
} // Namespace
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue