use of net.drewke.tdme.engine.model.JointWeight in project tdme by andreasdr.
the class TMReader method readSkinning.
/**
* Read skinning from input stream
* @param input stream
* @param group
* @throws IOException
*/
private static void readSkinning(InputStream is, Group g) throws IOException, ModelFileIOException {
if (readBoolean(is) == true) {
Skinning skinning = g.createSkinning();
skinning.setWeights(readFloatArray(is));
Joint[] joints = new Joint[readInt(is)];
for (int i = 0; i < joints.length; i++) {
joints[i] = readSkinningJoint(is);
}
skinning.setJoints(joints);
JointWeight[][] verticesJointsWeight = new JointWeight[readInt(is)][];
for (int i = 0; i < verticesJointsWeight.length; i++) {
verticesJointsWeight[i] = new JointWeight[readInt(is)];
for (int j = 0; j < verticesJointsWeight[i].length; j++) {
verticesJointsWeight[i][j] = readSkinningJointWeight(is);
}
}
skinning.setVerticesJointsWeights(verticesJointsWeight);
}
}
use of net.drewke.tdme.engine.model.JointWeight in project tdme by andreasdr.
the class Object3DGroupMesh method createMesh.
/**
* Creates a object3d group mesh from group
* @param animation processing target
* @param group
* @param transformationm matrices
* @return object 3d group mesh
*/
protected static Object3DGroupMesh createMesh(Engine.AnimationProcessingTarget animationProcessingTarget, Group group, HashMap<String, Matrix4x4> transformationMatrices) {
Object3DGroupMesh mesh = new Object3DGroupMesh();
// group data
Vector3[] groupVertices = group.getVertices();
Vector3[] groupNormals = group.getNormals();
TextureCoordinate[] groupTextureCoordinates = group.getTextureCoordinates();
Vector3[] groupTangents = group.getTangents();
Vector3[] groupBitangents = group.getBitangents();
// determine face count
int faceCount = group.getFaceCount();
// set up face count
mesh.faces = faceCount;
// animation processing target
mesh.animationProcessingTarget = animationProcessingTarget;
// transformations for skinned meshes
Skinning skinning = group.getSkinning();
mesh.skinning = skinning != null;
// transformed mesh vertices
mesh.transformedVertices = new Vector3[groupVertices.length];
for (int j = 0; j < mesh.transformedVertices.length; j++) {
mesh.transformedVertices[j] = new Vector3().set(groupVertices[j]);
}
// transformed mesh normals
mesh.transformedNormals = new Vector3[groupNormals.length];
for (int j = 0; j < mesh.transformedNormals.length; j++) {
mesh.transformedNormals[j] = new Vector3().set(groupNormals[j]);
}
// texture coordinates
if (groupTextureCoordinates != null) {
mesh.textureCoordinates = new TextureCoordinate[groupTextureCoordinates.length];
for (int j = 0; j < mesh.textureCoordinates.length; j++) {
mesh.textureCoordinates[j] = new TextureCoordinate(groupTextureCoordinates[j]);
}
}
// transformed mesh tangents
if (groupTangents != null) {
mesh.transformedTangents = new Vector3[groupTangents.length];
for (int j = 0; j < mesh.transformedTangents.length; j++) {
mesh.transformedTangents[j] = new Vector3().set(groupTangents[j]);
}
}
// transformed mesh bitangents
if (groupBitangents != null) {
mesh.transformedBitangents = new Vector3[groupBitangents.length];
for (int j = 0; j < mesh.transformedBitangents.length; j++) {
mesh.transformedBitangents[j] = new Vector3().set(groupBitangents[j]);
}
}
// indices
int indicesCount = 0;
for (FacesEntity facesEntity : group.getFacesEntities()) {
indicesCount += 3 * facesEntity.getFaces().length;
}
mesh.indices = new short[indicesCount];
{
int j = 0;
// create face vertex indices
for (FacesEntity facesEntity : group.getFacesEntities()) for (Face face : facesEntity.getFaces()) for (int vertexIndex : face.getVertexIndices()) {
mesh.indices[j++] = (short) vertexIndex;
}
}
//
mesh.recreatedBuffers = false;
// create mesh upload buffers
if (mesh.animationProcessingTarget != Engine.AnimationProcessingTarget.CPU_NORENDERING) {
mesh.sbIndices = ByteBuffer.allocateDirect(mesh.faces * 3 * Short.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asShortBuffer();
mesh.fbVertices = ByteBuffer.allocateDirect(groupVertices.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.fbNormals = ByteBuffer.allocateDirect(groupNormals.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.fbTextureCoordinates = groupTextureCoordinates != null ? ByteBuffer.allocateDirect(groupTextureCoordinates.length * 2 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
mesh.fbTangents = groupTangents != null ? ByteBuffer.allocateDirect(groupTangents.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
mesh.fbBitangents = groupBitangents != null ? ByteBuffer.allocateDirect(groupBitangents.length * 3 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer() : null;
// create face vertex indices, will never be changed in engine
for (FacesEntity facesEntity : group.getFacesEntities()) for (Face face : facesEntity.getFaces()) for (int vertexIndex : face.getVertexIndices()) {
mesh.sbIndices.put((short) vertexIndex);
}
mesh.sbIndices.flip();
// create texture coordinates buffer, will never be changed in engine
if (mesh.fbTextureCoordinates != null) {
// construct texture coordinates byte buffer as this will not change usually
for (TextureCoordinate textureCoordinate : groupTextureCoordinates) {
mesh.fbTextureCoordinates.put(textureCoordinate.getArray());
}
mesh.fbTextureCoordinates.flip();
}
}
// group transformations matrix
if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU || mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
// group transformations matrix
mesh.cGroupTransformationsMatrix = transformationMatrices.get(group.getId());
}
// skinning
if (skinning != null) {
// skinning computation caches if computing skinning on CPU
if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU || mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.CPU_NORENDERING) {
mesh.cSkinningJointWeight = new float[groupVertices.length][];
mesh.cSkinningJointBindMatrices = new Matrix4x4[groupVertices.length][];
mesh.cSkinningJointTransformationsMatrices = new Matrix4x4[groupVertices.length][];
mesh.cTransformationsMatrix = new Matrix4x4();
// compute joint weight caches
Joint[] joints = skinning.getJoints();
float[] weights = skinning.getWeights();
JointWeight[][] jointsWeights = skinning.getVerticesJointsWeights();
for (int vertexIndex = 0; vertexIndex < groupVertices.length; vertexIndex++) {
int vertexJointWeights = jointsWeights[vertexIndex].length;
if (vertexJointWeights > mesh.cSkinningMaxVertexWeights)
mesh.cSkinningMaxVertexWeights = vertexJointWeights;
mesh.cSkinningJointWeight[vertexIndex] = new float[vertexJointWeights];
mesh.cSkinningJointBindMatrices[vertexIndex] = new Matrix4x4[vertexJointWeights];
mesh.cSkinningJointTransformationsMatrices[vertexIndex] = new Matrix4x4[vertexJointWeights];
int jointWeightIdx = 0;
for (JointWeight jointWeight : jointsWeights[vertexIndex]) {
Joint joint = joints[jointWeight.getJointIndex()];
//
mesh.cSkinningJointWeight[vertexIndex][jointWeightIdx] = weights[jointWeight.getWeightIndex()];
mesh.cSkinningJointBindMatrices[vertexIndex][jointWeightIdx] = joint.getBindMatrix();
mesh.cSkinningJointTransformationsMatrices[vertexIndex][jointWeightIdx] = transformationMatrices.get(joint.getGroupId());
// next
jointWeightIdx++;
}
}
} else // GPU setup
if (mesh.animationProcessingTarget == Engine.AnimationProcessingTarget.GPU) {
// create skinning buffers
mesh.gIbSkinningVerticesJoints = ByteBuffer.allocateDirect(groupVertices.length * 1 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.gFbSkinningVerticesVertexJointsIdxs = ByteBuffer.allocateDirect(groupVertices.length * 4 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.gFbSkinningVerticesVertexJointsWeights = ByteBuffer.allocateDirect(groupVertices.length * 4 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.gFbSkinningJointsTransformationsMatrices = ByteBuffer.allocateDirect(60 * 16 * Float.SIZE / Byte.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
mesh.gFbSkinningTransformationMatrix = new Matrix4x4();
// fill skinning buffers, joint bind matrices
mesh.skinningJoints = skinning.getJoints().length;
mesh.gSkinningJointBindMatrices = new ArrayList<Matrix4x4>();
for (Joint joint : skinning.getJoints()) {
mesh.gSkinningJointBindMatrices.add(joint.getBindMatrix());
}
//
JointWeight[][] jointsWeights = skinning.getVerticesJointsWeights();
float[] weights = skinning.getWeights();
for (int groupVertexIndex = 0; groupVertexIndex < groupVertices.length; groupVertexIndex++) {
int vertexJoints = jointsWeights[groupVertexIndex].length;
// put number of joints
mesh.gIbSkinningVerticesJoints.put((float) vertexJoints);
// vertex joint idx 1..4
for (int i = 0; i < 4; i++) {
mesh.gFbSkinningVerticesVertexJointsIdxs.put((float) (vertexJoints > i ? jointsWeights[groupVertexIndex][i].getJointIndex() : -1));
}
// vertex joint weight 1..4
for (int i = 0; i < 4; i++) {
mesh.gFbSkinningVerticesVertexJointsWeights.put(vertexJoints > i ? weights[jointsWeights[groupVertexIndex][i].getWeightIndex()] : 0.0f);
}
}
// put number of joints
mesh.gIbSkinningVerticesJoints.flip();
// vertex joint idx 1..4
mesh.gFbSkinningVerticesVertexJointsIdxs.flip();
// vertex joint weight 1..4
mesh.gFbSkinningVerticesVertexJointsWeights.flip();
}
}
// temp vector3
mesh.tmpVector3 = new Vector3();
// issue a recreate buffer and upload to graphics board
mesh.recreateBuffers(group);
//
return mesh;
}
use of net.drewke.tdme.engine.model.JointWeight in project tdme by andreasdr.
the class DAEReader method readVisualSceneInstanceController.
/**
* Reads a instance controller
* @param authoring tool
* @param path name
* @param model
* @param parent group
* @param xml root
* @param xml node
* @return Group
* @throws Exception
*/
private static Group readVisualSceneInstanceController(AuthoringTool authoringTool, String pathName, Model model, Group parentGroup, Element xmlRoot, Element xmlNode) throws Exception {
StringTokenizer t;
String xmlNodeId = xmlNode.getAttribute("id");
String xmlNodeName = xmlNode.getAttribute("name");
HashMap<String, String> materialSymbols = new HashMap<String, String>();
// geometry id
String xmlGeometryId = null;
// parse library controllers, find our controller
List<Element> xmlInstanceControllers = getChildrenByTagName(xmlNode, "instance_controller");
Element xmlSkin = null;
Element xmlInstanceController = xmlInstanceControllers.get(0);
// parse material symbols
for (Element xmlBindMaterial : getChildrenByTagName(xmlInstanceController, "bind_material")) for (Element xmlTechniqueCommon : getChildrenByTagName(xmlBindMaterial, "technique_common")) for (Element xmlInstanceMaterial : getChildrenByTagName(xmlTechniqueCommon, "instance_material")) {
materialSymbols.put(xmlInstanceMaterial.getAttribute("symbol"), xmlInstanceMaterial.getAttribute("target"));
}
String xmlInstanceControllerId = xmlInstanceController.getAttribute("url").substring(1);
Element xmlLibraryControllers = getChildrenByTagName(xmlRoot, "library_controllers").get(0);
for (Element xmlLibraryController : getChildrenByTagName(xmlLibraryControllers, "controller")) {
// our controller ?
if (xmlLibraryController.getAttribute("id").equals(xmlInstanceControllerId)) {
// parse skin
List<Element> xmlSkins = getChildrenByTagName(xmlLibraryController, "skin");
if (xmlSkins.isEmpty() == false) {
xmlSkin = xmlSkins.get(0);
}
}
}
// check for xml skin
if (xmlSkin == null) {
throw new ModelFileIOException("skin not found for instance controller " + xmlNodeId);
}
// get geometry id
xmlGeometryId = xmlSkin.getAttribute("source").substring(1);
// parse bind shape matrix
String xmlMatrix = getChildrenByTagName(xmlSkin, "bind_shape_matrix").get(0).getTextContent();
t = new StringTokenizer(xmlMatrix, " \n\r");
//
Matrix4x4 bindShapeMatrix = new Matrix4x4(Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken())).transpose();
// tdme model definitions
Group group = new Group(model, parentGroup, xmlNodeId, xmlNodeName);
// create skinning
Skinning skinning = group.createSkinning();
// parse geometry
readGeometry(authoringTool, pathName, model, group, xmlRoot, xmlGeometryId, materialSymbols);
// parse joints
String xmlJointsSource = null;
String xmlJointsInverseBindMatricesSource = null;
Element xmlJoints = getChildrenByTagName(xmlSkin, "joints").get(0);
for (Element xmlJointsInput : getChildrenByTagName(xmlJoints, "input")) {
if (xmlJointsInput.getAttribute("semantic").equals("JOINT")) {
xmlJointsSource = xmlJointsInput.getAttribute("source").substring(1);
} else if (xmlJointsInput.getAttribute("semantic").equals("INV_BIND_MATRIX")) {
xmlJointsInverseBindMatricesSource = xmlJointsInput.getAttribute("source").substring(1);
}
}
// check for joints sources
if (xmlJointsSource == null) {
throw new ModelFileIOException("joint source not found for instance controller " + xmlNodeId);
}
// parse joint ids
ArrayList<Joint> joints = new ArrayList<Joint>();
for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
if (xmlSkinSource.getAttribute("id").equals(xmlJointsSource)) {
t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "Name_array").get(0).getTextContent(), " \n\r");
while (t.hasMoreTokens()) {
joints.add(new Joint(t.nextToken()));
}
}
}
skinning.setJoints(joints);
// check for inverse bind matrices source
if (xmlJointsInverseBindMatricesSource == null) {
throw new ModelFileIOException("inverse bind matrices source not found for instance controller " + xmlNodeId);
}
// Create joints bind matrices
for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
if (xmlSkinSource.getAttribute("id").equals(xmlJointsInverseBindMatricesSource)) {
t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "float_array").get(0).getTextContent(), " \n\r");
Joint[] _joints = skinning.getJoints();
for (int i = 0; i < _joints.length; i++) {
_joints[i].getBindMatrix().multiply(bindShapeMatrix);
_joints[i].getBindMatrix().multiply(// The transformation to the local space of the joint is called the inverse bind matrix
new Matrix4x4(Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken()), Float.parseFloat(t.nextToken())).transpose());
}
}
}
// read vertex influences
ArrayList<Float> weights = new ArrayList<Float>();
int xmlJointOffset = -1;
int xmlWeightOffset = -1;
String xmlWeightsSource = null;
Element xmlVertexWeights = getChildrenByTagName(xmlSkin, "vertex_weights").get(0);
List<Element> xmlVertexWeightInputs = getChildrenByTagName(xmlVertexWeights, "input");
for (Element xmlVertexWeightInput : xmlVertexWeightInputs) {
if (xmlVertexWeightInput.getAttribute("semantic").equals("JOINT")) {
if (xmlVertexWeightInput.getAttribute("source").substring(1).equals(xmlJointsSource) == false) {
throw new ModelFileIOException("joint inverse bind matrices source do not match");
}
xmlJointOffset = Integer.parseInt(xmlVertexWeightInput.getAttribute("offset"));
} else if (xmlVertexWeightInput.getAttribute("semantic").equals("WEIGHT")) {
xmlWeightOffset = Integer.parseInt(xmlVertexWeightInput.getAttribute("offset"));
xmlWeightsSource = xmlVertexWeightInput.getAttribute("source").substring(1);
}
}
// check for vertex weight parameter
if (xmlJointOffset == -1) {
throw new ModelFileIOException("xml vertex weight joint offset missing for node " + xmlNodeId);
}
if (xmlWeightOffset == -1) {
throw new ModelFileIOException("xml vertex weight weight offset missing for node " + xmlNodeId);
}
if (xmlWeightsSource == null) {
throw new ModelFileIOException("xml vertex weight weight source missing for node " + xmlNodeId);
}
// parse weights
for (Element xmlSkinSource : getChildrenByTagName(xmlSkin, "source")) {
if (xmlSkinSource.getAttribute("id").equals(xmlWeightsSource)) {
t = new StringTokenizer(getChildrenByTagName(xmlSkinSource, "float_array").get(0).getTextContent(), " \n\r");
while (t.hasMoreTokens()) {
weights.add(new Float(Float.parseFloat(t.nextToken())));
}
}
}
skinning.setWeights(weights);
// actually do parse joint influences of each vertex
int xmlVertexWeightInputCount = xmlVertexWeightInputs.size();
String vertexJointsInfluenceCountString = getChildrenByTagName(xmlVertexWeights, "vcount").get(0).getTextContent();
String vertexJointsInfluencesString = getChildrenByTagName(xmlVertexWeights, "v").get(0).getTextContent();
t = new StringTokenizer(vertexJointsInfluenceCountString, " \n\r");
StringTokenizer t2 = new StringTokenizer(vertexJointsInfluencesString, " \n\r");
int offset = 0;
ArrayList<ArrayList<JointWeight>> verticesJointsWeights = new ArrayList<ArrayList<JointWeight>>();
while (t.hasMoreTokens()) {
// read joint influences for current vertex
int vertexJointsInfluencesCount = Integer.parseInt(t.nextToken());
ArrayList<JointWeight> vertexJointsWeights = new ArrayList<JointWeight>();
for (int i = 0; i < vertexJointsInfluencesCount; i++) {
int vertexJoint = -1;
int vertexWeight = -1;
while (vertexJoint == -1 || vertexWeight == -1) {
int value = Integer.parseInt(t2.nextToken());
if (offset % xmlVertexWeightInputCount == xmlJointOffset) {
vertexJoint = value;
} else if (offset % xmlVertexWeightInputCount == xmlWeightOffset) {
vertexWeight = value;
}
offset++;
}
vertexJointsWeights.add(new JointWeight(vertexJoint, vertexWeight));
}
verticesJointsWeights.add(vertexJointsWeights);
}
skinning.setVerticesJointsWeights(verticesJointsWeights);
return group;
}
Aggregations