|
@@ -8,7 +8,7 @@
|
|
|
namespace anki
|
|
namespace anki
|
|
|
{
|
|
{
|
|
|
|
|
|
|
|
-static Error getUniformScale(const Mat4& m, F32& out)
|
|
|
|
|
|
|
+static ANKI_USE_RESULT Error getUniformScale(const Mat4& m, F32& out)
|
|
|
{
|
|
{
|
|
|
const F32 SCALE_THRESHOLD = 0.01f; // 1 cm
|
|
const F32 SCALE_THRESHOLD = 0.01f; // 1 cm
|
|
|
|
|
|
|
@@ -42,6 +42,44 @@ static void removeScale(Mat4& m)
|
|
|
m.setRotationPart(rot);
|
|
m.setRotationPart(rot);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static ANKI_USE_RESULT Error getNodeTransform(const cgltf_node& node, Transform& trf)
|
|
|
|
|
+{
|
|
|
|
|
+ trf = Transform::getIdentity();
|
|
|
|
|
+ if(node.has_matrix)
|
|
|
|
|
+ {
|
|
|
|
|
+ Mat4 mat = Mat4(node.matrix).getTransposed();
|
|
|
|
|
+ F32 scale;
|
|
|
|
|
+ ANKI_CHECK(getUniformScale(mat, scale));
|
|
|
|
|
+ removeScale(mat);
|
|
|
|
|
+ trf = Transform(mat);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ if(node.has_translation)
|
|
|
|
|
+ {
|
|
|
|
|
+ trf.setOrigin(Vec4(node.translation[0], node.translation[1], node.translation[2], 0.0f));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(node.has_rotation)
|
|
|
|
|
+ {
|
|
|
|
|
+ trf.setRotation(Mat3x4(Quat(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3])));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(node.has_scale)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(node.scale[0] != node.scale[1] || node.scale[0] != node.scale[2])
|
|
|
|
|
+ {
|
|
|
|
|
+ ANKI_GLTF_LOGE("Expecting uniform scale");
|
|
|
|
|
+ return Error::USER_DATA;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ trf.setScale(node.scale[0]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return Error::NONE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
Importer::Importer()
|
|
Importer::Importer()
|
|
|
{
|
|
{
|
|
|
m_hive = m_alloc.newInstance<ThreadHive>(getCpuCoresCount(), m_alloc, true);
|
|
m_hive = m_alloc.newInstance<ThreadHive>(getCpuCoresCount(), m_alloc, true);
|
|
@@ -101,12 +139,14 @@ Error Importer::writeAll()
|
|
|
sceneFname.sprintf("%sscene.lua", m_outDir.cstr());
|
|
sceneFname.sprintf("%sscene.lua", m_outDir.cstr());
|
|
|
ANKI_CHECK(m_sceneFile.open(sceneFname.toCString(), FileOpenFlag::WRITE));
|
|
ANKI_CHECK(m_sceneFile.open(sceneFname.toCString(), FileOpenFlag::WRITE));
|
|
|
|
|
|
|
|
|
|
+ ANKI_CHECK(m_sceneFile.writeText("local scene = getSceneGraph()\nlocal events = getEventManager()\n"));
|
|
|
|
|
+
|
|
|
// Nodes
|
|
// Nodes
|
|
|
for(const cgltf_scene* scene = m_gltf->scenes; scene < m_gltf->scenes + m_gltf->scenes_count; ++scene)
|
|
for(const cgltf_scene* scene = m_gltf->scenes; scene < m_gltf->scenes + m_gltf->scenes_count; ++scene)
|
|
|
{
|
|
{
|
|
|
for(cgltf_node* const* node = scene->nodes; node < scene->nodes + scene->nodes_count; ++node)
|
|
for(cgltf_node* const* node = scene->nodes; node < scene->nodes + scene->nodes_count; ++node)
|
|
|
{
|
|
{
|
|
|
- ANKI_CHECK(visitNode(*(*node)));
|
|
|
|
|
|
|
+ ANKI_CHECK(visitNode(*(*node), Transform::getIdentity()));
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -115,7 +155,26 @@ Error Importer::writeAll()
|
|
|
|
|
|
|
|
Error Importer::getExtras(const cgltf_extras& extras, HashMapAuto<StringAuto, StringAuto>& out)
|
|
Error Importer::getExtras(const cgltf_extras& extras, HashMapAuto<StringAuto, StringAuto>& out)
|
|
|
{
|
|
{
|
|
|
- // TODO
|
|
|
|
|
|
|
+ cgltf_size extrasSize;
|
|
|
|
|
+ cgltf_copy_extras_json(m_gltf, &extras, nullptr, &extrasSize);
|
|
|
|
|
+ if(extrasSize == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return Error::NONE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ DynamicArrayAuto<char> json(m_alloc);
|
|
|
|
|
+ json.create(extrasSize + 1);
|
|
|
|
|
+ cgltf_result res = cgltf_copy_extras_json(m_gltf, &extras, &json[0], &extrasSize);
|
|
|
|
|
+ if(res != cgltf_result_success)
|
|
|
|
|
+ {
|
|
|
|
|
+ ANKI_GLTF_LOGE("cgltf_copy_extras_json failed: %d", res);
|
|
|
|
|
+ return Error::FUNCTION_FAILED;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ json[json.getSize() - 1] = '\0';
|
|
|
|
|
+
|
|
|
|
|
+ printf("%s\n", &json[0]);
|
|
|
|
|
+
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -150,8 +209,15 @@ Error Importer::parseArrayOfNumbers(CString str, DynamicArrayAuto<F64>& out, con
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-Error Importer::visitNode(const cgltf_node& node)
|
|
|
|
|
|
|
+Error Importer::visitNode(const cgltf_node& node, const Transform& parentTrf)
|
|
|
{
|
|
{
|
|
|
|
|
+ Transform localTrf;
|
|
|
|
|
+ ANKI_CHECK(getNodeTransform(node, localTrf));
|
|
|
|
|
+ const Transform finalTrf = parentTrf.combineTransformations(localTrf);
|
|
|
|
|
+
|
|
|
|
|
+ Transform newParentTrf = Transform::getIdentity();
|
|
|
|
|
+ HashMapAuto<StringAuto, StringAuto> parentExtras(m_alloc);
|
|
|
|
|
+ Bool writeTrf = true;
|
|
|
if(node.light)
|
|
if(node.light)
|
|
|
{
|
|
{
|
|
|
ANKI_CHECK(writeLight(node));
|
|
ANKI_CHECK(writeLight(node));
|
|
@@ -167,53 +233,35 @@ Error Importer::visitNode(const cgltf_node& node)
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- ANKI_GLTF_LOGW("Ignoring node %s", node.name);
|
|
|
|
|
|
|
+ ANKI_GLTF_LOGW("Ignoring node %s. Assuming transform node", node.name);
|
|
|
|
|
+ newParentTrf = finalTrf;
|
|
|
|
|
+ ANKI_CHECK(getExtras(node.extras, parentExtras));
|
|
|
|
|
+ writeTrf = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- return Error::NONE;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-Error Importer::writeTransform(const cgltf_node& node)
|
|
|
|
|
-{
|
|
|
|
|
- Transform trf = Transform::getIdentity();
|
|
|
|
|
- if(node.has_matrix)
|
|
|
|
|
|
|
+ // Write transform
|
|
|
|
|
+ if(writeTrf)
|
|
|
{
|
|
{
|
|
|
- Mat4 mat = Mat4(node.matrix).getTransposed();
|
|
|
|
|
- F32 scale;
|
|
|
|
|
- ANKI_CHECK(getUniformScale(mat, scale));
|
|
|
|
|
- removeScale(mat);
|
|
|
|
|
- trf = Transform(mat);
|
|
|
|
|
|
|
+ ANKI_CHECK(writeTransform(finalTrf));
|
|
|
}
|
|
}
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- if(node.has_translation)
|
|
|
|
|
- {
|
|
|
|
|
- trf.setOrigin(Vec4(node.translation[0], node.translation[1], node.translation[2], 0.0f));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(node.has_rotation)
|
|
|
|
|
- {
|
|
|
|
|
- trf.setRotation(Mat3x4(Quat(node.rotation[0], node.rotation[1], node.rotation[2], node.rotation[3])));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(node.has_scale)
|
|
|
|
|
- {
|
|
|
|
|
- if(node.scale[0] != node.scale[1] || node.scale[0] != node.scale[2])
|
|
|
|
|
- {
|
|
|
|
|
- ANKI_GLTF_LOGE("Expecting uniform scale");
|
|
|
|
|
- return Error::USER_DATA;
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- trf.setScale(node.scale[0]);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // Visit children
|
|
|
|
|
+ for(cgltf_node* const* c = node.children; c < node.children + node.children_count; ++c)
|
|
|
|
|
+ {
|
|
|
|
|
+ ANKI_CHECK(visitNode(*(*c), newParentTrf));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ return Error::NONE;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+Error Importer::writeTransform(const Transform& trf)
|
|
|
|
|
+{
|
|
|
ANKI_CHECK(m_sceneFile.writeText("trf = Transform.new()\n"));
|
|
ANKI_CHECK(m_sceneFile.writeText("trf = Transform.new()\n"));
|
|
|
ANKI_CHECK(m_sceneFile.writeText(
|
|
ANKI_CHECK(m_sceneFile.writeText(
|
|
|
- "trf:setOrigin(%f, %f, %f, 0)\n", trf.getOrigin().x(), trf.getOrigin().y(), trf.getOrigin().z()));
|
|
|
|
|
|
|
+ "trf:setOrigin(Vec4.new(%f, %f, %f, 0))\n", trf.getOrigin().x(), trf.getOrigin().y(), trf.getOrigin().z()));
|
|
|
|
|
|
|
|
ANKI_CHECK(m_sceneFile.writeText("rot = Mat3x4.new()\n"));
|
|
ANKI_CHECK(m_sceneFile.writeText("rot = Mat3x4.new()\n"));
|
|
|
- ANKI_CHECK(m_sceneFile.writeText("rot:setAll(\n"));
|
|
|
|
|
|
|
+ ANKI_CHECK(m_sceneFile.writeText("rot:setAll("));
|
|
|
for(U i = 0; i < 12; i++)
|
|
for(U i = 0; i < 12; i++)
|
|
|
{
|
|
{
|
|
|
ANKI_CHECK(m_sceneFile.writeText((i != 11) ? "%f, " : "%f)\n", trf.getRotation()[i]));
|
|
ANKI_CHECK(m_sceneFile.writeText((i != 11) ? "%f, " : "%f)\n", trf.getRotation()[i]));
|
|
@@ -265,8 +313,8 @@ Error Importer::writeModel(const cgltf_mesh& mesh)
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
|
- ANKI_CHECK(
|
|
|
|
|
- file.writeText("\t\t\t<material>%s%s</material>\n", m_rpath.cstr(), mesh.primitives[0].material->name));
|
|
|
|
|
|
|
+ ANKI_CHECK(file.writeText(
|
|
|
|
|
+ "\t\t\t<material>%s%s.ankimtl</material>\n", m_rpath.cstr(), mesh.primitives[0].material->name));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
|
|
ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
|
|
@@ -308,6 +356,7 @@ Error Importer::writeLight(const cgltf_node& node)
|
|
|
ANKI_CHECK(m_sceneFile.writeText("lcomp = node:getSceneNodeBase():getLightComponent()\n"));
|
|
ANKI_CHECK(m_sceneFile.writeText("lcomp = node:getSceneNodeBase():getLightComponent()\n"));
|
|
|
|
|
|
|
|
Vec3 color(light.color[0], light.color[1], light.color[2]);
|
|
Vec3 color(light.color[0], light.color[1], light.color[2]);
|
|
|
|
|
+ color *= light.intensity;
|
|
|
ANKI_CHECK(
|
|
ANKI_CHECK(
|
|
|
m_sceneFile.writeText("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
|
|
m_sceneFile.writeText("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
|
|
|
|
|
|
|
@@ -398,14 +447,12 @@ Error Importer::writeLight(const cgltf_node& node)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ANKI_CHECK(writeTransform(node));
|
|
|
|
|
-
|
|
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Error Importer::writeCamera(const cgltf_node& node)
|
|
Error Importer::writeCamera(const cgltf_node& node)
|
|
|
{
|
|
{
|
|
|
- if(node.camera->type != cgltf_camera_type_orthographic)
|
|
|
|
|
|
|
+ if(node.camera->type != cgltf_camera_type_perspective)
|
|
|
{
|
|
{
|
|
|
ANKI_GLTF_LOGW("Unsupported camera type: %s", node.name);
|
|
ANKI_GLTF_LOGW("Unsupported camera type: %s", node.name);
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
@@ -414,18 +461,15 @@ Error Importer::writeCamera(const cgltf_node& node)
|
|
|
const cgltf_camera_perspective& cam = node.camera->perspective;
|
|
const cgltf_camera_perspective& cam = node.camera->perspective;
|
|
|
ANKI_GLTF_LOGI("Exporting camera %s", node.name);
|
|
ANKI_GLTF_LOGI("Exporting camera %s", node.name);
|
|
|
|
|
|
|
|
- ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newPerspectiveCameraNode(\"%s\")", node.name));
|
|
|
|
|
|
|
+ ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newPerspectiveCameraNode(\"%s\")\n", node.name));
|
|
|
ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node:getSceneNodeBase())\n"));
|
|
ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node:getSceneNodeBase())\n"));
|
|
|
ANKI_CHECK(m_sceneFile.writeText("frustumc = node:getSceneNodeBase():getFrustumComponent()\n"));
|
|
ANKI_CHECK(m_sceneFile.writeText("frustumc = node:getSceneNodeBase():getFrustumComponent()\n"));
|
|
|
|
|
|
|
|
- ANKI_CHECK(
|
|
|
|
|
- m_sceneFile.writeText("frustumc:setPerspective(%f, %f, %f, 1.0 / getMainRenderer():getAspectRatio() * %f)\n",
|
|
|
|
|
- cam.znear,
|
|
|
|
|
- cam.zfar,
|
|
|
|
|
- cam.yfov,
|
|
|
|
|
- cam.yfov));
|
|
|
|
|
-
|
|
|
|
|
- ANKI_CHECK(writeTransform(node));
|
|
|
|
|
|
|
+ ANKI_CHECK(m_sceneFile.writeText("frustumc:setPerspective(%f, %f, getMainRenderer():getAspectRatio() * %f, %f)\n",
|
|
|
|
|
+ cam.znear,
|
|
|
|
|
+ cam.zfar,
|
|
|
|
|
+ cam.yfov,
|
|
|
|
|
+ cam.yfov));
|
|
|
|
|
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
|
}
|
|
}
|
|
@@ -439,8 +483,6 @@ Error Importer::writeModelNode(const cgltf_node& node)
|
|
|
|
|
|
|
|
ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newModelNode(\"%s\", \"%s\")\n", node.name, modelFname.cstr()));
|
|
ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newModelNode(\"%s\", \"%s\")\n", node.name, modelFname.cstr()));
|
|
|
|
|
|
|
|
- ANKI_CHECK(writeTransform(node));
|
|
|
|
|
-
|
|
|
|
|
// TODO: collision mesh
|
|
// TODO: collision mesh
|
|
|
|
|
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|