Skip to content
Snippets Groups Projects
Commit 48f34b7b authored by Shon Ferguson's avatar Shon Ferguson
Browse files

Created a new ComplexShape class which can currently be used to automatically...

Created a new ComplexShape class which can currently be used to automatically split the sort of complicated mesh that contains per-point-per-face attributes into NiTriShape classes.  Should support skinning as well, but has not been tested.
Added TexCoord == operator.
Changed type of Triangle members to unsigned short.
Color4 now defaults to all zeros.
NiAVObject::AddProperty now takes a const argument.
Fixed exception in NiTexturingProperty to throw a runtime_error instead of a string.
NiTriBasedGeom::BindSkin should now automatically finds the skeleton root by itself.  The skeleton_root argument has been removed.
parent 06146ba2
No related branches found
No related tags found
No related merge requests found
/* Copyright (c) 2006, NIF File Format Library and Tools
All rights reserved. Please see niflib.h for licence. */
#include "ComplexShape.h"
#include "obj/NiNode.h"
#include "obj/NiProperty.h"
#include "obj/NiAVObject.h"
#include "obj/NiTriShape.h"
#include "obj/NiTriShapeData.h"
#include "obj/NiTexturingProperty.h"
#include "obj/NiSkinInstance.h"
#include "obj/NiSkinData.h"
#include "gen/SkinWeight.h"
#include <stdlib.h>
using namespace Niflib;
struct CompoundVertex {
Vector3 position;
Vector3 normal;
Color4 color;
map<TexType, TexCoord> texCoords;
map<NiNodeRef, float> weights;
CompoundVertex() {}
~CompoundVertex() {}
CompoundVertex( const CompoundVertex & n ) {
*this = n;
}
CompoundVertex & operator=( const CompoundVertex & n ) {
position = n.position;
normal = n.normal;
color = n.color;
texCoords = n.texCoords;
weights = n.weights;
return *this;
}
bool operator==( const CompoundVertex & n ) {
if ( position != n.position ) {
return false;
}
if ( normal != n.normal ) {
return false;
}
if ( color.r != n.color.r && color.g != n.color.g && color.b != n.color.b && color.a != n.color.a ) {
return false;
}
if ( texCoords != n.texCoords ) {
return false;
}
if ( weights != n.weights ) {
return false;
}
return true;
}
};
void ComplexShape::SetName( const string & n ) {
name = n;
}
void ComplexShape::SetVertices( const vector<WeightedVertex> & n ) {
vertices = n;
}
void ComplexShape::SetColors( const vector<Color4> & n ) {
colors = n;
}
void ComplexShape::SetNormals( const vector<Vector3> & n ) {
normals = n;
}
void ComplexShape::SetTexCoordSets( const vector<TexCoordSet> & n ) {
texCoordSets = n;
}
void ComplexShape::SetFaces( const vector< ComplexFace > & n ) {
faces = n;
}
void ComplexShape::SetPropGroups( const vector< vector< Ref<NiProperty> > > & n ) {
propGroups = n;
}
void ComplexShape::SetSkinInfluences( const vector< Ref<NiNode> > & n ) {
skinInfluences = n;
}
string ComplexShape::GetName() const {
return name;
}
vector<ComplexShape::WeightedVertex> ComplexShape::GetVertices() const {
return vertices;
}
vector<Color4> ComplexShape::GetColors() const {
return colors;
}
vector<Vector3> ComplexShape::GetNormals() const {
return normals;
}
vector<ComplexShape::TexCoordSet> ComplexShape::GetTexCoordSets() const {
return texCoordSets;
}
vector< ComplexShape::ComplexFace > ComplexShape::GetFaces() const {
return faces;
}
vector< vector< Ref<NiProperty > > > ComplexShape::GetPropGroups() const {
return propGroups;
}
vector< Ref<NiNode> > ComplexShape::GetSkinInfluences() const {
return skinInfluences;
}
//void ComplexShape::CombineTriShapes( list<blk_ref> & tri_shapes ) {
// //Clear all internal datea
// _vertices.clear();
// _colors.clear();
// _normals.clear();
// _materials.clear();
// _uvs.clear();
// _faces.clear();
// _bones.clear();
//
// //Create a temporary spot to hold the triangle lists from each TriShape
// vector< vector<Triangle> > ts_faces;
//
// //Create lists to hold the lookup tables
// vector<int> tri_lookup, nor_lookup, col_lookup;
// map<string, vector<int> > mat_lookup, uv_lookup;
//
// //--Cycle through all the TriShapes, adding their data to the lists--//
// list<blk_ref>::iterator it;
//
// for (it = tri_shapes.begin(); it != tri_shapes.end(); ++it) {
// ITriShapeData * data = QueryTriShapeData(*it);
//
// //Vertices
// vector<Vector3> ts_verts = data->GetVertices();
// _vertices.insert(_vertices.end(), ts_verts.begin(), ts_verts.end();
//
// //Normals
// vector<Vector3> ts_norms = data->GetNormals();
// _normals.insert(_normals.end(), ts_norms.begin(), ts_norms.end();
//
// //Colors
// vector<Colors> ts_cols = data->GetColors();
// _colors.insert(_colors.end(), ts_colors.begin(), ts_colors.end();
//
// //Triangles
// ts_faces[i] = data->GetTriangles();
//
// //UV Coords
// vector< vector<TexCoords> > uvs(data->GetUVSetCount());
// for (int i = 0; i < data->GetUVSetCount(); ++i) {
// uvs[i] = data->GetUVSet(i);
// }
//
// //Associate UV Coord Data with proper map name
// blk_ref tx_prop = par["Properties"]->FindLink( "NiTexturingProperty");
// if ( tx_prop.is_null() == false ) {
// int uv_set = 0;
// for (int i = 0; i < 7; ++i) {
// string attr_name, map;
// switch(i) {
// case 0: attr_name = "Base Texture"; map = "map1"; break;
// case 1: attr_name = "Dark Texture"; map = "dark"; break;
// case 2: attr_name = "Detail Texture"; map = "detail"; break;
// case 3: attr_name = "Gloss Texture"; map = "gloss"; break;
// case 4: attr_name = "Glow Texture"; map = "glow"; break;
// case 5: attr_name = "Bump Map Texture"; map = "bump"; break;
// case 6: attr_name = "Decal 0 Texture"; map = "decal0";
// }
//
// if ( tx_prop[attr_name]->asTexDesc().isUsed == true ) {
// //How to merge all UVs?
// }
//
// }
//
//
// //blk_ref material = (*it)->GetAttr("Propreties")->FindLink("NiMaterialProperty");
// //blk_ref skin_inst = (*it)->GetAttr("Skin Instance")->asLink();
// //blk_ref skin_data;
// //vector<blk_ref> bones;
// //map<int, float> weights;
// //if ( skin_inst.is_null() == false ) {
// // skin_block = skin_inst->GetAttr("Data");
// // if (skin_block.is_null() == false ) {
// // ISkinData * skin_data = QuerySkinData(skin_block);
// // weights = skin_data->GetWeights();
// // bones = skin_data->GetBones();
// // }
// //}
//
// }
//}
Ref<NiAVObject> ComplexShape::Split( Ref<NiNode> & parent ) const {
//Make sure parent is not NULL
if ( parent == NULL ) {
throw runtime_error ("A parent is necessary to split a complex shape.");
}
//There will be one NiTriShape per property group
//with a minimum of 1
unsigned int num_shapes = unsigned int(propGroups.size());
if ( num_shapes == 0 ) {
num_shapes = 1;
}
vector<NiTriShapeRef> shapes(num_shapes);
//Loop through each shape slot and create a NiTriShape
for ( unsigned int shape_num = 0; shape_num < shapes.size(); ++shape_num ) {
shapes[shape_num] = new NiTriShape;
}
NiAVObjectRef root;
//If there is just one shape, return it. Otherwise
//create a node, parent all shapes to it, and return
// that
if ( shapes.size() == 1 ) {
//One shape
shapes[0]->SetName(name);
root = StaticCast<NiAVObject>(shapes[0]);
} else {
//Multiple shapes
NiNodeRef niNode = new NiNode;
niNode->SetName(name);
for ( unsigned int i = 0; i < shapes.size(); ++i ) {
niNode->AddChild( StaticCast<NiAVObject>(shapes[i]) );
//Set Shape Name
stringstream shapeName;
shapeName << name << " " << i;
shapes[i]->SetName( shapeName.str() );
}
root = StaticCast<NiAVObject>(niNode);
}
parent->AddChild( root );
//Create NiTriShapeData and fill it out with all data that is relevant
//to this shape based on the material.
for ( unsigned int shape_num = 0; shape_num < shapes.size(); ++shape_num ) {
NiTriShapeDataRef niData = new NiTriShapeData;
shapes[shape_num]->SetData( StaticCast<NiTriBasedGeomData>(niData) );
//Create a list of CompoundVertex to make it easier to
//test for the need to clone a vertex
vector<CompoundVertex> compVerts;
//List of triangles for the final shape to use
vector<Triangle> shapeTriangles;
//Loop through all faces, and all points on each face
//to set the vertices in the CompoundVertex list
for ( vector<ComplexFace>::const_iterator face = faces.begin(); face != faces.end(); ++face ) {
//Ignore faces with less than 3 vertices
if ( face->points.size() < 3 ) {
continue;
}
//Skip this face if the material does not relate to this shape
if ( face->propGroupIndex != shape_num ) {
continue;
}
vector<unsigned short> shapeFacePoints;
for ( vector<ComplexPoint>::const_iterator point = face->points.begin(); point != face->points.end(); ++point ) {
//--Set up Compound vertex--//
CompoundVertex cv;
if ( vertices.size() > 0 ) {
const WeightedVertex & wv = vertices[point->vertexIndex];
cv.position = wv.position;
if ( skinInfluences.size() > 0 ) {
for ( unsigned int i = 0; i < wv.weights.size(); ++i ) {
const SkinInfluence & inf = wv.weights[i];
cv.weights[ skinInfluences[inf.influenceIndex] ] = inf.weight;
}
}
}
if ( normals.size() > 0 ) {
cv.normal = normals[point->normalIndex];
}
if ( colors.size() > 0 ) {
cv.color = colors[point->colorIndex];
}
if ( texCoordSets.size() > 0 ) {
for ( unsigned int i = 0; i < point->texCoordIndices.size(); ++i ) {
const TexCoordSet & set = texCoordSets[ point->texCoordIndices[i].texCoordSetIndex ];
cv.texCoords[ set.texType ] = set.texCoords[ point->texCoordIndices[i].texCoordIndex ];
}
}
bool found_match = false;
//Search for an identical vertex in the list
for ( unsigned short cv_index = 0; cv_index < compVerts.size(); ++cv_index ) {
if ( compVerts[cv_index] == cv ) {
//We found a match, push its index into the face list
found_match = true;
shapeFacePoints.push_back(cv_index);
break;
}
}
//If no match was found, append this vertex to the list
if ( found_match == false ) {
compVerts.push_back(cv);
//put the new vertex into the face point list
shapeFacePoints.push_back( unsigned int(compVerts.size()) - 1 );
}
//Next Point
}
//Starting from vertex 0, create a fan of triangles to fill
//in non-triangle polygons
Triangle new_face;
for ( unsigned int i = 0; i < shapeFacePoints.size() - 2; ++i ) {
new_face[0] = shapeFacePoints[0];
new_face[1] = shapeFacePoints[i+1];
new_face[2] = shapeFacePoints[i+2];
//Push the face into the face list
shapeTriangles.push_back(new_face);
}
//Next Face
}
//Attatch properties if any
if ( propGroups.size() > 0 ) {
for ( vector<NiPropertyRef>::const_iterator prop = propGroups[shape_num].begin(); prop != propGroups[shape_num].end(); ++prop ) {
shapes[shape_num]->AddProperty( *prop );
}
}
//--Set Shape Data--//
//lists to hold data
vector<Vector3> shapeVerts( compVerts.size() );
vector<Vector3> shapeNorms( compVerts.size() );
vector<Color4> shapeColors( compVerts.size() );
vector< vector<TexCoord> > shapeTCs;
list<int> shapeTexCoordSets;
map<NiNodeRef, vector<SkinWeight> > shapeWeights;
//Search for a NiTexturingProperty to build list of
//texture cooridinate sets to create
NiPropertyRef niProp = shapes[shape_num]->GetPropertyByType( NiTexturingProperty::TypeConst() );
NiTexturingPropertyRef niTexProp;
if ( niProp != NULL ) {
niTexProp = DynamicCast<NiTexturingProperty>(niProp);
}
if ( niTexProp != NULL ) {
for ( int tex_num = 0; tex_num < 8; ++tex_num ) {
if (niTexProp->HasTexture(tex_num)) {
shapeTexCoordSets.push_back(tex_num);
}
}
} else {
//Always include the base map if it's there, whether there's a
//texture or not
shapeTexCoordSets.push_back( BASE_MAP );
}
shapeTCs.resize( shapeTexCoordSets.size() );
for ( vector< vector<TexCoord> >::iterator set = shapeTCs.begin(); set != shapeTCs.end(); ++set ) {
set->resize( compVerts.size() );
}
//Loop through all compound vertices, adding the data
//to the correct arrays.
uint vert_index = 0;
for ( vector<CompoundVertex>::iterator cv = compVerts.begin(); cv != compVerts.end(); ++cv ) {
shapeVerts[vert_index] = cv->position;
shapeColors[vert_index] = cv->color;
shapeNorms[vert_index] = cv->normal;
shapeNorms[vert_index] = cv->normal;
uint tex_index = 0;
for ( list<int>::iterator tex = shapeTexCoordSets.begin(); tex != shapeTexCoordSets.end(); ++tex ) {
if ( cv->texCoords.find( TexType(*tex) ) != cv->texCoords.end() ) {
shapeTCs[tex_index][vert_index] = cv->texCoords[ TexType(*tex) ];
}
tex_index++;
}
SkinWeight sk;
for ( map<NiNodeRef, float>::iterator wt = cv->weights.begin(); wt != cv->weights.end(); ++wt ) {
//Only record influences that make a noticable contribution
if ( wt->second > 0.001f ) {
sk.index = vert_index;
sk.weight = wt->second;
shapeWeights[wt->first].push_back( sk );
}
}
++vert_index;
}
//Finally, set the data into the NiTriShapeData
if ( vertices.size() > 0 ) {
niData->SetVertices( shapeVerts );
niData->SetTriangles( shapeTriangles );
}
if ( normals.size() > 0 ) {
niData->SetNormals( shapeNorms );
}
if ( colors.size() > 0 ) {
niData->SetVertexColors( shapeColors );
}
if ( texCoordSets.size() > 0 ) {
niData->SetUVSetCount( int(shapeTCs.size()) );
for ( unsigned int tex_index = 0; tex_index < shapeTCs.size(); ++tex_index ) {
niData->SetUVSet( tex_index, shapeTCs[tex_index] );
}
}
//If there are any skin influences, bind the skin
if ( shapeWeights.size() > 0 ) {
vector<NiNodeRef> shapeInfluences;
for ( map<NiNodeRef, vector<SkinWeight> >::iterator inf = shapeWeights.begin(); inf != shapeWeights.end(); ++inf ) {
shapeInfluences.push_back( inf->first );
}
shapes[shape_num]->BindSkin( shapeInfluences );
NiSkinDataRef skinData = shapes[shape_num]->GetSkinInstance()->GetSkinData();
for ( unsigned int inf = 0; inf < shapeInfluences.size(); ++inf ) {
skinData->SetBoneWeights( inf, shapeWeights[ shapeInfluences[inf] ] );
}
}
//Next Shape
}
return root;
}
\ No newline at end of file
/* Copyright (c) 2006, NIF File Format Library and Tools
All rights reserved. Please see niflib.h for licence. */
#ifndef _COMPLEX_SHAPE_H_
#define _COMPLEX_SHAPE_H_
#include "Ref.h"
#include "nif_math.h"
#include "nif_basic_types.h"
namespace Niflib {
// Forward define of referenced classes
class NiProperty;
class NiNode;
class NiAVObject;
class ComplexShape {
public:
struct SkinInfluence {
unsigned int influenceIndex;
float weight;
};
struct WeightedVertex {
Vector3 position;
vector<SkinInfluence> weights;
};
struct TexCoordIndex {
unsigned int texCoordSetIndex;
unsigned int texCoordIndex;
};
struct ComplexPoint {
unsigned int vertexIndex;
unsigned int normalIndex;
unsigned int colorIndex;
vector<TexCoordIndex> texCoordIndices;
};
struct ComplexFace {
vector<ComplexPoint> points;
unsigned int propGroupIndex;
};
struct TexCoordSet {
TexType texType;
vector<TexCoord> texCoords;
};
Ref<NiAVObject> Split( Ref<NiNode> & parent ) const;
//Setters
void SetName( const string & n );
void SetVertices( const vector<WeightedVertex> & n );
void SetColors( const vector<Color4> & n );
void SetNormals( const vector<Vector3> & n );
void SetTexCoordSets( const vector<TexCoordSet> & n );
void SetFaces( const vector<ComplexFace> & n );
void SetPropGroups( const vector< vector< Ref<NiProperty> > > & n );
void SetSkinInfluences( const vector< Ref<NiNode> > & n );
//Getters
string GetName() const;
vector<WeightedVertex> GetVertices() const;
vector<Color4> GetColors() const;
vector<Vector3> GetNormals() const;
vector<TexCoordSet> GetTexCoordSets() const;
vector<ComplexFace> GetFaces() const;
vector< vector< Ref<NiProperty> > > GetPropGroups() const;
vector< Ref<NiNode> > GetSkinInfluences() const;
private:
vector<WeightedVertex> vertices;
vector<Color4> colors;
vector<Vector3> normals;
vector<TexCoordSet> texCoordSets;
vector<ComplexFace> faces;
vector< vector< Ref<NiProperty> > > propGroups;
vector< Ref<NiNode> > skinInfluences;
string name;
};
}
#endif
\ No newline at end of file
......@@ -19,6 +19,15 @@ const Matrix33 Matrix33::IDENTITY( 1.0f, 0.0f, 0.0f,
const Matrix22 Matrix22::IDENTITY( 1.0f, 0.0f,
0.0f, 1.0f );
/* TexCoord Methods
*
*/
bool TexCoord::operator==( const TexCoord & n ) const {
return ( u == n.u && v == n.v );
}
/*
* Vector3 Methods
*/
......
......@@ -55,13 +55,15 @@ struct NIFLIB_API TexCoord {
this->u = u;
this->v = v;
}
bool operator==( const TexCoord & n ) const;
};
/*! Represents a triangle face formed between three vertices referenced by number */
struct NIFLIB_API Triangle {
short v1; /*!< The index of the first vertex. */
short v2; /*!< The index of the second vertex. */
short v3; /*!< The index of the third vertex. */
unsigned short v1; /*!< The index of the first vertex. */
unsigned short v2; /*!< The index of the second vertex. */
unsigned short v3; /*!< The index of the third vertex. */
/*! Default constructor */
Triangle() {}
......@@ -71,7 +73,7 @@ struct NIFLIB_API Triangle {
* \param v2 The index of the second vertex.
* \param v3 The index of the third vertex.
*/
Triangle(short v1, short v2, short v3) {
Triangle(unsigned short v1, unsigned short v2, unsigned short v3) {
this->v1 = v1;
this->v2 = v2;
this->v3 = v3;
......@@ -82,7 +84,7 @@ struct NIFLIB_API Triangle {
* \param v2 The index of the second vertex.
* \param v3 The index of the third vertex.
*/
void Set(short v1, short v2, short v3) {
void Set(unsigned short v1, unsigned short v2, unsigned short v3) {
this->v1 = v1;
this->v2 = v2;
this->v3 = v3;
......@@ -94,7 +96,7 @@ struct NIFLIB_API Triangle {
* \param n The index into the data array. Should be 0, 1, or 2.
* \return The value at the given array index by reference so it can be read or set via the bracket operator.
*/
short & operator[](int n) {
unsigned short & operator[](int n) {
switch (n) {
case 0: return v1; break;
case 1: return v2; break;
......@@ -102,7 +104,7 @@ struct NIFLIB_API Triangle {
default: throw std::out_of_range("Index out of range for Triangle");
};
}
short operator[](int n) const {
unsigned short operator[](int n) const {
switch (n) {
case 0: return v1; break;
case 1: return v2; break;
......@@ -827,7 +829,7 @@ struct NIFLIB_API Color4 {
float a; /*!< The alpha translucency component of this color. Should be between 0.0f and 1.0f. */
/*! Default constructor */
Color4() {}
Color4() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
/*! This constructor can be used to set all values in this structure during initialization
* \param r The value to set the red component of this color to. Should be between 0.0f and 1.0f.
......
......@@ -270,131 +270,6 @@ NIFLIB_API bool IsVersionSupported(unsigned int ver);
*/
NIFLIB_API unsigned int GetVersion(string version);
//TODO: This is planned functionality but is unfinished
//struct ComplexVertex {
// ComplexVertex() : has_color(false), has_normal(false), vertex_index(0), normal_index(0), color_index(0) {}
// ~ComplexVertex();
// bool has_color, has_normal;
// int vertex_index, color_index, normal_index;
// bool has_base_uv, has_glow_uv;
// int base_uv_index, glow_uv_index;
//}
//
//struct ComplexFace {
// vector<ComplexVertex> points;
// int base_map_index;
// int glow_map_index;
//};
//
//class ComplexShape {
// void SetVertices( vector<Vector3> & vertices );
// void SetUVs( vector<TexCoord> & uvs );
// void SetColors( vector<Color4> & colors );
// void SetNormals( vector<Vector3> & normals );
// void SetBones( vector<blk_ref> & bones );
// void SetFaces( list< vector< ComplexVertex > > & faces );
//
// vector<Vector3> GetVertices();
// vector<TexCoord> GetUVs();
// vector<Color4> GetColors();
// vector<Vector3> GetNormals();
// vector<blk_ref> GetBones();
// list< vector< ComplexVertex > > GetFaces();
//
//private:
// vector<Vector3> _vertices;
// vector<Color4> _colors;
// vector<Vector3> _normals;
// list<ComplexFace> _faces;
// map<string, blk_ref> _materials;
// map<string, vector<TexCoord> > _uvs;
// map<blk_ref, map<int, float> > _bones;
//};
//
//void ComplexShape::CombineTriShapes( list<blk_ref> & tri_shapes ) {
// //Clear all internal datea
// _vertices.clear();
// _colors.clear();
// _normals.clear();
// _materials.clear();
// _uvs.clear();
// _faces.clear();
// _bones.clear();
//
// //Create a temporary spot to hold the triangle lists from each TriShape
// vector< vector<Triangle> > ts_faces;
//
// //Create lists to hold the lookup tables
// vector<int> tri_lookup, nor_lookup, col_lookup;
// map<string, vector<int> > mat_lookup, uv_lookup;
//
// //--Cycle through all the TriShapes, adding their data to the lists--//
// list<blk_ref>::iterator it;
//
// for (it = tri_shapes.begin(); it != tri_shapes.end(); ++it) {
// ITriShapeData * data = QueryTriShapeData(*it);
//
// //Vertices
// vector<Vector3> ts_verts = data->GetVertices();
// _vertices.insert(_vertices.end(), ts_verts.begin(), ts_verts.end();
//
// //Normals
// vector<Vector3> ts_norms = data->GetNormals();
// _normals.insert(_normals.end(), ts_norms.begin(), ts_norms.end();
//
// //Colors
// vector<Colors> ts_cols = data->GetColors();
// _colors.insert(_colors.end(), ts_colors.begin(), ts_colors.end();
//
// //Triangles
// ts_faces[i] = data->GetTriangles();
//
// //UV Coords
// vector< vector<TexCoords> > uvs(data->GetUVSetCount());
// for (int i = 0; i < data->GetUVSetCount(); ++i) {
// uvs[i] = data->GetUVSet(i);
// }
//
// //Associate UV Coord Data with proper map name
// blk_ref tx_prop = par["Properties"]->FindLink( "NiTexturingProperty");
// if ( tx_prop.is_null() == false ) {
// int uv_set = 0;
// for (int i = 0; i < 7; ++i) {
// string attr_name, map;
// switch(i) {
// case 0: attr_name = "Base Texture"; map = "map1"; break;
// case 1: attr_name = "Dark Texture"; map = "dark"; break;
// case 2: attr_name = "Detail Texture"; map = "detail"; break;
// case 3: attr_name = "Gloss Texture"; map = "gloss"; break;
// case 4: attr_name = "Glow Texture"; map = "glow"; break;
// case 5: attr_name = "Bump Map Texture"; map = "bump"; break;
// case 6: attr_name = "Decal 0 Texture"; map = "decal0";
// }
//
// if ( tx_prop[attr_name]->asTexDesc().isUsed == true ) {
// //How to merge all UVs?
// }
//
// }
//
//
// //blk_ref material = (*it)->GetAttr("Propreties")->FindLink("NiMaterialProperty");
// //blk_ref skin_inst = (*it)->GetAttr("Skin Instance")->asLink();
// //blk_ref skin_data;
// //vector<blk_ref> bones;
// //map<int, float> weights;
// //if ( skin_inst.is_null() == false ) {
// // skin_block = skin_inst->GetAttr("Data");
// // if (skin_block.is_null() == false ) {
// // ISkinData * skin_data = QuerySkinData(skin_block);
// // weights = skin_data->GetWeights();
// // bones = skin_data->GetBones();
// // }
// //}
//
// }
//}
//--USER GUIDE DOCUMENTATION--//
/*! \mainpage Niflib Documentation
......
......@@ -355,6 +355,10 @@
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\ComplexShape.cpp"
>
</File>
<File
RelativePath=".\kfm.cpp"
>
......@@ -1394,6 +1398,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\ComplexShape.h"
>
</File>
<File
RelativePath=".\dll_export.h"
>
......
......@@ -80,7 +80,7 @@ Ref<NiNode> NiAVObject::GetParent() const {
return parent;
}
void NiAVObject::AddProperty( Ref<NiProperty> & obj ) {
void NiAVObject::AddProperty( const Ref<NiProperty> & obj ) {
properties.push_back( obj );
}
......
......@@ -68,7 +68,7 @@ public:
Ref<NiNode> GetParent() const;
void AddProperty( Ref<NiProperty> & obj );
void AddProperty( const Ref<NiProperty> & obj );
void RemoveProperty( Ref<NiProperty> obj );
void ClearProperties();
vector< Ref<NiProperty> > GetProperties() const;
......
......@@ -222,7 +222,7 @@ bool NiTexturingProperty::HasTexture( int n ) const {
case DECAL_1_MAP:
return hasDecal1Texture;
default:
throw("You have specified an invalid texture type.");
throw runtime_error("You have specified an invalid texture type.");
};
}
......
......@@ -73,12 +73,31 @@ Ref<NiSkinInstance> NiTriBasedGeom::GetSkinInstance() const {
return skinInstance;
}
void NiTriBasedGeom::BindSkin( Ref<NiNode> skeleton_root, vector< Ref<NiNode> > bone_nodes ) {
void NiTriBasedGeom::BindSkin( vector< Ref<NiNode> > bone_nodes ) {
//Ensure skin is not aleady bound
if ( skinInstance != 0 ) {
throw runtime_error("You have attempted to re-bind a skin that is already bound. Unbind it first.");
}
//--Find a suitable skeleton root--//
//create a list of nodes that have an influence or this TriBasedGeom
//as decendents
list<NiAVObjectRef> ancestors;
NiAVObjectRef shape_tree_top = ListAncestors( StaticCast<NiAVObject>(this), ancestors );
NiAVObjectRef bone_tree_top;
for ( unsigned int i = 0; i < bone_nodes.size(); ++i ) {
bone_tree_top = ListAncestors( StaticCast<NiAVObject>(bone_nodes[i]), ancestors );
//Make sure bone and shapre are part of the same tree
if ( bone_tree_top != shape_tree_top ) {
throw runtime_error("Shape and all skin influence bones must be part of the same tree before skin bind can take place.");
}
}
NiNodeRef skeleton_root = FindFirstCommonAncestor( shape_tree_top, ancestors );
//Create a skin instance using the bone and root data
skinInstance = new NiSkinInstance( skeleton_root, bone_nodes );
......@@ -86,6 +105,38 @@ void NiTriBasedGeom::BindSkin( Ref<NiNode> skeleton_root, vector< Ref<NiNode> >
skinInstance->SetSkinData( new NiSkinData( this ) );
};
Ref<NiAVObject> NiTriBasedGeom::ListAncestors( const Ref<NiAVObject> & leaf, list< Ref<NiAVObject> > & ancestors ) const {
NiAVObjectRef avObj = leaf;
while ( avObj->GetParent() != NULL ) {
ancestors.push_back(avObj);
avObj = avObj->GetParent();
}
//Return top of tree
return avObj;
}
Ref<NiNode> NiTriBasedGeom::FindFirstCommonAncestor( const Ref<NiAVObject> & avObj, const list< Ref<NiAVObject> > & ancestors ) const {
//See if we've found the common ancestor yet
for ( list<NiAVObjectRef>::const_iterator ancestor = ancestors.begin(); ancestor != ancestors.end(); ++ancestor ) {
if ( *ancestor == avObj ) {
//We found the common ancestor, return it.
return DynamicCast<NiNode>(avObj);
}
}
//Call this function on any children
NiNodeRef niNode = DynamicCast<NiNode>(avObj);
if ( niNode != NULL ) {
vector<NiAVObjectRef> children = niNode->GetChildren();
for ( uint i = 0; i < children.size(); ++i ) {
return FindFirstCommonAncestor( children[i], ancestors );
}
} else {
return NULL;
}
}
void NiTriBasedGeom::UnbindSkin() {
//Clear skin instance
skinInstance = NULL;
......
......@@ -46,7 +46,7 @@ public:
* NiSkinInstance and NiSkinData class. The bones must have a common
* ancestor in the scenegraph. This becomes the skeleton root.
*/
void BindSkin( Ref<NiNode> skeleton_root, vector< Ref<NiNode> > bone_nodes );
void BindSkin( vector< Ref<NiNode> > bone_nodes );
void UnbindSkin();
Ref<NiSkinInstance> GetSkinInstance() const;
......@@ -62,6 +62,9 @@ public:
vector<Vector3> GetSkinInfluencedVertices() const;
protected:
Ref<NiAVObject> ListAncestors( const Ref<NiAVObject> & leaf, list< Ref<NiAVObject> > & ancestors ) const;
Ref<NiNode> FindFirstCommonAncestor( const Ref<NiAVObject> & avObj, const list< Ref<NiAVObject> > & ancestors ) const;
NI_TRI_BASED_GEOM_MEMBERS
STANDARD_INTERNAL_METHODS
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment