mirror of https://github.com/OpenMW/openmw.git
Started working on NIF reader prototype
parent
650f33811d
commit
769eae99b3
@ -0,0 +1 @@
|
||||
old_d
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
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_file.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_FILE_H_
|
||||
#define _NIF_FILE_H_
|
||||
|
||||
#include <string>
|
||||
#include "../mangle/stream/stream.h"
|
||||
#include "../mangle/stream/filters/buffer_stream.h"
|
||||
#include "../mangle/tools/str_exception.h"
|
||||
#include "../tools/stringops.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Only used during development. Remove later.
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
using namespace Mangle::Stream;
|
||||
|
||||
// A simple array implementation containing a pointer and a
|
||||
// length. Used for holding slices into a data buffer.
|
||||
#include <string.h>
|
||||
template <class T>
|
||||
struct SliceArray
|
||||
{
|
||||
const T* ptr;
|
||||
size_t length;
|
||||
|
||||
SliceArray(const T* _ptr, size_t _length)
|
||||
: ptr(_ptr), length(_length) {}
|
||||
|
||||
bool operator==(SliceArray &t)
|
||||
{
|
||||
return
|
||||
length == t.length &&
|
||||
(memcmp(ptr,t.ptr, length*sizeof(T)) == 0);
|
||||
}
|
||||
|
||||
/// Only use this for stings
|
||||
bool operator==(const char* str)
|
||||
{
|
||||
return
|
||||
str[length] == 0 &&
|
||||
(strncmp(ptr, str, length) == 0);
|
||||
}
|
||||
|
||||
/** This allocates a copy of the data. Only use this for debugging
|
||||
and error messages.
|
||||
*/
|
||||
std::string toString()
|
||||
{ return std::string(ptr,length); }
|
||||
};
|
||||
|
||||
typedef SliceArray<char> SString;
|
||||
typedef SliceArray<int> IntArray;
|
||||
typedef SliceArray<float> FloatArray;
|
||||
|
||||
class NIFFile
|
||||
{
|
||||
enum NIFVersion
|
||||
{
|
||||
VER_MW = 0x04000002 // Morrowind NIFs
|
||||
};
|
||||
|
||||
/// Nif file version
|
||||
int ver;
|
||||
|
||||
/// Input stream
|
||||
StreamPtr inp;
|
||||
|
||||
/// File name, used for error messages
|
||||
std::string filename;
|
||||
|
||||
/// Record list
|
||||
typedef void NifRecord;
|
||||
std::vector<NifRecord*> records;
|
||||
|
||||
/// Used for error handling
|
||||
void fail(const std::string &msg)
|
||||
{
|
||||
std::string err = "NIFFile Error: " + msg;
|
||||
err += "\nFile: " + filename;
|
||||
throw str_exception(err);
|
||||
}
|
||||
|
||||
/// Parse the file
|
||||
void parse()
|
||||
{
|
||||
// Check the header string
|
||||
const char* head = getString(40);
|
||||
if(!begins(head, "NetImmerse File Format"))
|
||||
fail("Invalid NIF header");
|
||||
|
||||
// Get BCD version
|
||||
ver = getInt();
|
||||
if(ver != VER_MW)
|
||||
fail("Unsupported NIF version");
|
||||
|
||||
// Number of records
|
||||
int recNum = getInt();
|
||||
records.resize(recNum);
|
||||
|
||||
for(int i=0;i<recNum;i++)
|
||||
{
|
||||
SString rec = getString();
|
||||
|
||||
cout << i << ": " << rec.toString() << endl;
|
||||
|
||||
if(rec == "NiNode") cout << " got a node!\n";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// Open a NIF stream. The name is used for error messages.
|
||||
NIFFile(StreamPtr nif, const std::string &name)
|
||||
: filename(name)
|
||||
{
|
||||
/* Load the entire file into memory. This allows us to use
|
||||
direct pointers to the data arrays in the NIF, instead of
|
||||
individually allocating and copying each one.
|
||||
|
||||
The NIF data is only stored temporarily in memory, since once
|
||||
the mesh data is loaded it is siphoned into OGRE and
|
||||
deleted. For that reason, we might improve this further and
|
||||
use a shared region/pool based allocation scheme in the
|
||||
future, especially since only one NIFFile will ever be loaded
|
||||
at any given time.
|
||||
*/
|
||||
inp = StreamPtr(new BufferStream(nif));
|
||||
|
||||
parse();
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************
|
||||
|
||||
Parser functions
|
||||
|
||||
****************************************************/
|
||||
|
||||
template<class X> X getType() { return *((X*)inp->getPtr(sizeof(X))); }
|
||||
int getInt() { return getType<int>(); }
|
||||
|
||||
template<class X>
|
||||
SliceArray<X> getArray()
|
||||
{
|
||||
int len = getInt();
|
||||
return SliceArray<X>((const X*)inp->getPtr(len), len);
|
||||
}
|
||||
|
||||
SString getString() { return getArray<char>(); }
|
||||
|
||||
const char *getString(int size)
|
||||
{ return (const char*)inp->getPtr(size); }
|
||||
};
|
||||
|
||||
#endif
|
@ -0,0 +1,3 @@
|
||||
niftool
|
||||
*_test
|
||||
*.nif
|
@ -0,0 +1,9 @@
|
||||
GCC=g++
|
||||
|
||||
all: niftool
|
||||
|
||||
niftool: niftool.cpp ../nif_file.h
|
||||
$(GCC) $< ../../tools/stringops.cpp -o $@
|
||||
|
||||
clean:
|
||||
rm niftool
|
@ -0,0 +1,23 @@
|
||||
#include "../nif_file.h"
|
||||
|
||||
/*
|
||||
Test of the NIFFile class
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "../../mangle/stream/servers/file_stream.h"
|
||||
|
||||
using namespace Mangle::Stream;
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char **args)
|
||||
{
|
||||
if(argc != 2)
|
||||
{
|
||||
cout << "Specify a NIF file on the command line\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
StreamPtr file(new FileStream(args[1]));
|
||||
NIFFile nif(file, args[1]);
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
make || exit
|
||||
|
||||
mkdir -p output
|
||||
|
||||
PROGS=*_test
|
||||
|
||||
for a in $PROGS; do
|
||||
if [ -f "output/$a.out" ]; then
|
||||
echo "Running $a:"
|
||||
$a | diff output/$a.out -
|
||||
else
|
||||
echo "Creating $a.out"
|
||||
$a > "output/$a.out"
|
||||
git add "output/$a.out"
|
||||
fi
|
||||
done
|
@ -0,0 +1,14 @@
|
||||
#include "stringops.h"
|
||||
|
||||
/// Returns true if str1 begins with substring str2
|
||||
bool begins(const char* str1, const char* str2)
|
||||
{
|
||||
while(*str2)
|
||||
{
|
||||
if(*str1 == 0 || *str1 != *str2) return false;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
return true;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
#ifndef __STRINGOPS_H
|
||||
#define __STRINGOPS_H
|
||||
|
||||
/// Returns true if str1 begins with substring str2
|
||||
bool begins(const char* str1, const char* str2);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue