/*---------------------------------------------------------------------------*/ NiTriShapeRef NifConvertUtility::convertNiTriShape(NiTriShapeRef pSrcNode, NiTriShapeRef pTmplNode, NiAlphaPropertyRef pTmplAlphaProp) { BSLightingShaderPropertyRef pTmplLShader(NULL); BSLightingShaderPropertyRef pDstLShader (NULL); vector<NiPropertyRef> dstPropList; short bsPropIdx (0); bool forceAlpha (pTmplAlphaProp != NULL); bool hasAlpha (false); // NiTriShape is moved from src to dest. It's unlinked in calling function NiTriShapeRef pDstNode(pSrcNode); NiGeometryDataRef pDstGeo (pDstNode->GetData()); // force some data in destination shape pDstNode->SetCollisionObject(NULL); // no collision object here pDstNode->SetFlags (14); // ??? // data node if (pDstGeo != NULL) { // set flags if (pTmplNode->GetData() != NULL) { pDstGeo->SetConsistencyFlags(pTmplNode->GetData()->GetConsistencyFlags()); // nessessary ??? } // update tangent space? if ((_updateTangentSpace) && (DynamicCast<NiTriShapeData>(pDstGeo) != NULL)) { // update tangent space if (updateTangentSpace(DynamicCast<NiTriShapeData>(pDstGeo))) { // enable tangent space pDstGeo->SetTspaceFlag(0x10); } } // if (_updateTangentSpace) } // if (pDstGeo != NULL) // properties - get them from template for (short index(0); index < 2; ++index) { // BSLightingShaderProperty if (DynamicCast<BSLightingShaderProperty>(pTmplNode->GetBSProperty(index)) != NULL) { pTmplLShader = DynamicCast<BSLightingShaderProperty>(pTmplNode->GetBSProperty(index)); } // NiAlphaProperty else if (DynamicCast<NiAlphaProperty>(pTmplNode->GetBSProperty(index)) != NULL) { pTmplAlphaProp = DynamicCast<NiAlphaProperty>(pTmplNode->GetBSProperty(index)); } } // for (short index(0); index < 2; ++index) // parse properties of destination node dstPropList = pDstNode->GetProperties(); for (vector<NiPropertyRef>::iterator ppIter = dstPropList.begin(); ppIter != dstPropList.end(); ppIter++) { // NiAlphaProperty if (DynamicCast<NiAlphaProperty>(*ppIter) != NULL) { NiAlphaPropertyRef pPropAlpha(DynamicCast<NiAlphaProperty>(*ppIter)); // set values from template pPropAlpha->SetFlags (pTmplAlphaProp->GetFlags()); pPropAlpha->SetTestThreshold(pTmplAlphaProp->GetTestThreshold()); // remove property from node pDstNode->RemoveProperty(*ppIter); // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pPropAlpha)); // own alpha, reset forced alpha forceAlpha = false; // mark alpha property hasAlpha = true; } // NiTexturingProperty else if (DynamicCast<NiTexturingProperty>(*ppIter) != NULL) { char* pTextPos (NULL); BSShaderTextureSetRef pDstSText(new BSShaderTextureSet()); TexDesc baseTex ((DynamicCast<NiTexturingProperty>(*ppIter))->GetTexture(BASE_MAP)); char fileName[1000] = {0}; char textName[1000] = {0}; // clone shader property from template pDstLShader = cloneBSLightingShaderProperty(pTmplLShader); //pDstLShader = new BSLightingShaderProperty(); // copy textures from template to copy pDstSText->SetTextures(pTmplLShader->GetTextureSet()->GetTextures()); // set new texture names sprintf(fileName, "%s", (const char*) _pathTexture.c_str()); baseTex.source->GetTextureFileName().copy(textName, 1000, 0); pTextPos = strrchr(textName, '\\'); if (pTextPos == NULL) { pTextPos = strrchr(textName, '/'); } if (pTextPos != NULL) { strcat(fileName, ++pTextPos); } else { strcat(fileName, textName); } fileName[strlen(fileName) - 3] = 0; strcat(fileName, "dds"); // set new texture map pDstSText->SetTexture(0, fileName); logMessage(NCU_MSG_TYPE_TEXTURE, string("Txt-Used: ") + fileName); if (!checkFileExists(fileName)) { _newTextures.insert(string("Txt-Missed: ") + fileName); } fileName[strlen(fileName) - 4] = 0; strcat(fileName, "_n.dds"); // set new normal map pDstSText->SetTexture(1, fileName); if (!checkFileExists(fileName)) { _newTextures.insert(string("Txt-Missed: ") + fileName); } // add texture set to texture property pDstLShader->SetTextureSet(pDstSText); // check for existing vertex colors if ((pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0) && ((pDstLShader->GetShaderFlags2() & Niflib::SLSF2_VERTEX_COLORS) != 0)) { switch (_vcHandling) { case NCU_VC_REMOVE_FLAG: { pDstLShader->SetShaderFlags2((SkyrimShaderPropertyFlags2) (pDstLShader->GetShaderFlags2() & ~Niflib::SLSF2_VERTEX_COLORS)); break; } case NCU_VC_ADD_DEFAULT: { pDstGeo->SetVertexColors(vector<Color4>(pDstGeo->GetVertexCount(), _vcDefaultColor)); break; } } } // if ((pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0) && ... // remove property from node pDstNode->RemoveProperty(*ppIter); // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pDstLShader)); } // NiMaterialProperty else if (DynamicCast<NiMaterialProperty>(*ppIter) != NULL) { // remove property from node pDstNode->RemoveProperty(*ppIter); } } // for (vector<NiPropertyRef>::iterator ppIter = dstPropList.begin(); ppIter != dstPropList.end(); ppIter++) // add forced NiAlphaProperty? if (forceAlpha) { NiAlphaPropertyRef pPropAlpha(new NiAlphaProperty()); // set values from template pPropAlpha->SetFlags (pTmplAlphaProp->GetFlags()); pPropAlpha->SetTestThreshold(pTmplAlphaProp->GetTestThreshold()); // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pPropAlpha)); // mark alpha property hasAlpha = true; } // if (forceAlpha) // add default vertex colors if alpha property and no colors if (hasAlpha && (pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0)) { pDstGeo->SetVertexColors(vector<Color4>(pDstGeo->GetVertexCount(), _vcDefaultColor)); // force flag in BSLightingShaderProperty if (pDstLShader != NULL) { pDstLShader->SetShaderFlags2((SkyrimShaderPropertyFlags2) (pDstLShader->GetShaderFlags2() | Niflib::SLSF2_VERTEX_COLORS)); } } // reorder properties //could be in the inenviable position of neither bsproperties existing if (_reorderProperties && pDstNode->GetBSProperty(0) && pDstNode->GetBSProperty(1)) { NiPropertyRef tProp01(pDstNode->GetBSProperty(0)); NiPropertyRef tProp02(pDstNode->GetBSProperty(1)); // make sure BSLightingShaderProperty comes before NiAlphaProperty - seems a 'must be' if ((tProp01->GetType().GetTypeName() == "NiAlphaProperty") && (tProp02->GetType().GetTypeName() == "BSLightingShaderProperty") ) { pDstNode->SetBSProperty(0, tProp02); pDstNode->SetBSProperty(1, tProp01); } } // if (_reorderProperties) return pDstNode; }
/*---------------------------------------------------------------------------*/ NiTriShapeRef NifConvertUtility::convertNiTri(NiTriShapeRef pDstNode, NiTriShapeRef pTmplNode, NiAlphaPropertyRef pTmplAlphaProp) { BSLightingShaderPropertyRef pTmplLShader(NULL); BSLightingShaderPropertyRef pDstLShader (NULL); NiGeometryDataRef pDstGeo (pDstNode->GetData()); vector<NiPropertyRef> dstPropList (pDstNode->GetProperties()); vector<NiPropertyRef> dstPropArray; list<NiExtraDataRef> dstExtraList(pDstNode->GetExtraData()); short bsPropIdx (0); bool forceAlpha (pTmplAlphaProp != NULL); bool hasAlpha (false); bool tanWasCopied(false); // copy new style properties if (pDstNode->GetBSProperty(0) != NULL) dstPropArray.push_back(pDstNode->GetBSProperty(0)); if (pDstNode->GetBSProperty(1) != NULL) dstPropArray.push_back(pDstNode->GetBSProperty(1)); // look for tangent space data for (auto pIter=dstExtraList.begin(), pEnd=dstExtraList.end(); pIter != pEnd; ++pIter) { if ((DynamicCast<NiBinaryExtraData>(*pIter) != NULL) && (pDstGeo != NULL)) { vector<byte> vecByte(DynamicCast<NiBinaryExtraData>(*pIter)->GetData()); vector<Vector3> vecTan; vector<Vector3> vecBin; float* pStartT((float*) &(vecByte[0])); int numVert(pDstGeo->GetVertexCount() * 3); // extract tangent space for (int i(0); i < numVert; i += 3) { vecTan.push_back(Vector3(pStartT[i], pStartT[i+1], pStartT[i+2])); vecBin.push_back(Vector3(pStartT[numVert+i], pStartT[numVert+i+1], pStartT[numVert+i+2])); } // set tangent space pDstGeo->SetTangents (vecTan); pDstGeo->SetBitangents(vecBin); // enable tangent space pDstGeo->SetTspaceFlag(0x10); tanWasCopied = true; } // if ((DynamicCast<NiBinaryExtraData>(*pIter) != NULL) && (pDstGeo != NULL)) } // for (auto pIter=dstExtraList.begin(), pEnd=dstExtraList.end(); pIter != pEnd; ++pIter) // remove extra data pDstNode->ClearExtraData(); // data node if (pDstGeo != NULL) { // set flags if (pTmplNode->GetData() != NULL) { pDstGeo->SetConsistencyFlags(pTmplNode->GetData()->GetConsistencyFlags()); // nessessary ??? } // update tangent space? if (_updateTangentSpace && !tanWasCopied && (DynamicCast<NiTriShapeData>(pDstGeo) != NULL)) { // update tangent space if (updateTangentSpace(DynamicCast<NiTriShapeData>(pDstGeo))) { // enable tangent space pDstGeo->SetTspaceFlag(0x10); } } // if (_updateTangentSpace) } // if (pDstGeo != NULL) // properties - get them from template for (short index(0); index < 2; ++index) { // BSLightingShaderProperty if (DynamicCast<BSLightingShaderProperty>(pTmplNode->GetBSProperty(index)) != NULL) { pTmplLShader = DynamicCast<BSLightingShaderProperty>(pTmplNode->GetBSProperty(index)); } // NiAlphaProperty else if (DynamicCast<NiAlphaProperty>(pTmplNode->GetBSProperty(index)) != NULL) { pTmplAlphaProp = DynamicCast<NiAlphaProperty>(pTmplNode->GetBSProperty(index)); } } // for (short index(0); index < 2; ++index) // parse properties of destination node //dstPropList = pDstNode->GetProperties(); pDstNode->ClearProperties(); pDstNode->SetBSProperties(Niflib::array<2, NiPropertyRef>()); for (auto ppIter=dstPropList.begin(), pEnd=dstPropList.end(); ppIter != pEnd; ppIter++) { // NiAlphaProperty if (DynamicCast<NiAlphaProperty>(*ppIter) != NULL) { NiAlphaPropertyRef pPropAlpha(DynamicCast<NiAlphaProperty>(*ppIter)); // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pPropAlpha)); // own alpha, reset forced alpha forceAlpha = false; // mark alpha property hasAlpha = true; } // NiTexturingProperty else if (DynamicCast<NiTexturingProperty>(*ppIter) != NULL) { char* pTextPos (NULL); BSShaderTextureSetRef pDstSText(new BSShaderTextureSet()); TexDesc baseTex ((DynamicCast<NiTexturingProperty>(*ppIter))->GetTexture(BASE_MAP)); string texture (baseTex.source->GetTextureFileName()); string::size_type result (string::npos); // clone shader property from template pDstLShader = cloneBSLightingShaderProperty(pTmplLShader); // copy textures from template to copy pDstSText->SetTextures(pTmplLShader->GetTextureSet()->GetTextures()); // separate filename from path result = texture.rfind('\\'); if (result == string::npos) result = texture.find_last_of('/'); if (result != string::npos) texture = texture.substr(result + 1); // build texture name if (_forceDDS) { result = texture.rfind('.'); if (result != string::npos) texture.erase(result); texture += ".dds"; } // build full path texture = _pathTexture + texture; // set new texture map pDstSText->SetTexture(0, texture); logMessage(NCU_MSG_TYPE_TEXTURE, string("Txt-Used: ") + texture); if (!checkFileExists(texture)) { _newTextures.insert(string("Txt-Missed: ") + texture); } // build normal map name result = texture.rfind('.'); if (result == string::npos) { texture += "_n"; } else { string extension(texture.substr(result)); texture.erase(result); texture += "_n" + extension; } // set new normal map pDstSText->SetTexture(1, texture); if (!checkFileExists(texture)) { _newTextures.insert(string("Txt-Missed: ") + texture); } // add texture set to texture property pDstLShader->SetTextureSet(pDstSText); // check for existing vertex colors if ((pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0) && ((pDstLShader->GetShaderFlags2() & Niflib::SLSF2_VERTEX_COLORS) != 0)) { switch (_vcHandling) { case NCU_VC_REMOVE_FLAG: { pDstLShader->SetShaderFlags2((SkyrimShaderPropertyFlags2) (pDstLShader->GetShaderFlags2() & ~Niflib::SLSF2_VERTEX_COLORS)); break; } case NCU_VC_ADD_DEFAULT: { pDstGeo->SetVertexColors(vector<Color4>(pDstGeo->GetVertexCount(), _vcDefaultColor)); break; } } } // if ((pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0) && ... // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pDstLShader)); } // NiMaterialProperty else if (DynamicCast<NiMaterialProperty>(*ppIter) != NULL) { // remove property from node pDstNode->RemoveProperty(*ppIter); } } // for (vector<NiPropertyRef>::iterator ppIter = dstPropList.begin(); ppIter != dstPropList.end(); ppIter++) // add forced NiAlphaProperty? if (forceAlpha) { NiAlphaPropertyRef pPropAlpha(new NiAlphaProperty()); // set values from template pPropAlpha->SetFlags (pTmplAlphaProp->GetFlags()); pPropAlpha->SetTestThreshold(pTmplAlphaProp->GetTestThreshold()); // set new property to node pDstNode->SetBSProperty(bsPropIdx++, &(*pPropAlpha)); // mark alpha property hasAlpha = true; } // if (forceAlpha) // add default vertex colors if alpha property and no colors if (hasAlpha && (pDstGeo != NULL) && (pDstGeo->GetColors().size() <= 0)) { pDstGeo->SetVertexColors(vector<Color4>(pDstGeo->GetVertexCount(), _vcDefaultColor)); // force flag in BSLightingShaderProperty if (pDstLShader != NULL) { pDstLShader->SetShaderFlags2((SkyrimShaderPropertyFlags2) (pDstLShader->GetShaderFlags2() | Niflib::SLSF2_VERTEX_COLORS)); } } // add allowed properties to fee slots for (auto pIter=dstPropArray.begin(), pEnd=dstPropArray.end(); (pIter != pEnd) && (bsPropIdx < 2); ++pIter) { // skip old style properties if ((*pIter)->GetType().GetTypeName() == "NiMaterialProperty") continue; // add property to free slot pDstNode->SetBSProperty(bsPropIdx++, *pIter); } // reorder properties - only necessary in case of both are set if (_reorderProperties && (pDstNode->GetBSProperty(0) != NULL) && (pDstNode->GetBSProperty(1) != NULL)) { NiPropertyRef tProp01(pDstNode->GetBSProperty(0)); NiPropertyRef tProp02(pDstNode->GetBSProperty(1)); // make sure BSLightingShaderProperty comes before NiAlphaProperty - seems a 'must be' if ((tProp01->GetType().GetTypeName() == "NiAlphaProperty") && (tProp02->GetType().GetTypeName() == "BSLightingShaderProperty") ) { pDstNode->SetBSProperty(0, tProp02); pDstNode->SetBSProperty(1, tProp01); } } // if (_reorderProperties) return pDstNode; }