private void readAnimations() throws IOException { if (header.ofs_anims == readBytes) { for (int i = 0; i < header.num_anims; ++i) { byte[] buffer = new byte[ANIM_SIZE]; readBytes += in.read(buffer); int pos = 0; AnimationData animData = new AnimationData(); pos++; animData.name = texts.get(textPos++); int firstFrame = toInt(buffer, (pos++) * 4); int numFrames = toInt(buffer, (pos++) * 4); animData.animationFrames = new AnimationFrame[numFrames]; animData.frameRate = toFloat(buffer, (pos++) * 4); animData.flag = toInt(buffer, (pos++) * 4); entityData.skeletonData.animations.add(animData); } } if (header.ofs_frames == readBytes) { for (int i = 0; i < header.num_anims; ++i) { AnimationData animData = entityData.skeletonData.animations.get(i); byte[] buffer = new byte[2 * animData.animationFrames.length * header.num_framechannels]; readBytes += in.read(buffer); int pos = 0; float prevTime = 0; for (int j = 0; j < animData.animationFrames.length; ++j) { AnimationFrame frame = new AnimationFrame(header.num_joints); animData.animationFrames[j] = frame; frame.time = prevTime; prevTime += 1 / animData.frameRate; for (int k = 0; k < header.num_poses; ++k) { PoseData p = entityData.skeletonData.poses[k]; Vector3 translate = new Vector3(p.channeloffset[0], p.channeloffset[1], p.channeloffset[2]); if ((p.channelmask & 0x01) != 0) translate.x += toShort(buffer, (pos++) * 2) * p.channelscale[0]; if ((p.channelmask & 0x02) != 0) translate.y += toShort(buffer, (pos++) * 2) * p.channelscale[1]; if ((p.channelmask & 0x04) != 0) translate.z += toShort(buffer, (pos++) * 2) * p.channelscale[2]; Quaternion rotate = new Quaternion( p.channeloffset[3], p.channeloffset[4], p.channeloffset[5], p.channeloffset[6]); if ((p.channelmask & 0x08) != 0) rotate.x += toShort(buffer, (pos++) * 2) * p.channelscale[3]; if ((p.channelmask & 0x10) != 0) rotate.y += toShort(buffer, (pos++) * 2) * p.channelscale[4]; if ((p.channelmask & 0x20) != 0) rotate.z += toShort(buffer, (pos++) * 2) * p.channelscale[5]; if ((p.channelmask & 0x40) != 0) rotate.w += toShort(buffer, (pos++) * 2) * p.channelscale[6]; if ((p.channelmask & 0x80) != 0) pos++; if ((p.channelmask & 0x100) != 0) pos++; if ((p.channelmask & 0x200) != 0) pos++; frame.bonePos[k] = translate; frame.boneRot[k] = rotate; } } } } }
private void readVertices() throws IOException { for (int i = 0; i < header.num_vertexarrays; ++i) { VertexArray vertexArray = vertexArrays[i]; for (int j = 0; j < entityData.subEntities.length; ++j) { SubEntityData subEntity = entityData.subEntities[j]; // These are the vertices belonging to this subentity int componentSize = getVertexArrayComponentSize(vertexArray); byte[] buffer = new byte[subEntity.countVertices * vertexArray.size * componentSize]; readBytes += in.read(buffer); int pos = 0; int byteStride = vertexLayout.getByteStride(); int offset; switch (vertexArray.type) { case 0: // This is a position offset = vertexLayout.getPos(VertexLayout.POSITION); for (int k = 0; k < subEntity.countVertices; ++k) { subEntity.vertexData[k * byteStride + offset + 0] = toFloat(buffer, (pos++) * 4); subEntity.vertexData[k * byteStride + offset + 1] = toFloat(buffer, (pos++) * 4); subEntity.vertexData[k * byteStride + offset + 2] = toFloat(buffer, (pos++) * 4); } break; case 1: // This is a texture coordinate offset = vertexLayout.getPos(VertexLayout.UV); for (int k = 0; k < subEntity.countVertices; ++k) { subEntity.vertexData[k * byteStride + offset + 0] = toFloat(buffer, (pos++) * 4); subEntity.vertexData[k * byteStride + offset + 1] = toFloat(buffer, (pos++) * 4); } break; case 2: // This is a normal offset = vertexLayout.getPos(VertexLayout.NORMAL); for (int k = 0; k < subEntity.countVertices; ++k) { float x = toFloat(buffer, (pos++) * 4); float y = toFloat(buffer, (pos++) * 4); float z = toFloat(buffer, (pos++) * 4); if (light == null) { // Lighting information not baked into the mesh subEntity.vertexData[k * byteStride + offset + 0] = x; subEntity.vertexData[k * byteStride + offset + 1] = y; subEntity.vertexData[k * byteStride + offset + 2] = z; } else { // Lighting information baked into the mesh float[] lightVector = light.getLightVector(); float diffuse = Math.max( Vector3.dot(x, y, z, lightVector[0], lightVector[1], lightVector[2]), 0); subEntity.vertexData[k * byteStride + offset] = diffuse; } } break; case 4: // This is a blendindex offset = Mesh.BONE_INDEX_OFFSET; for (int k = 0; k < subEntity.countVertices; ++k) { for (int m = 0; m < 4; ++m) { int intVal = buffer[pos++] & 0xff; subEntity.boneData[k * Mesh.BONE_BYTE_STRIDE + offset + m] = intVal; } } break; case 5: // This is a blendweight offset = Mesh.BONE_WEIGHT_OFFSET; for (int k = 0; k < subEntity.countVertices; ++k) { for (int m = 0; m < 4; ++m) { int intVal = buffer[pos++] & 0xff; float weight = intVal / 255.f; subEntity.boneData[k * Mesh.BONE_BYTE_STRIDE + offset + m] = weight; } } break; case 6: // This i a color break; default: // None of the above, we dont care about this data; break; } } } }