mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 01:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			829 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			829 lines
		
	
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
  OpenMW - The completely unofficial reimplementation of Morrowind
 | 
						|
  Copyright (C) 2008-2010  Nicolay Korslund
 | 
						|
  Email: < korslund@gmail.com >
 | 
						|
  WWW: http://openmw.sourceforge.net/
 | 
						|
 | 
						|
  This file (data.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_DATA_H_
 | 
						|
#define _NIF_DATA_H_
 | 
						|
 | 
						|
#include "controlled.hpp"
 | 
						|
 | 
						|
#include <OgreQuaternion.h>
 | 
						|
#include <OgreVector3.h>
 | 
						|
 | 
						|
namespace Nif
 | 
						|
{
 | 
						|
 | 
						|
class NiSourceTexture : public Named
 | 
						|
{
 | 
						|
public:
 | 
						|
 | 
						|
  // Is this an external (references a separate texture file) or
 | 
						|
  // internal (data is inside the nif itself) texture?
 | 
						|
  bool external;
 | 
						|
 | 
						|
  Misc::SString filename;    // In case of external textures
 | 
						|
  NiPixelDataPtr data; // In case of internal textures
 | 
						|
 | 
						|
  /* Pixel layout
 | 
						|
     0 - Palettised
 | 
						|
     1 - High color 16
 | 
						|
     2 - True color 32
 | 
						|
     3 - Compressed
 | 
						|
     4 - Bumpmap
 | 
						|
     5 - Default */
 | 
						|
  int pixel;
 | 
						|
 | 
						|
  /* Mipmap format
 | 
						|
     0 - no
 | 
						|
     1 - yes
 | 
						|
     2 - default */
 | 
						|
  int mipmap;
 | 
						|
 | 
						|
  /* Alpha
 | 
						|
     0 - none
 | 
						|
     1 - binary
 | 
						|
     2 - smooth
 | 
						|
     3 - default (use material alpha, or multiply material with texture if present)
 | 
						|
  */
 | 
						|
  int alpha;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    Named::read(nif);
 | 
						|
 | 
						|
    external = !!nif->getByte();
 | 
						|
 | 
						|
    if(external) filename = nif->getString();
 | 
						|
    else
 | 
						|
      {
 | 
						|
        nif->getByte(); // always 1
 | 
						|
        data.read(nif);
 | 
						|
      }
 | 
						|
 | 
						|
    pixel = nif->getInt();
 | 
						|
    mipmap = nif->getInt();
 | 
						|
    alpha = nif->getInt();
 | 
						|
 | 
						|
    nif->getByte(); // always 1
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
// Common ancestor for several data classes
 | 
						|
class ShapeData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  Misc::FloatArray vertices, normals, colors, uvlist;
 | 
						|
  const Vector *center;
 | 
						|
  float radius;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int verts = nif->getShort();
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      vertices = nif->getFloatLen(verts*3);
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      normals = nif->getFloatLen(verts*3);
 | 
						|
 | 
						|
    center = nif->getVector();
 | 
						|
    radius = nif->getFloat();
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      colors = nif->getFloatLen(verts*4);
 | 
						|
 | 
						|
    int uvs = nif->getShort();
 | 
						|
 | 
						|
    // Only the first 6 bits are used as a count. I think the rest are
 | 
						|
    // flags of some sort.
 | 
						|
    uvs &= 0x3f;
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      uvlist = nif->getFloatLen(uvs*verts*2);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiTriShapeData : public ShapeData
 | 
						|
{
 | 
						|
public:
 | 
						|
  // Triangles, three vertex indices per triangle
 | 
						|
  Misc::SliceArray<short> triangles;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    ShapeData::read(nif);
 | 
						|
 | 
						|
    int tris = nif->getShort();
 | 
						|
    if(tris)
 | 
						|
      {
 | 
						|
        // We have three times as many vertices as triangles, so this
 | 
						|
        // is always equal to tris*3.
 | 
						|
        int cnt = nif->getInt();
 | 
						|
        triangles = nif->getArrayLen<short>(cnt);
 | 
						|
      }
 | 
						|
 | 
						|
    // Read the match list, which lists the vertices that are equal to
 | 
						|
    // vertices. We don't actually need need this for anything, so
 | 
						|
    // just skip it.
 | 
						|
    int verts = nif->getShort();
 | 
						|
    if(verts)
 | 
						|
      {
 | 
						|
        for(int i=0;i<verts;i++)
 | 
						|
          {
 | 
						|
            // Number of vertices matching vertex 'i'
 | 
						|
            short num = nif->getShort();
 | 
						|
            nif->skip(num*sizeof(short));
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiAutoNormalParticlesData : public ShapeData
 | 
						|
{
 | 
						|
public:
 | 
						|
  int activeCount;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    ShapeData::read(nif);
 | 
						|
 | 
						|
    // Should always match the number of vertices
 | 
						|
    activeCount = nif->getShort();
 | 
						|
 | 
						|
    // Skip all the info, we don't support particles yet
 | 
						|
    nif->getFloat();  // Active radius ?
 | 
						|
    nif->getShort(); // Number of valid entries in the following arrays ?
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      // Particle sizes
 | 
						|
      nif->getFloatLen(activeCount);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiRotatingParticlesData : public NiAutoNormalParticlesData
 | 
						|
{
 | 
						|
public:
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    NiAutoNormalParticlesData::read(nif);
 | 
						|
 | 
						|
    if(nif->getInt())
 | 
						|
      // Rotation quaternions. I THINK activeCount is correct here,
 | 
						|
      // but verts (vertex number) might also be correct, if there is
 | 
						|
      // any case where the two don't match.
 | 
						|
      nif->getArrayLen<Vector4>(activeCount);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiPosData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int count = nif->getInt();
 | 
						|
    int type = nif->getInt();
 | 
						|
    if(type != 1 && type != 2)
 | 
						|
      nif->fail("Cannot handle NiPosData type");
 | 
						|
 | 
						|
    // TODO: Could make structs of these. Seems to be identical to
 | 
						|
    // translation in NiKeyframeData.
 | 
						|
    for(int i=0; i<count; i++)
 | 
						|
      {
 | 
						|
        /*float time =*/ nif->getFloat();
 | 
						|
        nif->getVector(); // This isn't really shared between type 1
 | 
						|
                          // and type 2, most likely
 | 
						|
        if(type == 2)
 | 
						|
          {
 | 
						|
            nif->getVector();
 | 
						|
            nif->getVector();
 | 
						|
          }
 | 
						|
      }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiUVData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    // TODO: This is claimed to be a "float animation key", which is
 | 
						|
    // also used in FloatData and KeyframeData. We could probably
 | 
						|
    // reuse and refactor a lot of this if we actually use it at some
 | 
						|
    // point.
 | 
						|
 | 
						|
    for(int i=0; i<2; i++)
 | 
						|
      {
 | 
						|
        int count = nif->getInt();
 | 
						|
 | 
						|
        if(count)
 | 
						|
          {
 | 
						|
            nif->getInt(); // always 2
 | 
						|
            nif->getArrayLen<Vector4>(count); // Really one time float + one vector
 | 
						|
          }
 | 
						|
      }
 | 
						|
    // Always 0
 | 
						|
    nif->getInt();
 | 
						|
    nif->getInt();
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiFloatData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int count = nif->getInt();
 | 
						|
    nif->getInt(); // always 2
 | 
						|
    nif->getArrayLen<Vector4>(count); // Really one time float + one vector
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiPixelData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  unsigned int rmask, gmask, bmask, amask;
 | 
						|
  int bpp, mips;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    nif->getInt(); // always 0 or 1
 | 
						|
 | 
						|
    rmask = nif->getInt(); // usually 0xff
 | 
						|
    gmask = nif->getInt(); // usually 0xff00
 | 
						|
    bmask = nif->getInt(); // usually 0xff0000
 | 
						|
    amask = nif->getInt(); // usually 0xff000000 or zero
 | 
						|
 | 
						|
    bpp = nif->getInt();
 | 
						|
 | 
						|
    // Unknown
 | 
						|
    nif->skip(12);
 | 
						|
 | 
						|
    mips = nif->getInt();
 | 
						|
 | 
						|
    // Bytes per pixel, should be bpp * 8
 | 
						|
    /*int bytes =*/ nif->getInt();
 | 
						|
 | 
						|
    for(int i=0; i<mips; i++)
 | 
						|
      {
 | 
						|
        // Image size and offset in the following data field
 | 
						|
        /*int x =*/ nif->getInt();
 | 
						|
        /*int y =*/ nif->getInt();
 | 
						|
        /*int offset =*/ nif->getInt();
 | 
						|
      }
 | 
						|
 | 
						|
    // Skip the data
 | 
						|
    unsigned int dataSize = nif->getInt();
 | 
						|
    nif->skip(dataSize);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiColorData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  struct ColorData
 | 
						|
  {
 | 
						|
    float time;
 | 
						|
    Vector4 rgba;
 | 
						|
  };
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int count = nif->getInt();
 | 
						|
    nif->getInt(); // always 1
 | 
						|
 | 
						|
    // Skip the data
 | 
						|
    assert(sizeof(ColorData) == 4*5);
 | 
						|
    nif->skip(sizeof(ColorData) * count);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiVisData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int count = nif->getInt();
 | 
						|
    /*
 | 
						|
      Each VisData consists of:
 | 
						|
        float time;
 | 
						|
        byte isSet;
 | 
						|
 | 
						|
      If you implement this, make sure you use a packed struct
 | 
						|
      (sizeof==5), or read each element individually.
 | 
						|
     */
 | 
						|
    nif->skip(count*5);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiSkinInstance : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  NiSkinDataPtr data;
 | 
						|
  NodePtr root;
 | 
						|
  NodeList bones;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    data.read(nif);
 | 
						|
    root.read(nif);
 | 
						|
    bones.read(nif);
 | 
						|
 | 
						|
    if(data.empty() || root.empty())
 | 
						|
      nif->fail("NiSkinInstance missing root or data");
 | 
						|
  }
 | 
						|
 | 
						|
  void post(NIFFile *nif);
 | 
						|
};
 | 
						|
 | 
						|
class NiSkinData : public Record
 | 
						|
{
 | 
						|
public:
 | 
						|
  // This is to make sure the structs are packed, ie. that the
 | 
						|
  // compiler doesn't mess them up with extra alignment bytes.
 | 
						|
#pragma pack(push)
 | 
						|
#pragma pack(1)
 | 
						|
 | 
						|
  struct BoneTrafo
 | 
						|
  {
 | 
						|
    Matrix rotation; // Rotation offset from bone?
 | 
						|
    Vector trans;    // Translation
 | 
						|
    float scale;     // Probably scale (always 1)
 | 
						|
  };
 | 
						|
  struct BoneTrafoCopy
 | 
						|
  {
 | 
						|
	  Ogre::Quaternion rotation;
 | 
						|
	  Ogre::Vector3 trans;
 | 
						|
	  float scale;
 | 
						|
  };
 | 
						|
 | 
						|
  struct VertWeight
 | 
						|
  {
 | 
						|
    short vertex;
 | 
						|
    float weight;
 | 
						|
  };
 | 
						|
#pragma pack(pop)
 | 
						|
 | 
						|
  struct BoneInfo
 | 
						|
  {
 | 
						|
    const BoneTrafo *trafo;
 | 
						|
    const Vector4 *unknown;
 | 
						|
    Misc::SliceArray<VertWeight> weights;
 | 
						|
  };
 | 
						|
  struct BoneInfoCopy
 | 
						|
  {
 | 
						|
	   std::string bonename;
 | 
						|
       unsigned short bonehandle;
 | 
						|
	   BoneTrafoCopy trafo;
 | 
						|
	   Vector4 unknown;
 | 
						|
       //std::vector<VertWeight> weights;
 | 
						|
  };
 | 
						|
  struct IndividualWeight
 | 
						|
  {
 | 
						|
      float weight;
 | 
						|
        unsigned int boneinfocopyindex;
 | 
						|
  };
 | 
						|
 | 
						|
  const BoneTrafo *trafo;
 | 
						|
  std::vector<BoneInfo> bones;
 | 
						|
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    assert(sizeof(BoneTrafo) == 4*(9+3+1));
 | 
						|
    assert(sizeof(VertWeight) == 6);
 | 
						|
 | 
						|
    trafo = nif->getPtr<BoneTrafo>();
 | 
						|
 | 
						|
    int boneNum = nif->getInt();
 | 
						|
    nif->getInt(); // -1
 | 
						|
 | 
						|
    bones.resize(boneNum);
 | 
						|
 | 
						|
    for(int i=0;i<boneNum;i++)
 | 
						|
      {
 | 
						|
        BoneInfo &bi = bones[i];
 | 
						|
 | 
						|
        bi.trafo = nif->getPtr<BoneTrafo>();
 | 
						|
        bi.unknown = nif->getVector4();
 | 
						|
 | 
						|
        // Number of vertex weights
 | 
						|
        int count = nif->getShort();
 | 
						|
        bi.weights = nif->getArrayLen<VertWeight>(count);
 | 
						|
      }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
class NiMorphData : public Record
 | 
						|
{
 | 
						|
	float startTime;
 | 
						|
	float stopTime;
 | 
						|
	std::vector<Ogre::Vector3> initialVertices;
 | 
						|
	std::vector<std::vector<float> > relevantTimes;
 | 
						|
	std::vector<std::vector<Ogre::Vector3> > relevantData;
 | 
						|
	std::vector<std::vector<Ogre::Vector3> > additionalVertices;
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
	  float getStartTime(){
 | 
						|
	     return startTime;
 | 
						|
	  }
 | 
						|
	  float getStopTime(){
 | 
						|
	      return stopTime;
 | 
						|
	  }
 | 
						|
	  void setStartTime(float time){
 | 
						|
			startTime = time;
 | 
						|
	  }
 | 
						|
 | 
						|
	  void setStopTime(float time){
 | 
						|
			stopTime = time;
 | 
						|
	  }
 | 
						|
	  std::vector<Ogre::Vector3> getInitialVertices(){
 | 
						|
			return initialVertices;
 | 
						|
	  }
 | 
						|
	  std::vector<std::vector<Ogre::Vector3> > getRelevantData(){
 | 
						|
			return relevantData;
 | 
						|
	  }
 | 
						|
	  std::vector<std::vector<float> > getRelevantTimes(){
 | 
						|
			return relevantTimes;
 | 
						|
	  }
 | 
						|
	   std::vector<std::vector<Ogre::Vector3> > getAdditionalVertices(){
 | 
						|
			return additionalVertices;
 | 
						|
	  }
 | 
						|
 | 
						|
void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    int morphCount = nif->getInt();
 | 
						|
    int vertCount  = nif->getInt();
 | 
						|
    nif->getByte();
 | 
						|
	int magic = nif->getInt();
 | 
						|
	/*int type =*/ nif->getInt();
 | 
						|
	for(int i = 0; i < vertCount; i++){
 | 
						|
 | 
						|
		float x = nif->getFloat();
 | 
						|
		float y = nif->getFloat();
 | 
						|
		float z = nif->getFloat();
 | 
						|
		initialVertices.push_back(Ogre::Vector3(x, y, z));
 | 
						|
	}
 | 
						|
 | 
						|
    for(int i=1; i<morphCount; i++)
 | 
						|
    {
 | 
						|
        magic = nif->getInt();
 | 
						|
        /*type =*/ nif->getInt();
 | 
						|
		std::vector<Ogre::Vector3> current;
 | 
						|
		std::vector<float> currentTime;
 | 
						|
        for(int i = 0; i < magic; i++){
 | 
						|
        // Time, data, forward, backward tangents
 | 
						|
	        float time = nif->getFloat();
 | 
						|
		    float x = nif->getFloat();
 | 
						|
		    float y = nif->getFloat();
 | 
						|
		    float z = nif->getFloat();
 | 
						|
		    current.push_back(Ogre::Vector3(x,y,z));
 | 
						|
		    currentTime.push_back(time);
 | 
						|
          //nif->getFloatLen(4*magic);
 | 
						|
		}
 | 
						|
		if(magic){
 | 
						|
			relevantData.push_back(current);
 | 
						|
			relevantTimes.push_back(currentTime);
 | 
						|
		}
 | 
						|
		std::vector<Ogre::Vector3> verts;
 | 
						|
        for(int i = 0; i < vertCount; i++){
 | 
						|
		    float x = nif->getFloat();
 | 
						|
		    float y = nif->getFloat();
 | 
						|
		    float z = nif->getFloat();
 | 
						|
		    verts.push_back(Ogre::Vector3(x, y, z));
 | 
						|
		}
 | 
						|
		additionalVertices.push_back(verts);
 | 
						|
      }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class NiKeyframeData : public Record
 | 
						|
{
 | 
						|
	std::string bonename;
 | 
						|
	//Rotations
 | 
						|
	std::vector<Ogre::Quaternion> quats;
 | 
						|
	std::vector<Ogre::Vector3> tbc;
 | 
						|
	std::vector<float> rottime;
 | 
						|
	float startTime;
 | 
						|
	float stopTime;
 | 
						|
	int rtype;
 | 
						|
 | 
						|
	//Translations
 | 
						|
	std::vector<Ogre::Vector3> translist1;
 | 
						|
	std::vector<Ogre::Vector3> translist2;
 | 
						|
	std::vector<Ogre::Vector3> translist3;
 | 
						|
	std::vector<Ogre::Vector3> transtbc;
 | 
						|
	std::vector<float> transtime;
 | 
						|
	int ttype;
 | 
						|
 | 
						|
	//Scalings
 | 
						|
 | 
						|
	std::vector<float> scalefactor;
 | 
						|
	std::vector<float> scaletime;
 | 
						|
	std::vector<float> forwards;
 | 
						|
	std::vector<float> backwards;
 | 
						|
	std::vector<Ogre::Vector3> tbcscale;
 | 
						|
	int stype;
 | 
						|
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
	void clone(NiKeyframeData c)
 | 
						|
	{
 | 
						|
		quats = c.getQuat();
 | 
						|
		tbc = c.getrTbc();
 | 
						|
		rottime = c.getrTime();
 | 
						|
 | 
						|
		//types
 | 
						|
		ttype = c.getTtype();
 | 
						|
		rtype = c.getRtype();
 | 
						|
		stype = c.getStype();
 | 
						|
 | 
						|
 | 
						|
		translist1 = c.getTranslist1();
 | 
						|
		translist2 =	c.getTranslist2();
 | 
						|
        translist3 = c.getTranslist3();
 | 
						|
 | 
						|
	    transtime = c.gettTime();
 | 
						|
 | 
						|
	    bonename = c.getBonename();
 | 
						|
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	void setBonename(std::string bone)
 | 
						|
	{
 | 
						|
		bonename = bone;
 | 
						|
	}
 | 
						|
	void setStartTime(float start)
 | 
						|
	{
 | 
						|
		startTime = start;
 | 
						|
	}
 | 
						|
  	void setStopTime(float end)
 | 
						|
	{
 | 
						|
		stopTime = end;
 | 
						|
	}
 | 
						|
  void read(NIFFile *nif)
 | 
						|
  {
 | 
						|
    // Rotations first
 | 
						|
    int count = nif->getInt();
 | 
						|
	//std::vector<Ogre::Quaternion> quat(count);
 | 
						|
	//std::vector<float> rottime(count);
 | 
						|
    if(count)
 | 
						|
      {
 | 
						|
 | 
						|
		//TYPE1  LINEAR_KEY
 | 
						|
		//TYPE2  QUADRATIC_KEY
 | 
						|
		//TYPE3  TBC_KEY
 | 
						|
		//TYPE4  XYZ_ROTATION_KEY
 | 
						|
		//TYPE5  UNKNOWN_KEY
 | 
						|
        rtype = nif->getInt();
 | 
						|
		    //std::cout << "Count: " << count << "Type: " << type << "\n";
 | 
						|
 | 
						|
        if(rtype == 1)
 | 
						|
		{
 | 
						|
			//We need to actually read in these values instead of skipping them
 | 
						|
			//nif->skip(count*4*5); // time + quaternion
 | 
						|
			for (int i = 0; i < count; i++) {
 | 
						|
			    float time = nif->getFloat();
 | 
						|
			    float w = nif->getFloat();
 | 
						|
			    float x = nif->getFloat();
 | 
						|
			    float y = nif->getFloat();
 | 
						|
			    float z = nif->getFloat();
 | 
						|
				Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
 | 
						|
				quats.push_back(quat);
 | 
						|
				rottime.push_back(time);
 | 
						|
				//if(time == 0.0 || time > 355.5)
 | 
						|
					// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
 | 
						|
			}
 | 
						|
		}
 | 
						|
        else if(rtype == 3)
 | 
						|
		{                  //Example - node 116 in base_anim.nif
 | 
						|
			for (int i = 0; i < count; i++) {
 | 
						|
			    float time = nif->getFloat();
 | 
						|
			    float w = nif->getFloat();
 | 
						|
			    float x = nif->getFloat();
 | 
						|
			    float y = nif->getFloat();
 | 
						|
			    float z = nif->getFloat();
 | 
						|
 | 
						|
				float tbcx = nif->getFloat();
 | 
						|
				float tbcy = nif->getFloat();
 | 
						|
				float tbcz = nif->getFloat();
 | 
						|
				Ogre::Quaternion quat = Ogre::Quaternion(Ogre::Real(w), Ogre::Real(x), Ogre::Real(y), Ogre::Real(z));
 | 
						|
				Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
 | 
						|
				quats.push_back(quat);
 | 
						|
				rottime.push_back(time);
 | 
						|
				tbc.push_back(vec);
 | 
						|
				//if(time == 0.0 || time > 355.5)
 | 
						|
					// std::cout <<"Time:" << time << "W:" << w <<"X:" << x << "Y:" << y << "Z:" << z << "\n";
 | 
						|
			}
 | 
						|
 | 
						|
          //nif->skip(count*4*8); // rot1 + tension+bias+continuity
 | 
						|
		}
 | 
						|
        else if(rtype == 4)
 | 
						|
          {
 | 
						|
            for(int j=0;j<count;j++)
 | 
						|
              {
 | 
						|
                nif->getFloat(); // time
 | 
						|
                for(int i=0; i<3; i++)
 | 
						|
                  {
 | 
						|
                    int cnt = nif->getInt();
 | 
						|
                    int type = nif->getInt();
 | 
						|
                    if(type == 1)
 | 
						|
                      nif->skip(cnt*4*2); // time + unknown
 | 
						|
                    else if(type == 2)
 | 
						|
                      nif->skip(cnt*4*4); // time + unknown vector
 | 
						|
                    else nif->fail("Unknown sub-rotation type");
 | 
						|
                  }
 | 
						|
              }
 | 
						|
          }
 | 
						|
        else nif->fail("Unknown rotation type in NiKeyframeData");
 | 
						|
      }
 | 
						|
	//first = false;
 | 
						|
 | 
						|
    // Then translation
 | 
						|
    count = nif->getInt();
 | 
						|
 | 
						|
    if(count)
 | 
						|
      {
 | 
						|
       ttype = nif->getInt();
 | 
						|
 | 
						|
		//std::cout << "TransCount:" << count << " Type: " << type << "\n";
 | 
						|
        if(ttype == 1) {
 | 
						|
			for (int i = 0; i < count; i++) {
 | 
						|
				float time = nif->getFloat();
 | 
						|
				float x = nif->getFloat();
 | 
						|
				float y = nif->getFloat();
 | 
						|
				float z = nif->getFloat();
 | 
						|
				Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
 | 
						|
				translist1.push_back(trans);
 | 
						|
				transtime.push_back(time);
 | 
						|
			}
 | 
						|
			//nif->getFloatLen(count*4); // time + translation
 | 
						|
		}
 | 
						|
        else if(ttype == 2)
 | 
						|
		{                                        //Example - node 116 in base_anim.nif
 | 
						|
			for (int i = 0; i < count; i++) {
 | 
						|
				float time = nif->getFloat();
 | 
						|
				float x = nif->getFloat();
 | 
						|
				float y = nif->getFloat();
 | 
						|
				float z = nif->getFloat();
 | 
						|
				float x2 = nif->getFloat();
 | 
						|
				float y2 = nif->getFloat();
 | 
						|
				float z2 = nif->getFloat();
 | 
						|
				float x3 = nif->getFloat();
 | 
						|
				float y3 = nif->getFloat();
 | 
						|
				float z3 = nif->getFloat();
 | 
						|
				Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
 | 
						|
				Ogre::Vector3 trans2 = Ogre::Vector3(x2, y2, z2);
 | 
						|
				Ogre::Vector3 trans3 = Ogre::Vector3(x3, y3, z3);
 | 
						|
				transtime.push_back(time);
 | 
						|
				translist1.push_back(trans);
 | 
						|
				translist2.push_back(trans2);
 | 
						|
				translist3.push_back(trans3);
 | 
						|
			}
 | 
						|
 | 
						|
			//nif->getFloatLen(count*10); // trans1 + forward + backward
 | 
						|
		}
 | 
						|
        else if(ttype == 3){
 | 
						|
			for (int i = 0; i < count; i++) {
 | 
						|
				float time = nif->getFloat();
 | 
						|
				float x = nif->getFloat();
 | 
						|
				float y = nif->getFloat();
 | 
						|
				float z = nif->getFloat();
 | 
						|
				float t = nif->getFloat();
 | 
						|
				float b = nif->getFloat();
 | 
						|
				float c = nif->getFloat();
 | 
						|
				Ogre::Vector3 trans = Ogre::Vector3(x, y, z);
 | 
						|
				Ogre::Vector3 tbc = Ogre::Vector3(t, b, c);
 | 
						|
				translist1.push_back(trans);
 | 
						|
				transtbc.push_back(tbc);
 | 
						|
				transtime.push_back(time);
 | 
						|
			}
 | 
						|
          //nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
 | 
						|
		}
 | 
						|
        else nif->fail("Unknown translation type");
 | 
						|
      }
 | 
						|
 | 
						|
    // Finally, scalings
 | 
						|
    count = nif->getInt();
 | 
						|
    if(count)
 | 
						|
      {
 | 
						|
        stype = nif->getInt();
 | 
						|
 | 
						|
 | 
						|
		for(int i = 0; i < count; i++){
 | 
						|
 | 
						|
 | 
						|
        //int size = 0;
 | 
						|
        if(stype >= 1 && stype < 4)
 | 
						|
			{
 | 
						|
				float time = nif->getFloat();
 | 
						|
				float scale = nif->getFloat();
 | 
						|
				scaletime.push_back(time);
 | 
						|
				scalefactor.push_back(scale);
 | 
						|
				//size = 2; // time+scale
 | 
						|
			}
 | 
						|
		else nif->fail("Unknown scaling type");
 | 
						|
         if(stype == 2){
 | 
						|
			//size = 4; // 1 + forward + backward (floats)
 | 
						|
			float forward = nif->getFloat();
 | 
						|
			float backward = nif->getFloat();
 | 
						|
			forwards.push_back(forward);
 | 
						|
			backwards.push_back(backward);
 | 
						|
		}
 | 
						|
		else if(stype == 3){
 | 
						|
			float tbcx = nif->getFloat();
 | 
						|
			float tbcy = nif->getFloat();
 | 
						|
			float tbcz = nif->getFloat();
 | 
						|
			Ogre::Vector3 vec = Ogre::Vector3(tbcx, tbcy, tbcz);
 | 
						|
			tbcscale.push_back(vec);
 | 
						|
 | 
						|
			//size = 5; // 1 + tbc
 | 
						|
		}
 | 
						|
 | 
						|
		}
 | 
						|
      }
 | 
						|
	  else
 | 
						|
		  stype = 0;
 | 
						|
  }
 | 
						|
  	int getRtype(){
 | 
						|
		return rtype;
 | 
						|
	}
 | 
						|
	int getStype(){
 | 
						|
		return stype;
 | 
						|
	}
 | 
						|
	int getTtype(){
 | 
						|
		return ttype;
 | 
						|
	}
 | 
						|
	float getStartTime(){
 | 
						|
		return startTime;
 | 
						|
	}
 | 
						|
	float getStopTime(){
 | 
						|
		return stopTime;
 | 
						|
	}
 | 
						|
	std::vector<Ogre::Quaternion> getQuat(){
 | 
						|
		return quats;
 | 
						|
	}
 | 
						|
	std::vector<Ogre::Vector3> getrTbc(){
 | 
						|
		return tbc;
 | 
						|
	}
 | 
						|
	std::vector<float> getrTime(){
 | 
						|
		return rottime;
 | 
						|
	}
 | 
						|
 | 
						|
	std::vector<Ogre::Vector3> getTranslist1(){
 | 
						|
		return translist1;
 | 
						|
	}
 | 
						|
	std::vector<Ogre::Vector3> getTranslist2(){
 | 
						|
		return translist2;
 | 
						|
	}
 | 
						|
	std::vector<Ogre::Vector3> getTranslist3(){
 | 
						|
		return translist3;
 | 
						|
	}
 | 
						|
	std::vector<float> gettTime(){
 | 
						|
		return transtime;
 | 
						|
	}
 | 
						|
	std::vector<float> getScalefactor(){
 | 
						|
		return scalefactor;
 | 
						|
	}
 | 
						|
	std::vector<float> getForwards(){
 | 
						|
		return forwards;
 | 
						|
	}
 | 
						|
	std::vector<float> getBackwards(){
 | 
						|
		return backwards;
 | 
						|
	}
 | 
						|
	std::vector<Ogre::Vector3> getScaleTbc(){
 | 
						|
		return tbcscale;
 | 
						|
	}
 | 
						|
 | 
						|
	std::vector<float> getsTime(){
 | 
						|
		return scaletime;
 | 
						|
	}
 | 
						|
	std::string getBonename(){ return bonename;
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
} // Namespace
 | 
						|
#endif
 |