Started working on NIF reader prototype

pull/7/head
Nicolay Korslund 15 years ago
parent 650f33811d
commit 769eae99b3

1
nif/.gitignore vendored

@ -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…
Cancel
Save