void bake_mesh_skin(const struct aiMesh *mesh) { int i, k, b; struct aiMatrix3x3 mat3; struct aiMatrix4x4 bonemat[1000], mat; struct aiVector3D *outpos, *outnorm; if (mesh->mNumBones == 0) return; outpos = malloc(mesh->mNumVertices * sizeof *outpos); outnorm = malloc(mesh->mNumVertices * sizeof *outnorm); memset(outpos, 0, mesh->mNumVertices * sizeof *outpos); memset(outnorm, 0, mesh->mNumVertices * sizeof *outpos); calc_abs_pose(); for (i = 0; i < mesh->mNumBones; i++) { b = find_bone(mesh->mBones[i]->mName.data); bonemat[i] = bonelist[b].abspose; aiMultiplyMatrix4(&bonemat[i], &mesh->mBones[i]->mOffsetMatrix); } for (k = 0; k < mesh->mNumBones; k++) { struct aiBone *bone = mesh->mBones[k]; b = find_bone(mesh->mBones[k]->mName.data); mat = bonemat[k]; mat3.a1 = mat.a1; mat3.a2 = mat.a2; mat3.a3 = mat.a3; mat3.b1 = mat.b1; mat3.b2 = mat.b2; mat3.b3 = mat.b3; mat3.c1 = mat.c1; mat3.c2 = mat.c2; mat3.c3 = mat.c3; for (i = 0; i < bone->mNumWeights; i++) { struct aiVertexWeight vw = bone->mWeights[i]; int v = vw.mVertexId; float w = vw.mWeight; struct aiVector3D srcpos = mesh->mVertices[v]; struct aiVector3D srcnorm = mesh->mNormals[v]; aiTransformVecByMatrix4(&srcpos, &mat); aiTransformVecByMatrix3(&srcnorm, &mat3); outpos[v].x += srcpos.x * w; outpos[v].y += srcpos.y * w; outpos[v].z += srcpos.z * w; outnorm[v].x += srcnorm.x * w; outnorm[v].y += srcnorm.y * w; outnorm[v].z += srcnorm.z * w; } } memcpy(mesh->mVertices, outpos, mesh->mNumVertices * sizeof *outpos); memcpy(mesh->mNormals, outnorm, mesh->mNumVertices * sizeof *outnorm); free(outpos); free(outnorm); }
void mark_skinned_bones(const struct aiScene *scene) { int i, k, a, b; for (i = 0; i < numbones; i++) { struct aiNode *node = bonelist[i].node; if (only_one_node && strcmp(bonelist[i].clean_name, only_one_node)) continue; for (k = 0; k < node->mNumMeshes; k++) { struct aiMesh *mesh = scene->mMeshes[node->mMeshes[k]]; for (a = 0; a < mesh->mNumBones; a++) { b = find_bone(mesh->mBones[a]->mName.data); if (!bonelist[b].isbone) { bonelist[b].reason = "skinned"; bonelist[b].invpose = mesh->mBones[a]->mOffsetMatrix; bonelist[b].isbone = 1; bonelist[b].isskin = 1; } else if (!need_to_bake_skin) { if (memcmp(&bonelist[b].invpose, &mesh->mBones[a]->mOffsetMatrix, sizeof bonelist[b].invpose)) need_to_bake_skin = 1; } } } } }
void mark_animated_bones(const struct aiScene *scene) { int i, k, b; for (i = 0; i < scene->mNumAnimations; i++) { const struct aiAnimation *anim = scene->mAnimations[i]; for (k = 0; k < anim->mNumChannels; k++) { b = find_bone(anim->mChannels[k]->mNodeName.data); bonelist[b].reason = "animated"; bonelist[b].isbone = 1; } } }
void Skeleton::physical_bones_start_simulation_on(const Array &p_bones) { Vector<int> sim_bones; if (p_bones.size() <= 0) { sim_bones.push_back(0); // if no bones is specified, activate ragdoll on full body } else { sim_bones.resize(p_bones.size()); int c = 0; for (int i = sim_bones.size() - 1; 0 <= i; --i) { if (Variant::STRING == p_bones.get(i).get_type()) { int bone_id = find_bone(p_bones.get(i)); if (bone_id != -1) sim_bones.write[c++] = bone_id; } } sim_bones.resize(c); } _pb_start_simulation(this, this, sim_bones); }
void export_frame(FILE *out, const struct aiAnimation *anim, int frame) { int i; // start with fresh matrices apply_initial_frame(); for (i = 0; i < anim->mNumChannels; i++) { struct aiNodeAnim *chan = anim->mChannels[i]; int a = find_bone(chan->mNodeName.data); int tframe = MIN(frame, chan->mNumPositionKeys - 1); int rframe = MIN(frame, chan->mNumRotationKeys - 1); int sframe = MIN(frame, chan->mNumScalingKeys - 1); bonelist[a].translate = chan->mPositionKeys[tframe].mValue; bonelist[a].rotate = chan->mRotationKeys[rframe].mValue; bonelist[a].scale = chan->mScalingKeys[sframe].mValue; #ifdef HACK_MATRIX_KEY bonelist[a].pose = chan->mRotationKeys[rframe].mMatrixValue; #endif } #ifndef HACK_MATRIX_KEY // translate/rotate/scale have changed: recompute pose for (i = 0; i < numbones; i++) { if (bonelist[i].isbone) { // make sure we're not hit by precision issues in decomposematrix aiNormalizeQuaternion(&bonelist[i].rotate); aiComposeMatrix(&bonelist[i].pose, &bonelist[i].scale, &bonelist[i].rotate, &bonelist[i].translate); } } #endif fprintf(out, "\n"); fprintf(out, "frame %d\n", frame); export_pose(out); }
Bone_CPtr BoneHierarchy::bones(const std::string& name) const { return m_bones[find_bone(name)]; }
void export_node(FILE *out, const struct aiScene *scene, const struct aiNode *node, struct aiMatrix4x4 mat, char *clean_name) { struct aiMatrix3x3 mat3; int i, a, k, t; aiMultiplyMatrix4(&mat, &node->mTransformation); mat3.a1 = mat.a1; mat3.a2 = mat.a2; mat3.a3 = mat.a3; mat3.b1 = mat.b1; mat3.b2 = mat.b2; mat3.b3 = mat.b3; mat3.c1 = mat.c1; mat3.c2 = mat.c2; mat3.c3 = mat.c3; if (!strstr(node->mName.data, "$ColladaAutoName$")) clean_name = clean_node_name((char*)node->mName.data); if (only_one_node && strcmp(clean_name, only_one_node)) goto skip_mesh; for (i = 0; i < node->mNumMeshes; i++) { struct aiMesh *mesh = scene->mMeshes[node->mMeshes[i]]; struct aiMaterial *material = scene->mMaterials[mesh->mMaterialIndex]; if (mesh->mNumBones == 0 && dobone && !dorigid) { if (verbose) fprintf(stderr, "skipping rigid mesh %d in node %s (no bones)\n", i, clean_name); continue; } fprintf(stderr, "exporting mesh %s[%d]: %d vertices, %d faces\n", clean_name, i, mesh->mNumVertices, mesh->mNumFaces); fprintf(out, "\n"); fprintf(out, "mesh \"%s\"\n", clean_name); fprintf(out, "material \"%s\"\n", find_material(material)); struct vb *vb = (struct vb*) malloc(mesh->mNumVertices * sizeof(*vb)); memset(vb, 0, mesh->mNumVertices * sizeof(*vb)); // A rigidly animated node -- insert fake blend index/weights if (mesh->mNumBones == 0 && dobone) { a = find_bone((char*)node->mName.data); if (verbose) fprintf(stderr, "\trigid bone %d for mesh in node %s (no bones)\n", bonelist[a].number, node->mName.data); for (k = 0; k < mesh->mNumVertices; k++) { vb[k].b[0] = bonelist[a].number; vb[k].w[0] = 1; vb[k].n = 1; } } // Assemble blend index/weight array for (k = 0; k < mesh->mNumBones; k++) { struct aiBone *bone = mesh->mBones[k]; a = find_bone(bone->mName.data); for (t = 0; t < bone->mNumWeights; t++) { struct aiVertexWeight *w = mesh->mBones[k]->mWeights + t; int idx = w->mVertexId; if (vb[idx].n < MAXBLEND) { vb[idx].b[vb[idx].n] = bonelist[a].number; vb[idx].w[vb[idx].n] = w->mWeight; vb[idx].n++; } } } for (k = 0; k < mesh->mNumVertices; k++) { struct aiVector3D vp = mesh->mVertices[k]; if (!dobone) aiTransformVecByMatrix4(&vp, &mat); fprintf(out, "vp %.9g %.9g %.9g\n", vp.x, vp.y, vp.z); if (mesh->mNormals) { struct aiVector3D vn = mesh->mNormals[k]; if (!dobone) aiTransformVecByMatrix3(&vn, &mat3); fprintf(out, "vn %.9g %.9g %.9g\n", vn.x, vn.y, vn.z); } if (mesh->mTextureCoords[0]) { float u = mesh->mTextureCoords[0][k].x; float v = 1 - mesh->mTextureCoords[0][k].y; fprintf(out, "vt %.9g %.9g\n", u, v); } for (t = 1; t <= MAX_UVMAP; t++) { if (mesh->mTextureCoords[t]) { float u = mesh->mTextureCoords[t][k].x; float v = 1 - mesh->mTextureCoords[t][k].y; fprintf(out, "v%d %.9g %.9g\n", FIRST_UVMAP+t-1, u, v); } } if (mesh->mColors[0]) { float r = mesh->mColors[0][k].r; r = floorf(r * 255) / 255; float g = mesh->mColors[0][k].g; g = floorf(g * 255) / 255; float b = mesh->mColors[0][k].b; b = floorf(b * 255) / 255; float a = mesh->mColors[0][k].a; a = floorf(a * 255) / 255; fprintf(out, "vc %.9g %.9g %.9g %.9g\n", r, g, b, a); } for (t = 1; t <= MAX_COL; t++) { if (mesh->mColors[t]) { float r = mesh->mColors[t][k].r; r = floorf(r * 255) / 255; float g = mesh->mColors[t][k].g; g = floorf(g * 255) / 255; float b = mesh->mColors[t][k].b; b = floorf(b * 255) / 255; float a = mesh->mColors[t][k].a; a = floorf(a * 255) / 255; fprintf(out, "v%d %.9g %.9g %.9g %.9g\n", FIRST_COL+t-1, r, g, b, a); } } if (dobone) { fprintf(out, "vb"); for (t = 0; t < vb[k].n; t++) { fprintf(out, " %d %.9g", vb[k].b[t], vb[k].w[t]); } fprintf(out, "\n"); } } for (k = 0; k < mesh->mNumFaces; k++) { struct aiFace *face = mesh->mFaces + k; if (face->mNumIndices == 3) { if (doflip) fprintf(out, "fm %d %d %d\n", face->mIndices[2], face->mIndices[1], face->mIndices[0]); else fprintf(out, "fm %d %d %d\n", face->mIndices[0], face->mIndices[1], face->mIndices[2]); } else if (face->mNumIndices == 4) { if (doflip) fprintf(out, "fm %d %d %d %d\n", face->mIndices[3], face->mIndices[2], face->mIndices[1], face->mIndices[0]); else fprintf(out, "fm %d %d %d %d\n", face->mIndices[0], face->mIndices[1], face->mIndices[2], face->mIndices[3]); } else if (face->mNumIndices > 4) { fprintf(stderr, "n-gon (%d) in mesh!\n", face->mNumIndices); int i1 = face->mIndices[0]; int i2 = face->mIndices[1]; for (a = 2; a < face->mNumIndices; a++) { int i3 = face->mIndices[a]; if (doflip) fprintf(out, "fm %d %d %d\n", i3, i2, i1); else fprintf(out, "fm %d %d %d\n", i1, i2, i3); i2 = i3; } } else { fprintf(stderr, "skipping point/line primitive\n"); } } free(vb); } skip_mesh: for (i = 0; i < node->mNumChildren; i++) export_node(out, scene, node->mChildren[i], mat, clean_name); }