mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	glTF: Clean up rigid animation
This commit is contained in:
		
				
					committed by
					
						
						Lars Müller
					
				
			
			
				
	
			
			
			
						parent
						
							5113fcaedd
						
					
				
				
					commit
					01e4395977
				
			@@ -364,18 +364,6 @@ IAnimatedMesh* SelfType::createMesh(io::IReadFile* file)
 | 
			
		||||
	return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void transformVertices(std::vector<video::S3DVertex> &vertices, const core::matrix4 &transform)
 | 
			
		||||
{
 | 
			
		||||
	for (auto &vertex : vertices) {
 | 
			
		||||
		// Apply scaling, rotation and rotation (in that order) to the position.
 | 
			
		||||
		transform.transformVect(vertex.Pos);
 | 
			
		||||
		// For the normal, we do not want to apply the translation.
 | 
			
		||||
		vertex.Normal = transform.rotateAndScaleVect(vertex.Normal);
 | 
			
		||||
		// Renormalize (length might have been affected by scaling).
 | 
			
		||||
		vertex.Normal.normalize();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void checkIndices(const std::vector<u16> &indices, const std::size_t nVerts)
 | 
			
		||||
{
 | 
			
		||||
	for (u16 index : indices) {
 | 
			
		||||
@@ -425,12 +413,6 @@ void SelfType::MeshExtractor::addPrimitive(
 | 
			
		||||
	if (n_vertices >= std::numeric_limits<u16>::max())
 | 
			
		||||
		throw std::runtime_error("too many vertices");
 | 
			
		||||
 | 
			
		||||
	// Apply the global transform along the parent chain.
 | 
			
		||||
	// "Only the joint transforms are applied to the skinned mesh;
 | 
			
		||||
	// the transform of the skinned mesh node MUST be ignored."
 | 
			
		||||
	if (!skinIdx)
 | 
			
		||||
		transformVertices(*vertices, parent->GlobalMatrix);
 | 
			
		||||
 | 
			
		||||
	auto maybeIndices = getIndices(primitive);
 | 
			
		||||
	std::vector<u16> indices;
 | 
			
		||||
	if (maybeIndices.has_value()) {
 | 
			
		||||
@@ -441,10 +423,9 @@ void SelfType::MeshExtractor::addPrimitive(
 | 
			
		||||
		indices = generateIndices(vertices->size());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_irr_model->addMeshBuffer(
 | 
			
		||||
			new SSkinMeshBuffer(std::move(*vertices), std::move(indices)));
 | 
			
		||||
	auto *meshbuf = new SSkinMeshBuffer(std::move(*vertices), std::move(indices));
 | 
			
		||||
	m_irr_model->addMeshBuffer(meshbuf);
 | 
			
		||||
	const auto meshbufNr = m_irr_model->getMeshBufferCount() - 1;
 | 
			
		||||
	auto *meshbuf = m_irr_model->getMeshBuffer(meshbufNr);
 | 
			
		||||
 | 
			
		||||
	if (primitive.material.has_value()) {
 | 
			
		||||
		const auto &material = m_gltf_model.materials->at(*primitive.material);
 | 
			
		||||
@@ -463,17 +444,17 @@ void SelfType::MeshExtractor::addPrimitive(
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!skinIdx.has_value()) {
 | 
			
		||||
		// No skin => all vertices belong entirely to their parent
 | 
			
		||||
		for (std::size_t v = 0; v < n_vertices; ++v) {
 | 
			
		||||
			auto *weight = m_irr_model->addWeight(parent);
 | 
			
		||||
			weight->buffer_id = meshbufNr;
 | 
			
		||||
			weight->vertex_id = v;
 | 
			
		||||
			weight->strength = 1.0f;
 | 
			
		||||
		}
 | 
			
		||||
	if (!skinIdx) {
 | 
			
		||||
		// Apply the global transform along the parent chain.
 | 
			
		||||
		meshbuf->Transformation = parent->GlobalMatrix;
 | 
			
		||||
		// Set up rigid animation
 | 
			
		||||
		parent->AttachedMeshes.push_back(meshbufNr);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Otherwise: "Only the joint transforms are applied to the skinned mesh;
 | 
			
		||||
	// the transform of the skinned mesh node MUST be ignored."
 | 
			
		||||
 | 
			
		||||
	const auto &skin = m_gltf_model.skins->at(*skinIdx);
 | 
			
		||||
 | 
			
		||||
	const auto &attrs = primitive.attributes;
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,20 @@ SECTION("minimal triangle") {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto check_cube_vertices = [](auto *meshbuf) {
 | 
			
		||||
	REQUIRE(meshbuf->getVertexCount() == 24);
 | 
			
		||||
	auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
			meshbuf->getVertices());
 | 
			
		||||
	CHECK(vertices[0].Pos == v3f{-1.0f, -1.0f, -1.0f});
 | 
			
		||||
	CHECK(vertices[3].Pos == v3f{-1.0f, 1.0f, -1.0f});
 | 
			
		||||
	CHECK(vertices[6].Pos == v3f{-1.0f, -1.0f, 1.0f});
 | 
			
		||||
	CHECK(vertices[9].Pos == v3f{-1.0f, 1.0f, 1.0f});
 | 
			
		||||
	CHECK(vertices[12].Pos == v3f{1.0f, -1.0f, -1.0f});
 | 
			
		||||
	CHECK(vertices[15].Pos == v3f{1.0f, 1.0f, -1.0f});
 | 
			
		||||
	CHECK(vertices[18].Pos == v3f{1.0f, -1.0f, 1.0f});
 | 
			
		||||
	CHECK(vertices[21].Pos == v3f{1.0f, 1.0f, 1.0f});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SECTION("blender cube") {
 | 
			
		||||
	const auto path = GENERATE(
 | 
			
		||||
		model_stem + "blender_cube.gltf",
 | 
			
		||||
@@ -98,24 +112,20 @@ SECTION("blender cube") {
 | 
			
		||||
	const auto mesh = loadMesh(path);
 | 
			
		||||
	REQUIRE(mesh);
 | 
			
		||||
	REQUIRE(mesh->getMeshBufferCount() == 1);
 | 
			
		||||
	auto *meshbuf = dynamic_cast<irr::scene::SSkinMeshBuffer *>(
 | 
			
		||||
				mesh->getMeshBuffer(0));
 | 
			
		||||
	REQUIRE(meshbuf);
 | 
			
		||||
	SECTION("vertex coordinates are correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getVertexCount() == 24);
 | 
			
		||||
		auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getVertices());
 | 
			
		||||
		CHECK(vertices[0].Pos == v3f{-10.0f, -10.0f, -10.0f});
 | 
			
		||||
		CHECK(vertices[3].Pos == v3f{-10.0f, 10.0f, -10.0f});
 | 
			
		||||
		CHECK(vertices[6].Pos == v3f{-10.0f, -10.0f, 10.0f});
 | 
			
		||||
		CHECK(vertices[9].Pos == v3f{-10.0f, 10.0f, 10.0f});
 | 
			
		||||
		CHECK(vertices[12].Pos == v3f{10.0f, -10.0f, -10.0f});
 | 
			
		||||
		CHECK(vertices[15].Pos == v3f{10.0f, 10.0f, -10.0f});
 | 
			
		||||
		CHECK(vertices[18].Pos == v3f{10.0f, -10.0f, 10.0f});
 | 
			
		||||
		CHECK(vertices[21].Pos == v3f{10.0f, 10.0f, 10.0f});
 | 
			
		||||
		core::matrix4 scale;
 | 
			
		||||
		scale.setScale(v3f(10.0f));
 | 
			
		||||
		REQUIRE(meshbuf->Transformation == scale);
 | 
			
		||||
		check_cube_vertices(meshbuf);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SECTION("vertex indices are correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getIndexCount() == 36);
 | 
			
		||||
		REQUIRE(meshbuf->getIndexCount() == 36);
 | 
			
		||||
		auto indices = static_cast<const irr::u16 *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getIndices());
 | 
			
		||||
				meshbuf->getIndices());
 | 
			
		||||
		CHECK(indices[0] == 16);
 | 
			
		||||
		CHECK(indices[1] == 5);
 | 
			
		||||
		CHECK(indices[2] == 22);
 | 
			
		||||
@@ -123,9 +133,9 @@ SECTION("blender cube") {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SECTION("vertex normals are correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getVertexCount() == 24);
 | 
			
		||||
		REQUIRE(meshbuf->getVertexCount() == 24);
 | 
			
		||||
		auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getVertices());
 | 
			
		||||
				meshbuf->getVertices());
 | 
			
		||||
		CHECK(vertices[0].Normal == v3f{-1.0f, 0.0f, 0.0f});
 | 
			
		||||
		CHECK(vertices[1].Normal == v3f{0.0f, -1.0f, 0.0f});
 | 
			
		||||
		CHECK(vertices[2].Normal == v3f{0.0f, 0.0f, -1.0f});
 | 
			
		||||
@@ -136,9 +146,9 @@ SECTION("blender cube") {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SECTION("texture coords are correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getVertexCount() == 24);
 | 
			
		||||
		REQUIRE(meshbuf->getVertexCount() == 24);
 | 
			
		||||
		auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getVertices());
 | 
			
		||||
				meshbuf->getVertices());
 | 
			
		||||
		CHECK(vertices[0].TCoords == v2f{0.375f, 1.0f});
 | 
			
		||||
		CHECK(vertices[1].TCoords == v2f{0.125f, 0.25f});
 | 
			
		||||
		CHECK(vertices[2].TCoords == v2f{0.375f, 0.0f});
 | 
			
		||||
@@ -151,20 +161,15 @@ SECTION("blender cube scaled") {
 | 
			
		||||
	const auto mesh = loadMesh(model_stem + "blender_cube_scaled.gltf");
 | 
			
		||||
	REQUIRE(mesh);
 | 
			
		||||
	REQUIRE(mesh->getMeshBufferCount() == 1);
 | 
			
		||||
	auto *meshbuf = dynamic_cast<irr::scene::SSkinMeshBuffer *>(
 | 
			
		||||
			mesh->getMeshBuffer(0));
 | 
			
		||||
	REQUIRE(meshbuf);
 | 
			
		||||
 | 
			
		||||
	SECTION("Scaling is correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getVertexCount() == 24);
 | 
			
		||||
		auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getVertices());
 | 
			
		||||
 | 
			
		||||
		CHECK(vertices[0].Pos == v3f{-150.0f, -1.0f, -21.5f});
 | 
			
		||||
		CHECK(vertices[3].Pos == v3f{-150.0f, 1.0f, -21.5f});
 | 
			
		||||
		CHECK(vertices[6].Pos == v3f{-150.0f, -1.0f, 21.5f});
 | 
			
		||||
		CHECK(vertices[9].Pos == v3f{-150.0f, 1.0f, 21.5f});
 | 
			
		||||
		CHECK(vertices[12].Pos == v3f{150.0f, -1.0f, -21.5f});
 | 
			
		||||
		CHECK(vertices[15].Pos == v3f{150.0f, 1.0f, -21.5f});
 | 
			
		||||
		CHECK(vertices[18].Pos == v3f{150.0f, -1.0f, 21.5f});
 | 
			
		||||
		CHECK(vertices[21].Pos == v3f{150.0f, 1.0f, 21.5f});
 | 
			
		||||
		core::matrix4 scale;
 | 
			
		||||
		scale.setScale(v3f{150.0f, 1.0f, 21.5f});
 | 
			
		||||
		REQUIRE(meshbuf->Transformation == scale);
 | 
			
		||||
		check_cube_vertices(meshbuf);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -174,14 +179,17 @@ SECTION("blender cube matrix transform") {
 | 
			
		||||
	REQUIRE(mesh->getMeshBufferCount() == 1);
 | 
			
		||||
 | 
			
		||||
	SECTION("Transformation is correct") {
 | 
			
		||||
		REQUIRE(mesh->getMeshBuffer(0)->getVertexCount() == 24);
 | 
			
		||||
		auto *meshbuf = dynamic_cast<irr::scene::SSkinMeshBuffer *>(
 | 
			
		||||
				mesh->getMeshBuffer(0));
 | 
			
		||||
		REQUIRE(meshbuf);
 | 
			
		||||
		REQUIRE(meshbuf->getVertexCount() == 24);
 | 
			
		||||
		auto vertices = static_cast<const irr::video::S3DVertex *>(
 | 
			
		||||
				mesh->getMeshBuffer(0)->getVertices());
 | 
			
		||||
				meshbuf->getVertices());
 | 
			
		||||
		const auto checkVertex = [&](const std::size_t i, v3f vec) {
 | 
			
		||||
			// The transform scales by (1, 2, 3) and translates by (4, 5, 6).
 | 
			
		||||
			CHECK(vertices[i].Pos == vec * v3f{1, 2, 3}
 | 
			
		||||
					// The -6 is due to the coordinate system conversion.
 | 
			
		||||
					+ v3f{4, 5, -6});
 | 
			
		||||
			// The -6 is due to the coordinate system conversion.
 | 
			
		||||
			CHECK(meshbuf->Transformation.transformVect(vertices[i].Pos)
 | 
			
		||||
					== vec * v3f{1, 2, 3} + v3f{4, 5, -6});
 | 
			
		||||
		};
 | 
			
		||||
		checkVertex(0, v3f{-1, -1, -1});
 | 
			
		||||
		checkVertex(3, v3f{-1, 1, -1});
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user