mirror of
https://github.com/aimrebirth/tools.git
synced 2026-04-15 01:43:25 +00:00
Refactor fbx output.
This commit is contained in:
parent
baacacc44b
commit
33787f94ae
1 changed files with 119 additions and 153 deletions
|
|
@ -252,6 +252,117 @@ void model::printFbx(const std::string &fn, AxisSystem as) const
|
||||||
DestroySdkObjects(lSdkManager, true);
|
DestroySdkObjects(lSdkManager, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FbxMesh *create_mesh(FbxScene *s, const block &b)
|
||||||
|
{
|
||||||
|
auto m = FbxMesh::Create(s, b.h.name.c_str());
|
||||||
|
|
||||||
|
// vertexes
|
||||||
|
{
|
||||||
|
m->InitControlPoints(b.pmd.vertices.size());
|
||||||
|
auto cps = m->GetControlPoints();
|
||||||
|
for (const auto &[i, v] : enumerate(b.pmd.vertices))
|
||||||
|
cps[i] = FbxVector4(v.x, v.y, v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// normals
|
||||||
|
{
|
||||||
|
auto normal = m->CreateElementNormal();
|
||||||
|
normal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
normal->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
for (const auto &v : b.pmd.normals)
|
||||||
|
normal->GetDirectArray().Add(FbxVector4(v.x, v.y, v.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
// uvs
|
||||||
|
{
|
||||||
|
auto uv = m->CreateElementUV("uv", FbxLayerElement::eTextureDiffuse);
|
||||||
|
uv->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
||||||
|
uv->SetReferenceMode(FbxGeometryElement::eDirect);
|
||||||
|
for (const auto &[u,v] : b.pmd.uvs)
|
||||||
|
uv->GetDirectArray().Add(FbxVector2(u, v));
|
||||||
|
//float f;
|
||||||
|
//auto uc = modf(fabs(u), &f);
|
||||||
|
//auto vc = modf(fabs(v), &f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// faces
|
||||||
|
for (auto &v : b.pmd.faces)
|
||||||
|
{
|
||||||
|
// Set the control point indices of the bottom side of the pyramid
|
||||||
|
m->BeginPolygon();
|
||||||
|
for (auto &i : v.points)
|
||||||
|
m->AddPolygon(i.vertex);
|
||||||
|
m->EndPolygon();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add smoothing groups
|
||||||
|
{
|
||||||
|
FbxGeometryConverter lGeometryConverter(m->GetFbxManager());
|
||||||
|
lGeometryConverter.ComputeEdgeSmoothingFromNormals(m);
|
||||||
|
//convert soft/hard edge info to smoothing group info
|
||||||
|
lGeometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_material(FbxMesh *m, const block &b)
|
||||||
|
{
|
||||||
|
m->GetNode()->RemoveAllMaterials();
|
||||||
|
|
||||||
|
auto mat = m->CreateElementMaterial();
|
||||||
|
// This allows us to control where the materials are mapped. Using eAllSame
|
||||||
|
// means that all faces/polygons of the mesh will be assigned the same material.
|
||||||
|
mat->SetMappingMode(FbxLayerElement::eAllSame);
|
||||||
|
mat->SetReferenceMode(FbxLayerElement::eDirect);
|
||||||
|
|
||||||
|
auto lMaterial = FbxSurfacePhong::Create(m->GetNode(), b.h.name.c_str());
|
||||||
|
|
||||||
|
FbxDouble3 lAmbientColor(b.mat.ambient.r, b.mat.ambient.g, b.mat.ambient.b);
|
||||||
|
FbxDouble3 lSpecularColor(b.mat.specular.r, b.mat.specular.g, b.mat.specular.b);
|
||||||
|
FbxDouble3 lDiffuseColor(b.mat.diffuse.r, b.mat.diffuse.g, b.mat.diffuse.b);
|
||||||
|
FbxDouble3 lEmissiveColor(b.mat.emissive.r, b.mat.emissive.g, b.mat.emissive.b);
|
||||||
|
|
||||||
|
// Generate primary and secondary colors.
|
||||||
|
lMaterial->Emissive.Set(lEmissiveColor);
|
||||||
|
lMaterial->EmissiveFactor.Set(b.mat.emissive.r);
|
||||||
|
|
||||||
|
lMaterial->Ambient.Set(lAmbientColor);
|
||||||
|
lMaterial->AmbientFactor.Set(b.mat.ambient.r);
|
||||||
|
|
||||||
|
lMaterial->Diffuse.Set(lDiffuseColor);
|
||||||
|
lMaterial->DiffuseFactor.Set(b.mat.diffuse.r);
|
||||||
|
|
||||||
|
//lMaterial->TransparencyFactor.Set(0.4);
|
||||||
|
lMaterial->ShadingModel.Set("Phong");
|
||||||
|
//lMaterial->Shininess.Set(0.5);
|
||||||
|
|
||||||
|
lMaterial->Specular.Set(lSpecularColor);
|
||||||
|
lMaterial->SpecularFactor.Set(b.mat.power);
|
||||||
|
|
||||||
|
m->GetNode()->AddMaterial(lMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_textures(FbxMesh *m, const block &b)
|
||||||
|
{
|
||||||
|
auto add_tex = [m, &b](String name, String texname, auto &what)
|
||||||
|
{
|
||||||
|
auto lTexture = FbxFileTexture::Create(m->GetNode(), (name + " Texture").c_str());
|
||||||
|
lTexture->SetFileName((texname + texture_extension).c_str()); // Resource file is in current directory.
|
||||||
|
lTexture->SetTextureUse(FbxTexture::eStandard);
|
||||||
|
lTexture->SetMappingType(FbxTexture::eUV);
|
||||||
|
lTexture->SetMaterialUse(FbxFileTexture::eDefaultMaterial);
|
||||||
|
lTexture->UVSet.Set(m->GetElementUV()->GetName());
|
||||||
|
|
||||||
|
what.ConnectSrcObject(lTexture);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto mat = (FbxSurfacePhong *)m->GetNode()->GetMaterial(0);
|
||||||
|
add_tex("Specular", b.h.spec.name, mat->Specular);
|
||||||
|
add_tex("Diffuse", b.h.mask.name, mat->Diffuse);
|
||||||
|
add_tex("Ambient", b.h.mask.name, mat->Ambient);
|
||||||
|
}
|
||||||
|
|
||||||
bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkManager, FbxScene* pScene)
|
bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkManager, FbxScene* pScene)
|
||||||
{
|
{
|
||||||
static const char* gDiffuseElementName = "DiffuseUV";
|
static const char* gDiffuseElementName = "DiffuseUV";
|
||||||
|
|
@ -322,166 +433,21 @@ bool CreateScene(const model &model, const std::string &name, FbxManager* pSdkMa
|
||||||
//auto block_name = name + "/" + b.h.name;
|
//auto block_name = name + "/" + b.h.name;
|
||||||
const auto block_name = b.h.name;
|
const auto block_name = b.h.name;
|
||||||
|
|
||||||
// mesh
|
// mesh node
|
||||||
auto m = FbxMesh::Create(pScene, block_name.c_str());
|
|
||||||
|
|
||||||
// node
|
|
||||||
FbxNode *node = FbxNode::Create(pScene, block_name.c_str());
|
FbxNode *node = FbxNode::Create(pScene, block_name.c_str());
|
||||||
|
pScene->GetRootNode()->AddChild(node);
|
||||||
|
auto m = create_mesh(pScene, b);
|
||||||
node->SetNodeAttribute(m);
|
node->SetNodeAttribute(m);
|
||||||
node->SetShadingMode(FbxNode::eFullShading); // change?! was texture sh
|
set_material(m, b);
|
||||||
|
|
||||||
// vertices
|
|
||||||
m->InitControlPoints(b.pmd.vertices.size());
|
|
||||||
|
|
||||||
// normals
|
|
||||||
auto normal = m->CreateElementNormal();
|
|
||||||
normal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
normal->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
|
|
||||||
// uv
|
|
||||||
auto create_uv = [&m](auto &name)
|
|
||||||
{
|
|
||||||
auto uv1 = m->CreateElementUV(name);
|
|
||||||
uv1->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
uv1->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
return uv1;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto d_uv = create_uv(gDiffuseElementName);
|
|
||||||
auto a_uv = create_uv(gAmbientElementName);
|
|
||||||
auto s_uv = create_uv(gSpecularElementName);
|
|
||||||
|
|
||||||
// add vertices, normals, uvs
|
|
||||||
SW_CHECK(b.pmd.vertices.size() == b.pmd.normals.size());
|
|
||||||
for (const auto &[i,v] : enumerate(b.pmd.vertices))
|
|
||||||
{
|
|
||||||
FbxVector4 cp(v.x * scale_mult(), v.y * scale_mult(), v.z * scale_mult(), v.w);
|
|
||||||
FbxVector4 n(b.pmd.normals[i].x, b.pmd.normals[i].y, b.pmd.normals[i].z);
|
|
||||||
m->SetControlPointAt(cp, n, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// uvs
|
|
||||||
for (const auto &[u,v] : b.pmd.uvs)
|
|
||||||
{
|
|
||||||
float f;
|
|
||||||
auto uc = modf(fabs(u), &f);
|
|
||||||
auto vc = modf(fabs(v), &f);
|
|
||||||
d_uv->GetDirectArray().Add(FbxVector2(uc, vc));
|
|
||||||
a_uv->GetDirectArray().Add(FbxVector2(uc, vc));
|
|
||||||
s_uv->GetDirectArray().Add(FbxVector2(uc, vc));
|
|
||||||
}
|
|
||||||
|
|
||||||
// faces
|
|
||||||
for (auto &v : b.pmd.faces)
|
|
||||||
{
|
|
||||||
// Set the control point indices of the bottom side of the pyramid
|
|
||||||
m->BeginPolygon();
|
|
||||||
for (auto &i : v.points)
|
|
||||||
m->AddPolygon(i.vertex);
|
|
||||||
m->EndPolygon();
|
|
||||||
}
|
|
||||||
|
|
||||||
m->BuildMeshEdgeArray();
|
|
||||||
|
|
||||||
//if (m->GenerateNormals(true))
|
|
||||||
//throw SW_RUNTIME_ERROR("Cannot generate normals");
|
|
||||||
|
|
||||||
// mats
|
|
||||||
auto lMaterial = node->GetSrcObject<FbxSurfacePhong>(0);
|
|
||||||
if (!lMaterial)
|
|
||||||
{
|
|
||||||
FbxString lMaterialName = block_name.c_str();
|
|
||||||
FbxString lShadingName = "Phong";
|
|
||||||
FbxDouble3 lAmbientColor(b.mat.ambient.r, b.mat.ambient.g, b.mat.ambient.b);
|
|
||||||
FbxDouble3 lSpecularColor(b.mat.specular.r, b.mat.specular.g, b.mat.specular.b);
|
|
||||||
FbxDouble3 lDiffuseColor(b.mat.diffuse.r, b.mat.diffuse.g, b.mat.diffuse.b);
|
|
||||||
FbxDouble3 lEmissiveColor(b.mat.emissive.r, b.mat.emissive.g, b.mat.emissive.b);
|
|
||||||
|
|
||||||
FbxLayer* lLayer = m->GetLayer(0);
|
|
||||||
|
|
||||||
// Create a layer element material to handle proper mapping.
|
|
||||||
FbxLayerElementMaterial* lLayerElementMaterial = FbxLayerElementMaterial::Create(m, lMaterialName.Buffer());
|
|
||||||
|
|
||||||
// This allows us to control where the materials are mapped. Using eAllSame
|
|
||||||
// means that all faces/polygons of the mesh will be assigned the same material.
|
|
||||||
lLayerElementMaterial->SetMappingMode(FbxLayerElement::eAllSame);
|
|
||||||
lLayerElementMaterial->SetReferenceMode(FbxLayerElement::eDirect);
|
|
||||||
|
|
||||||
// Save the material on the layer
|
|
||||||
lLayer->SetMaterials(lLayerElementMaterial);
|
|
||||||
|
|
||||||
// Add an index to the lLayerElementMaterial. Since we have only one, and are using eAllSame mapping mode,
|
|
||||||
// we only need to add one.
|
|
||||||
lLayerElementMaterial->GetIndexArray().Add(0);
|
|
||||||
|
|
||||||
lMaterial = FbxSurfacePhong::Create(pScene, lMaterialName.Buffer());
|
|
||||||
|
|
||||||
// Generate primary and secondary colors.
|
|
||||||
lMaterial->Emissive.Set(lEmissiveColor);
|
|
||||||
lMaterial->EmissiveFactor.Set(b.mat.emissive.r);
|
|
||||||
|
|
||||||
lMaterial->Ambient.Set(lAmbientColor);
|
|
||||||
lMaterial->AmbientFactor.Set(b.mat.ambient.r);
|
|
||||||
|
|
||||||
// Add texture for diffuse channel
|
|
||||||
lMaterial->Diffuse.Set(lDiffuseColor);
|
|
||||||
lMaterial->DiffuseFactor.Set(b.mat.diffuse.r);
|
|
||||||
|
|
||||||
//lMaterial->TransparencyFactor.Set(0.4);
|
|
||||||
lMaterial->ShadingModel.Set(lShadingName);
|
|
||||||
//lMaterial->Shininess.Set(0.5);
|
|
||||||
|
|
||||||
lMaterial->Specular.Set(lSpecularColor);
|
|
||||||
lMaterial->SpecularFactor.Set(b.mat.power);
|
|
||||||
node->AddMaterial(lMaterial);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (b.mat_type != MaterialType::MaterialOnly)
|
if (b.mat_type != MaterialType::MaterialOnly)
|
||||||
{
|
set_textures(m, b);
|
||||||
FbxFileTexture* lTexture;
|
|
||||||
|
|
||||||
// Set texture properties.
|
//node->SetShadingMode(FbxNode::eFullShading); // change?! was texture sh
|
||||||
lTexture = FbxFileTexture::Create(pScene, "Diffuse Texture");
|
|
||||||
lTexture->SetFileName((b.h.mask.name + texture_extension).c_str()); // Resource file is in current directory.
|
|
||||||
lTexture->SetTextureUse(FbxTexture::eStandard);
|
|
||||||
lTexture->SetMappingType(FbxTexture::eUV);
|
|
||||||
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
|
|
||||||
lTexture->UVSet.Set(gDiffuseElementName);
|
|
||||||
if (lMaterial)
|
|
||||||
lMaterial->Diffuse.ConnectSrcObject(lTexture);
|
|
||||||
|
|
||||||
// Set texture properties.
|
|
||||||
lTexture = FbxFileTexture::Create(pScene, "Ambient Texture");
|
|
||||||
lTexture->SetFileName((b.h.mask.name + texture_extension).c_str()); // Resource file is in current directory.
|
|
||||||
lTexture->SetTextureUse(FbxTexture::eStandard);
|
|
||||||
lTexture->SetMappingType(FbxTexture::eUV);
|
|
||||||
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
|
|
||||||
lTexture->UVSet.Set(gAmbientElementName);
|
|
||||||
if (lMaterial)
|
|
||||||
lMaterial->Ambient.ConnectSrcObject(lTexture);
|
|
||||||
|
|
||||||
// Set texture properties.
|
|
||||||
lTexture = FbxFileTexture::Create(pScene, "Specular Texture");
|
|
||||||
lTexture->SetFileName((b.h.spec.name + texture_extension).c_str()); // Resource file is in current directory.
|
|
||||||
lTexture->SetTextureUse(FbxTexture::eStandard);
|
|
||||||
lTexture->SetMappingType(FbxTexture::eUV);
|
|
||||||
lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial);
|
|
||||||
lTexture->UVSet.Set(gSpecularElementName);
|
|
||||||
if (lMaterial)
|
|
||||||
lMaterial->Specular.ConnectSrcObject(lTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add smoothing groups
|
|
||||||
FbxGeometryConverter lGeometryConverter(pSdkManager);
|
|
||||||
lGeometryConverter.ComputeEdgeSmoothingFromNormals(m);
|
|
||||||
//convert soft/hard edge info to smoothing group info
|
|
||||||
lGeometryConverter.ComputePolygonSmoothingFromEdgeSmoothing(m);
|
|
||||||
|
|
||||||
// scale
|
// scale
|
||||||
//node->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult()));
|
node->LclScaling.Set(FbxDouble3(scale_mult(), scale_mult(), scale_mult()));
|
||||||
|
|
||||||
//
|
//m->BuildMeshEdgeArray();
|
||||||
pScene->GetRootNode()->AddChild(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue