最近我一直试图为我的引擎创建一个骨架动画系统,但没有成功......
在互联网上关注了几个教程之后,我设法让一些工作变得有效,但是"""非常奇怪地... It's supposed to be a full worm
这应该是一个完整的蠕虫病毒,但只有它的起点才能得到。
以下是代码:
Mesh _ret_mesh = null;
try {
byte[] _data = IOUtils.toByteArray(stream);
ByteBuffer data = BufferUtils.createByteBuffer(_data.length);
data.put(_data);
data.flip();
AIScene scene = Assimp.aiImportFileFromMemory(
data, ...
);
...
PointerBuffer meshes = scene.mMeshes();
_ret_mesh = new Mesh();
AIMesh mesh = AIMesh.create(meshes.get(0));
for (int f = 0; f < mesh.mNumFaces(); f++) {
AIFace face = mesh.mFaces().get(f);
for (int j = 0; j < 3; j++) {
int index = face.mIndices().get(j);
AIColor4D color = null;
AIVector3D norm = null;
AIVector3D tex = null;
AIVector3D pos = mesh.mVertices().get(index);
Color mcolor = new Color(1, 1, 1);
Vec3 mnorm = new Vec3(0, 0, 1);
Vec2 mtex = new Vec2(0, 0);
if (mesh.mNormals() != null) {
norm = mesh.mNormals().get(index);
mnorm.set(norm.x(), norm.y(), norm.z());
}
if (mesh.mTextureCoords(0) != null) {
tex = mesh.mTextureCoords(0).get(index);
mtex.set(tex.x(), tex.y());
}
if (mesh.mColors(0) != null) {
color = mesh.mColors(0).get();
mcolor.set(color.r(), color.g(), color.b(), color.a());
}
Vertex vert = new Vertex();
vert.position = new Vec3(pos.x(), pos.y(), pos.z());
vert.normal = mnorm;
vert.texCoord = mtex;
vert.color = mcolor;
_ret_mesh.pushVertex(vert);
_ret_mesh.pushIndex(index);
}
}
if (mesh.mNumBones() > 0) {
// Loads bone ids and weights
loadBones(mesh, _ret_mesh);
loadSkeleton(scene, _ret_mesh);
}
_ret_mesh.finalize();
_ret_mesh.setSkeleton(skeleton);
} catch (IOException e) {
e.printStackTrace();
}
return _ret_mesh;
}
private void loadSkeleton(AIScene scene, Mesh mesh) {
skeleton = new Skeleton();
skeleton.setInverseGlobalTransform(Mat4.assimp(scene.mRootNode().mTransformation()).invert());
AINode root = findRootBone(scene.mRootNode());
buildSkeleton(root, null);
}
private void buildSkeleton(AINode current, Bone parent) {
String boneName = current.mName().dataString();
if (bone_names.contains(boneName)) {
int bone_id = bone_name_map.get(boneName);
Mat4 bone_trans = bind_pose_map.get(bone_id);
Bone bone = new Bone(bone_id, bone_trans);
Transform bone_t = new Transform(Mat4.assimp(current.mTransformation()).transpose());
bone.setTransform(bone_t);
if (parent == null) {
skeleton.root = bone;
} else {
parent.addChild(bone);
}
PointerBuffer children = current.mChildren();
for (int i = 0; i < children.remaining(); i++) {
buildSkeleton(AINode.create(children.get(i)), bone);
}
}
}
private AINode findRootBone(AINode node) {
String boneName = node.mName().dataString();
if (bone_names.contains(boneName)) {
return node;
}
AINode result = null;
for (int i = 0; i < node.mNumChildren(); i++) {
result = findRootBone(new AINode(node.mChildren().getByteBuffer(i, 1288)));
if (result != null) {
return result;
}
}
return null;
}
private void loadBones(AIMesh mesh, Mesh retmesh) {
if (mesh.mNumBones() > 0) {
int numBones = 0;
PointerBuffer bones = mesh.mBones();
for (int k = 0; k < bones.remaining(); k++) {
int bone_id = 0;
AIBone bone = AIBone.create(bones.get(k));
String bone_name = bone.mName().dataString();
if (!bone_name_map.containsKey(bone_name)) {
bone_id = numBones;
numBones++;
bone_name_map.put(bone_name, bone_id);
bone_names.add(bone_name);
bind_pose_map.put(bone_id, Mat4.assimp(bone.mOffsetMatrix()).transpose());
} else {
bone_id = bone_name_map.get(bone_name);
bone_name_map.replace(bone_name, bone_id);
bind_pose_map.replace(bone_id, Mat4.assimp(bone.mOffsetMatrix()).transpose());
}
for (int j = 0; j < bone.mNumWeights(); j++) {
int vid = bone.mWeights().get(j).mVertexId();
float weight = bone.mWeights().get(j).mWeight();
for (int i = 0; i < WEIGHTS_PER_VERTEX; i++) {
Vertex vert = retmesh.getVertices().get(vid);
if (vert.weights.get(i) == 0.0f) {
vert.weights.set(i, weight);
vert.ids.set(i, bone_id);
break;
}
}
}
}
}
}
这是骨架更新方法:
private void readHierarchy(Bone bone, Mat4 parentTransform) {
Mat4 boneTransform = bone.getTransform().getTransformation();
Mat4 globalTransform = parentTransform.mul(boneTransform);
bone.worldTransform = globalTransform;
bone.skinnedTransform = inverseGlobalTransform.mul(globalTransform).mul(bone.bindPose);
for (Bone c : bone.getChildren()) {
readHierarchy(c, globalTransform);
}
}
public void update() {
ArrayList<Bone> bones = getBones();
matrixMap.clear();
int i = 0;
while (matrixMap.size() < bones.size()) {
matrixMap.put(bones.get(i).id, Mat4.identity());
i++;
}
readHierarchy(root, Mat4.identity());
for (Bone bone : bones) {
matrixMap.replace(bone.id, bone.skinnedTransform);
}
}
顶点着色器
#version 330
const int MAX_BONES = 64;
const int MAX_WEIGHTS = 4;
layout (location = 0) in vec3 v_position;
layout (location = 1) in vec3 v_normal;
layout (location = 2) in vec2 v_texco;
layout (location = 3) in vec4 v_color;
layout (location = 4) in vec4 v_bone_weights;
layout (location = 5) in vec4 v_bone_ids;
out DATA {
vec3 normal;
vec4 position;
vec4 color;
vec2 uv;
} vs_out;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 normalMatrix;
uniform mat4 modelMatrix;
uniform bool hasBones;
uniform mat4 bones[MAX_BONES];
void main() {
// Bones and Skinning
vec4 skinned_vertex = vec4(0.0);
vec4 skinned_normal = vec4(0.0);
if (hasBones) {
for (int i = 0; i < MAX_WEIGHTS; i++) {
vec4 local_position = bones[int(v_bone_ids[i])] * vec4(v_position, 1.0);
skinned_vertex += local_position * v_bone_weights[i];
vec4 world_normal = bones[int(v_bone_ids[i])] * vec4(v_normal, 0.0);
skinned_normal += world_normal * v_bone_weights[i];
}
} else {
skinned_vertex = vec4(v_position, 1.0);
skinned_normal = vec4(v_normal, 0.0);
}
//
vec4 _position = modelViewMatrix * skinned_vertex;
gl_Position = projectionMatrix * _position;
vs_out.position = modelMatrix * skinned_vertex;
vs_out.normal = (normalMatrix * skinned_normal).xyz;
vs_out.color = v_color;
vs_out.uv = v_texco;
}
我无法找到问题,我尝试了很多东西,已经过了5天。