(Niefunkcjonujące) Macierze w anymacjach GLTF załądowanych przez fastgltf w C++

(Niefunkcjonujące) Macierze w anymacjach GLTF załądowanych przez fastgltf w C++

Wątek przeniesiony 2025-05-30 00:08 z C/C++ przez somekind.

MB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
1

Dzień dobry,

spróbowałem zaprogramować animację modelu w formacie GLTF i no nie działa to. Ale nie działa to w bardzo dziwny sposób - tylko na niektórych modelach i tak, że animacja ma poprawny kierunek i silę ale lokacja całej kości jest zła. Próbowałem zapytać znajomych, szt. "inteligencję", i na StackOverflow oraz innych forach, niestety bez sukcesu.

Przykładów dodam 2: tramwaj typu T3R.P, animacja pantografu funkcjonuje i jest w porządku, ale cały model jest przeniesiony na klika metrów w dól.
Drugi przykład to lis - pierwsze zdjęcie pokazuje modeł w oryginału (Fox.glb) a drugie (już funkcjonujące) pokazuje go po tym co ponownie wyeksportowałem go z Blender-a (FoxRE.glb).
Zdjęcia są w załączniku.

Link na repo z minimalnym kodem: GitHub / MegapolisPlayer / GLTFAnimationSample

Używam języka C++, ląduje model za pomocy fastgltf i używam też glm-a oraz GLFW.
Co dotyczy plików:
Shader i Texture na pewno funkcjonują, Mesh w zasadzie niczego nie robi, Animation testowałem - podejrzewam na część liczącą macierze w Model.cpp bo model się naładuje w porządku (w UI to widać jako "render base model").

Przepraszam za jakiekolwiek błędy gramatyczne, nie jestem z Polski ale próbuję się tego języka nauczyć i czasu od czasu to nawet spoko idzie. Oczywiście bardzo dziękuje za jakąkolwiek pomóc.

MB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
0

https://drive.google.com/file/d/17zj87iDwM2zWYP0Q41XCxmGlnpgz21bb/view?usp=sharing Link na własne wideo dobrze pokazujące problem. Najpewniej gdzieś źle coś liczę...

obscurity
  • Rejestracja: dni
  • Ostatnio: dni
1
Martin Bykov napisał(a):

nie działa to w bardzo dziwny sposób - tylko na niektórych modelach i tak, że animacja ma poprawny kierunek i silę ale lokacja całej kości jest zła.

Paaanie, kto ci będzie analizował taką ilość kodu. Jak nie potrafisz znaleźć błędu to napisz to od początku.
Skoro tylko na niektórych modelach to albo problem jest z modelem, być może nie są wycentrowane punkty odniesienia a ty nie bierzesz ich pod uwagę.
Daj konkret czym się różnią te modele. Może nie liczysz przesunięcia / obrotu względem nadrzędnej kości tylko względem świata.

Na filmiku to wygląda jakbyś liczył najpierw przesunięcie a potem obrót zamiast na odwrót i obrót masz względem środka świata zamiast środka modelu / kości.

Też nie rozumiem za bardzo - jeśli potrafisz debugować i sam napisałeś obliczenia to powinieneś być w stanie powiedzieć które wartości i w którym miejscu są złe. Wrzuć sobie prostszy model tak żebyś mógł śledzić wartości w głowie i jazda.

MB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
0

Animacje funkcjonują ale po prostu nie są tam gdzie być powinny, coś oznacza że problem jest gdzieś w skinning macierzach.
Shadery funkcjonują (są z tutorialu i nie ma tam nawet niczego co by się mogło popsuć), Textury też. Zalądowanie modelu też. (bind pose jest spoko)

Co dotyczy TRS, wiem że to na pewno liczę to w objektu Animation poprawnie, według specu jest gwarantowany układ T/R/S. (przesunięć, rotacji i skali).

Problem jest taki: prostsze modele funkcjonują, cięższe już nie. Wszystkie modele ale nie funkcjonują tylko w moim programu, w GLTF viewerach online funkcjonuje wszystko tak jak powinno. Z tego oczywiście płynie że problem jest na mojej stronie.
I oczywiście nie oczekuję że ktoś będzie tyle kodu kontrolować :), tak na serio problem jest gdzieś tutaj:

Kopiuj
glm::mat4 Model::getNodeMatrix(Node& node) {
	glm::mat4 nodeMatrix = node.hasAnimData ? node.localMatrix : node.transformMatrix;
	int64_t currentParent = node.parent;
	while (currentParent != -1) {
		if(this->mNodes[currentParent].hasAnimData) {
			nodeMatrix = this->mNodes[currentParent].localMatrix * nodeMatrix;
		}
		else {
			nodeMatrix = this->mNodes[currentParent].transformMatrix * nodeMatrix;
		}
		currentParent = this->mNodes[currentParent].parent;
	}
	return nodeMatrix;
}

void Model::updateJoints(Node& node, std::vector<glm::mat4>& aJointMatrices) {
	if (node.idOfSkin > -1) {
		glm::mat4              inverseTransform = glm::inverse(getNodeMatrix(node));
		Bone                   skin             = this->mBones[node.idOfSkin];
		size_t                 numJoints        = skin.joints.size();
		std::vector<glm::mat4> jointMatrices(numJoints);
		for (size_t i = 0; i < numJoints; i++) {
			jointMatrices[i] = inverseTransform * getNodeMatrix(this->mNodes[skin.joints[i]]) * skin.inverseBindMatrix[i];
		}

		aJointMatrices.insert(aJointMatrices.end(), jointMatrices.begin(), jointMatrices.end());
	}

	for(auto& child : node.children) updateJoints(this->mNodes[child], aJointMatrices);
}

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.