From 8e46bf6ba34d55cb17414ae8b6273a5b888bc45a Mon Sep 17 00:00:00 2001 From: Tazpn <tazpn@users.sourceforge.net> Date: Sat, 3 Jan 2009 09:57:08 +0000 Subject: [PATCH] niflib: fix bit unpack routine. Fix tangent space for fallout. --- include/NIF_IO.h | 2 +- include/obj/NiGeometryData.h | 40 +++++++++++++++- src/obj/BSShaderProperty.cpp | 2 +- src/obj/NiAVObject.cpp | 2 +- src/obj/NiGeometryData.cpp | 33 ++++++++++++++ src/obj/NiTriBasedGeom.cpp | 88 ++++++++++++++++++++---------------- 6 files changed, 122 insertions(+), 45 deletions(-) diff --git a/include/NIF_IO.h b/include/NIF_IO.h index 7593de2a..00cacd3a 100644 --- a/include/NIF_IO.h +++ b/include/NIF_IO.h @@ -74,7 +74,7 @@ storage UnpackField( storage src, size_t lshift, size_t num_bits ) { mask |= (1 << i); } - return (storage)(( src & mask) << lshift); + return (storage)(( src & mask) >> lshift); } template <class storage, class T> diff --git a/include/obj/NiGeometryData.h b/include/obj/NiGeometryData.h index 9dc5931f..4cab63ce 100644 --- a/include/obj/NiGeometryData.h +++ b/include/obj/NiGeometryData.h @@ -197,11 +197,47 @@ public: // Consistency Flags // \return The current value. - ConsistencyType GetConsistencyFlags() const; + NIFLIB_API ConsistencyType GetConsistencyFlags() const; // Consistency Flags // \param[in] value The new value. - void SetConsistencyFlags( const ConsistencyType & value ); + NIFLIB_API void SetConsistencyFlags( const ConsistencyType & value ); + + // Methods for saving binormals and tangents saved in upper byte. + // \return The current value. + NIFLIB_API byte GetTspaceFlag() const; + + // Methods for saving binormals and tangents saved in upper byte. + // \param[in] value The new value. + NIFLIB_API void SetTspaceFlag( byte value ); + + // Do we have lighting normals? These are essential for proper lighting: if not + // present, the model will only be influenced by ambient light. + // \return The current value. + NIFLIB_API bool GetHasNormals() const; + + // Do we have lighting normals? These are essential for proper lighting: if not + // present, the model will only be influenced by ambient light. + // \param[in] value The new value. + NIFLIB_API void SetHasNormals( bool value ); + + // Unknown. Binormal & tangents? has_normals must be set as well for this field to + // be present. + // \return The current value. + NIFLIB_API vector<Vector3 > GetBinormals() const; + + // Unknown. Binormal & tangents? has_normals must be set as well for this field to + // be present. + // \param[in] value The new value. + NIFLIB_API void SetBinormals( const vector<Vector3 >& value ); + + // Unknown. Binormal & tangents? + // \return The current value. + NIFLIB_API vector<Vector3 > GetTangents() const; + + // Unknown. Binormal & tangents? + // \param[in] value The new value. + NIFLIB_API void SetTangents( const vector<Vector3 >& value ); //--END CUSTOM CODE--// protected: diff --git a/src/obj/BSShaderProperty.cpp b/src/obj/BSShaderProperty.cpp index ee959202..4243ec6e 100644 --- a/src/obj/BSShaderProperty.cpp +++ b/src/obj/BSShaderProperty.cpp @@ -20,7 +20,7 @@ using namespace Niflib; //Definition of TYPE constant const Type BSShaderProperty::TYPE("BSShaderProperty", &NiProperty::TYPE ); -BSShaderProperty::BSShaderProperty() : flags((unsigned short)1), shaderType((BSShaderType)1), shaderFlags((BSShaderFlags)0x82000103), unknownInt2((int)1), envmapScale(1.0f) { +BSShaderProperty::BSShaderProperty() : flags((unsigned short)1), shaderType((BSShaderType)1), shaderFlags((BSShaderFlags)0x82000000), unknownInt2((int)1), envmapScale(1.0f) { //--BEGIN CONSTRUCTOR CUSTOM CODE--// //--END CUSTOM CODE--// diff --git a/src/obj/NiAVObject.cpp b/src/obj/NiAVObject.cpp index f9570d2e..bc9805c5 100644 --- a/src/obj/NiAVObject.cpp +++ b/src/obj/NiAVObject.cpp @@ -23,7 +23,7 @@ using namespace Niflib; //Definition of TYPE constant const Type NiAVObject::TYPE("NiAVObject", &NiObjectNET::TYPE ); -NiAVObject::NiAVObject() : flags((unsigned short)0), unknownShort1((unsigned short)0), scale(1.0f), numProperties((unsigned int)0), unknown2((byte)0), hasBoundingBox(false), collisionObject(NULL) { +NiAVObject::NiAVObject() : flags((unsigned short)0), unknownShort1((unsigned short)8), scale(1.0f), numProperties((unsigned int)0), unknown2((byte)0), hasBoundingBox(false), collisionObject(NULL) { //--BEGIN CONSTRUCTOR CUSTOM CODE--// parent = NULL; diff --git a/src/obj/NiGeometryData.cpp b/src/obj/NiGeometryData.cpp index b99c8f14..695773c8 100644 --- a/src/obj/NiGeometryData.cpp +++ b/src/obj/NiGeometryData.cpp @@ -565,4 +565,37 @@ void NiGeometryData::SetBound(Vector3 const & center, float radius) this->radius = radius; } + +byte NiGeometryData::GetTspaceFlag() const { + return tspaceFlag; +} + +void NiGeometryData::SetTspaceFlag( byte value ) { + tspaceFlag = value; +} + +bool NiGeometryData::GetHasNormals() const { + return hasNormals; +} + +void NiGeometryData::SetHasNormals( bool value ) { + hasNormals = value; +} + +vector<Vector3 > NiGeometryData::GetBinormals() const { + return binormals; +} + +void NiGeometryData::SetBinormals( const vector<Vector3 >& value ) { + binormals = value; +} + +vector<Vector3 > NiGeometryData::GetTangents() const { + return tangents; +} + +void NiGeometryData::SetTangents( const vector<Vector3 >& value ) { + tangents = value; +} + //--END CUSTOM CODE--// diff --git a/src/obj/NiTriBasedGeom.cpp b/src/obj/NiTriBasedGeom.cpp index 22bf3400..34081462 100644 --- a/src/obj/NiTriBasedGeom.cpp +++ b/src/obj/NiTriBasedGeom.cpp @@ -270,51 +270,59 @@ void NiTriBasedGeom::UpdateTangentSpace(int method) { } } - // generate the byte data - size_t vCount = verts.size(); - int fSize = sizeof(float[3]); - vector<byte> binData( 2 * vCount * fSize ); - - for( unsigned i = 0; i < verts.size(); i++ ) { - float tan_xyz[3], bin_xyz[3]; - - tan_xyz[0] = tangents[i].x; - tan_xyz[1] = tangents[i].y; - tan_xyz[2] = tangents[i].z; - - bin_xyz[0] = binormals[i].x; - bin_xyz[1] = binormals[i].y; - bin_xyz[2] = binormals[i].z; - - char * tan_Bytes = (char*)tan_xyz; - char * bin_Bytes = (char*)bin_xyz; - - for( int j = 0; j < fSize; j++ ) { - binData[ i * fSize + j] = tan_Bytes[j]; - binData[(i + vCount) * fSize + j] = bin_Bytes[j]; - } - } + if ( !niTriGeomData->GetHasNormals() && (niTriGeomData->GetTspaceFlag() & 0xF0) == 0 ) + { + // generate the byte data + size_t vCount = verts.size(); + int fSize = sizeof(float[3]); + vector<byte> binData( 2 * vCount * fSize ); + + for( unsigned i = 0; i < verts.size(); i++ ) { + float tan_xyz[3], bin_xyz[3]; + + tan_xyz[0] = tangents[i].x; + tan_xyz[1] = tangents[i].y; + tan_xyz[2] = tangents[i].z; + + bin_xyz[0] = binormals[i].x; + bin_xyz[1] = binormals[i].y; + bin_xyz[2] = binormals[i].z; + + char * tan_Bytes = (char*)tan_xyz; + char * bin_Bytes = (char*)bin_xyz; + + for( int j = 0; j < fSize; j++ ) { + binData[ i * fSize + j] = tan_Bytes[j]; + binData[(i + vCount) * fSize + j] = bin_Bytes[j]; + } + } - // update or create the tangent space extra data - NiBinaryExtraDataRef TSpaceRef; + // update or create the tangent space extra data + NiBinaryExtraDataRef TSpaceRef; - std::list<NiExtraDataRef> props = this->GetExtraData(); - std::list<NiExtraDataRef>::iterator prop; + std::list<NiExtraDataRef> props = this->GetExtraData(); + std::list<NiExtraDataRef>::iterator prop; - for( prop = props.begin(); prop != props.end(); ++prop ){ - if((*prop)->GetName() == "Tangent space (binormal & tangent vectors)") { - TSpaceRef = DynamicCast<NiBinaryExtraData>(*prop); - break; - } - } + for( prop = props.begin(); prop != props.end(); ++prop ){ + if((*prop)->GetName() == "Tangent space (binormal & tangent vectors)") { + TSpaceRef = DynamicCast<NiBinaryExtraData>(*prop); + break; + } + } - if( TSpaceRef == NULL ) { - TSpaceRef = new NiBinaryExtraData(); - TSpaceRef->SetName( "Tangent space (binormal & tangent vectors)" ); - this->AddExtraData( StaticCast<NiExtraData>(TSpaceRef) ); - } + if( TSpaceRef == NULL ) { + TSpaceRef = new NiBinaryExtraData(); + TSpaceRef->SetName( "Tangent space (binormal & tangent vectors)" ); + this->AddExtraData( StaticCast<NiExtraData>(TSpaceRef) ); + } - TSpaceRef->SetData(binData); + TSpaceRef->SetData(binData); + } + else + { + niTriGeomData->SetTangents(tangents); + niTriGeomData->SetBinormals(binormals); + } } //--END CUSTOM CODE--// -- GitLab