1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-05 09:15:33 +00:00

Started working on NIF reader prototype

This commit is contained in:
Nicolay Korslund 2010-01-04 14:48:18 +01:00
parent 650f33811d
commit 769eae99b3
8 changed files with 255 additions and 0 deletions

1
nif/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
old_d

180
nif/nif_file.h Normal file
View file

@ -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

3
nif/tests/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
niftool
*_test
*.nif

9
nif/tests/Makefile Normal file
View file

@ -0,0 +1,9 @@
GCC=g++
all: niftool
niftool: niftool.cpp ../nif_file.h
$(GCC) $< ../../tools/stringops.cpp -o $@
clean:
rm niftool

23
nif/tests/niftool.cpp Normal file
View file

@ -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]);
}

18
nif/tests/test.sh Executable file
View file

@ -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

14
tools/stringops.cpp Normal file
View file

@ -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;
}

7
tools/stringops.h Normal file
View file

@ -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