`
micheal19840929
  • 浏览: 167418 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

MS3D模型载入与演示(支持动画)

J# 
阅读更多
import java.io.InputStream;
import java.nio.FloatBuffer;
import java.util.Hashtable;
import java.util.Vector;

import org.lwjgl.BufferUtils;
import org.lwjgl.Sys;
import org.lwjgl.opengl.GL11;
import org.tinder.studio.lwjgl.util.BinaryFileReader;
import org.tinder.studio.lwjgl.util.Bounding;
import org.tinder.studio.lwjgl.util.GLApp;
import org.tinder.studio.lwjgl.util.Matrix4f;
import org.tinder.studio.lwjgl.util.Vector3f;
import org.tinder.studio.lwjgl.util.Vector4f;

/**
 * 
 * 
 * @Author Micheal Hong
 * @Email babala_234@163.com
 * @Version 2010-6-29下午10:33:28
 * 
 */
public class MS3DModel {

	MS3DHeader header;

	int numVertices;
	public MS3DVertex[] vertices;
	float vertex[];

	int numTriangles;
	MS3DTriangle[] triangles;

	int numMeshs;
	MS3DMesh[] meshs;

	int numMaterials;
	MS3DMaterial[] materials;

	int numJoints;
	MS3DJoint[] joints;

	long lastTime;
	int currentAnimation;
	float currentTime;
	int totalFrames;
	int endFrame;
	float animationFPS;
	boolean loop;
	boolean loopDone;
	Vector<MS3DAnimation> allAnimations;
	Hashtable<String, MS3DJoint> allJoints;
	Vector<MS3DJoint> rootJoints;
	String textureDirectory;
	
	Bounding bounding;

	/***************************************************************************************************************************************************************************************************
	 * MS3DModel () - Constructor
	 **************************************************************************************************************************************************************************************************/
	public MS3DModel(InputStream file,String textureDirectory) {
		this.allJoints = new Hashtable<String, MS3DJoint>();
		this.rootJoints = new Vector<MS3DJoint>();
		this.allAnimations = new Vector<MS3DAnimation>();
		this.currentAnimation = -1;
		this.loop = true;
		this.loopDone = false;
		this.textureDirectory=textureDirectory;
		this.loadModel(file);
		this.makeBounding();

	}

	/***************************************************************************************************************************************************************************************************
	 * loadModel() - Load a ms3d model and prepare it for rendering
	 **************************************************************************************************************************************************************************************************/
	protected void loadModel(InputStream file) {

		try {
			// Read the model file
			BinaryFileReader modelFile = new BinaryFileReader(file);

			// Read header
			this.header = new MS3DHeader(modelFile);
			if (!this.header.isValid())
				throw new Exception("Model header is invalid! Only versions 1.3 and 1.4 are supported!");

			// Read vertices
			this.numVertices = modelFile.readShort();
			this.vertices = new MS3DVertex[this.numVertices];
			this.vertex = new float[3 * numVertices];
			for (int i = 0; i < this.numVertices; i++) {
				this.vertices[i] = new MS3DVertex(modelFile);
				this.vertex[3 * i] = this.vertices[i].vertex.x;
				this.vertex[3 * i + 1] = this.vertices[i].vertex.y;
				this.vertex[3 * i + 2] = this.vertices[i].vertex.z;
			}

			// Triangles
			this.numTriangles = modelFile.readShort();
			this.triangles = new MS3DTriangle[this.numTriangles];
			for (int i = 0; i < this.numTriangles; i++)
				this.triangles[i] = new MS3DTriangle(modelFile);

			// Meshs
			this.numMeshs = modelFile.readShort();
			this.meshs = new MS3DMesh[this.numMeshs];
			for (int i = 0; i < this.numMeshs; i++)
				this.meshs[i] = new MS3DMesh(modelFile);

			// Materials
			this.numMaterials = modelFile.readShort();
			this.materials = new MS3DMaterial[this.numMaterials];
			for (int i = 0; i < this.numMaterials; i++)
				this.materials[i] = new MS3DMaterial(modelFile);

			// Keyframe data
			animationFPS = modelFile.readFloat();
			currentTime = (long) (modelFile.readFloat() * 1000);
			totalFrames = modelFile.readInt();

			// Joints
			numJoints = modelFile.readShort();
			this.joints = new MS3DJoint[numJoints];
			for (int i = 0; i < this.numJoints; i++) {
				this.joints[i] = new MS3DJoint(modelFile);
				addJoint(this.joints[i]);
			}

			// Load textures
			this.reloadTextures();

			this.makeBones();

			this.reset();

		} catch (Exception e) {
			Sys.alert("Error", "Failed to load model '" + file.toString()+ "'!\n\n" + e.getMessage());
			e.printStackTrace();
			System.exit(0);
		}

	}

	public void addJoint(MS3DJoint joint) {
		allJoints.put(joint.name, joint);

		if (joint.parentName.equals(""))
			rootJoints.addElement(joint);
	}

	public Hashtable<String, MS3DJoint> getJoints() {
		return allJoints;
	}

	/***************************************************************************************************************************************************************************************************
	 * reloadTextures() - Load the texture of each material
	 **************************************************************************************************************************************************************************************************/
	public void reloadTextures() {

		for (int i = 0; i < this.numMaterials; i++) {
			if (this.materials[i].textureID != 0)
				GL11.glDeleteTextures(BufferUtils.createIntBuffer(1).put(this.materials[i].textureID));
			else {
				try {
					this.materials[i].textureID = GLApp.makeTexture(this.textureDirectory+"/"+this.materials[i].texturemap);
				} catch (Exception e) {
					System.out.println("Failed to open texture file 'this.materials[i].texturemap'!");
				}
			}

		}
	}

	public void updateModel(long time) {
		// update the animation
		updateAnimation(time);

		boolean texturingEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D);

		// update the points
		for (int i = 0; i < numMeshs; i++) {
			if (this.meshs[i].materialIndex >= 0) {
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT,this.materials[this.meshs[i].materialIndex].ambient);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE,this.materials[this.meshs[i].materialIndex].diffuse);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR,this.materials[this.meshs[i].materialIndex].specular);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_EMISSION,this.materials[this.meshs[i].materialIndex].emissive);
				GL11.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS,this.materials[this.meshs[i].materialIndex].shininess);

				if (this.materials[this.meshs[i].materialIndex].textureID > 0) {
					GL11.glBindTexture(GL11.GL_TEXTURE_2D,this.materials[this.meshs[i].materialIndex].textureID);
					GL11.glEnable(GL11.GL_TEXTURE_2D);
				} else {
					GL11.glDisable(GL11.GL_TEXTURE_2D);
				}
			} else {
				GL11.glDisable(GL11.GL_TEXTURE_2D);
			}
			float[] coords = new float[3];
			Vector4f temp = new Vector4f();
			Matrix4f matrix=null;
			GL11.glBegin(GL11.GL_TRIANGLES);
			for (int j = 0; j < meshs[i].numTriangles; j++) {

				for (int k = 0; k < 3; k++) {

					coords[0] = vertex[3 * triangles[meshs[i].triangleIndices[j]].vertexIndices[k]];
					coords[1] = vertex[3 * triangles[meshs[i].triangleIndices[j]].vertexIndices[k] + 1];
					coords[2] = vertex[3 * triangles[meshs[i].triangleIndices[j]].vertexIndices[k] + 2];

					if (vertices[triangles[meshs[i].triangleIndices[j]].vertexIndices[k]].boneID != -1) {
						matrix = joints[vertices[triangles[meshs[i].triangleIndices[j]].vertexIndices[k]].boneID].finalMatrix;

						temp.x = coords[0] * matrix.m00 + coords[1]
								* matrix.m10 + coords[2] * matrix.m20
								+ matrix.m30;
						temp.y = coords[0] * matrix.m01 + coords[1]
								* matrix.m11 + coords[2] * matrix.m21
								+ matrix.m31;
						temp.z = coords[0] * matrix.m02 + coords[1]
								* matrix.m12 + coords[2] * matrix.m22
								+ matrix.m32;
						temp.w = coords[0] * matrix.m03 + coords[1]
								* matrix.m13 + coords[2] * matrix.m23
								+ matrix.m33;

						GL11.glNormal3f(
										triangles[meshs[i].triangleIndices[j]].vertexNormals[0][0],
										triangles[meshs[i].triangleIndices[j]].vertexNormals[0][1],
										triangles[meshs[i].triangleIndices[j]].vertexNormals[0][2]);
						GL11.glTexCoord2f(
								triangles[meshs[i].triangleIndices[j]].s[k],
								triangles[meshs[i].triangleIndices[j]].t[k]);
						GL11.glVertex3f(temp.x, temp.y, temp.z);
					}

				}
			}
			GL11.glEnd();

		}

		// Reset texture state
		if (texturingEnabled)
			GL11.glEnable(GL11.GL_TEXTURE_2D);
		else
			GL11.glDisable(GL11.GL_TEXTURE_2D);

	}

	/***************************************************************************************************************************************************************************************************
	 * render() - Render this model
	 **************************************************************************************************************************************************************************************************/
	public void render() {

		// Save texture state
		boolean texturingEnabled = GL11.glIsEnabled(GL11.GL_TEXTURE_2D);

		// Render each mesh
		for (int m = 0; m < this.numMeshs; m++) {

			// Set texture for this mesh
			if (this.meshs[m].materialIndex >= 0) {
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT,this.materials[this.meshs[m].materialIndex].ambient);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE,this.materials[this.meshs[m].materialIndex].diffuse);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR,this.materials[this.meshs[m].materialIndex].specular);
				GL11.glMaterial(GL11.GL_FRONT, GL11.GL_EMISSION,this.materials[this.meshs[m].materialIndex].emissive);
				GL11.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS,this.materials[this.meshs[m].materialIndex].shininess);

				if (this.materials[this.meshs[m].materialIndex].textureID > 0) {
					GL11.glBindTexture(GL11.GL_TEXTURE_2D,this.materials[this.meshs[m].materialIndex].textureID);
					GL11.glEnable(GL11.GL_TEXTURE_2D);
				} else {
					GL11.glDisable(GL11.GL_TEXTURE_2D);
				}
			} else {
				GL11.glDisable(GL11.GL_TEXTURE_2D);
			}

			// Render each mesh
			GL11.glBegin(GL11.GL_TRIANGLES);
			{
				for (int t = 0; t < this.meshs[m].numTriangles; t++) {
					for (int v = 0; v < 3; v++) {
						GL11.glNormal3f(
										this.triangles[this.meshs[m].triangleIndices[t]].vertexNormals[v][0],
										this.triangles[this.meshs[m].triangleIndices[t]].vertexNormals[v][1],
										this.triangles[this.meshs[m].triangleIndices[t]].vertexNormals[v][2]);
						GL11.glTexCoord2f(
										this.triangles[this.meshs[m].triangleIndices[t]].s[v],
										this.triangles[this.meshs[m].triangleIndices[t]].t[v]);
						GL11.glVertex3f(
										this.vertices[this.triangles[this.meshs[m].triangleIndices[t]].vertexIndices[v]].vertex.x,
										this.vertices[this.triangles[this.meshs[m].triangleIndices[t]].vertexIndices[v]].vertex.y,
										this.vertices[this.triangles[this.meshs[m].triangleIndices[t]].vertexIndices[v]].vertex.z);
					}
				}
			}
			GL11.glEnd();

		}

		// Reset texture state
		if (texturingEnabled)
			GL11.glEnable(GL11.GL_TEXTURE_2D);
		else
			GL11.glDisable(GL11.GL_TEXTURE_2D);
	}

	public void reset() {
		for (int i = 0; i < numJoints; i++) {
			joints[i].currentRotationKeyframe = 0;
			joints[i].currentTranslationKeyframe = 0;
			joints[i].finalMatrix = new Matrix4f(joints[i].absoluteMatrix);
		}

		currentTime = 0;
		if (currentAnimation != -1) {
			MS3DAnimation ms3dAnimation = (MS3DAnimation) allAnimations.get(currentAnimation);
			currentTime += ms3dAnimation.startFrame * 1000.0 / animationFPS;
		}
		loopDone = false;
	}

	public void updateAnimation(long time) {

		currentTime += time - lastTime;
		lastTime = time;

		if (currentAnimation == -1) {
			endFrame = totalFrames;
		} else {
			MS3DAnimation ms3dAnimation = (MS3DAnimation) allAnimations.get(currentAnimation);
			endFrame = ms3dAnimation.endFrame;
		}

		if (currentTime >= (endFrame + 1) * 1000.0 / animationFPS) {
			if (loop) {
				reset();
			} else {
				currentTime = (long) ((endFrame + 1) * 1000.0 / animationFPS);
				loopDone = true;
			}
		}

		for (int i = 0; i < numJoints; i++) {
			Vector3f transVec = new Vector3f();
			Matrix4f transform = new Matrix4f();
			transform.setIdentity();

			short frame;
			MS3DJoint joint = joints[i];

			if (joint.numRotationKeyframes == 0
					&& joint.numTranslationKeyframes == 0) {
				joint.finalMatrix = new Matrix4f(joint.absoluteMatrix);
				continue;
			}

			frame = joint.currentTranslationKeyframe;
			while (frame < joint.numTranslationKeyframes
					&& joint.translationKeyframes[frame].time < currentTime) {
				frame++;
			}
			// System.out.println("frame:"+frame);
			joint.currentTranslationKeyframe = frame;

			if (frame == 0) {
				transVec.x = joint.translationKeyframes[0].x;
				transVec.y = joint.translationKeyframes[0].y;
				transVec.z = joint.translationKeyframes[0].z;
			} else if (frame == joint.numTranslationKeyframes) {
				transVec.x = joint.translationKeyframes[frame - 1].x;
				transVec.y = joint.translationKeyframes[frame - 1].y;
				transVec.z = joint.translationKeyframes[frame - 1].z;
			} else {
				MS3DKeyframe curFrame = joint.translationKeyframes[frame];
				MS3DKeyframe prevFrame = joint.translationKeyframes[frame - 1];

				float timeDelta = ((float) (curFrame.time - prevFrame.time));
				float interpValue = (float) ((currentTime - prevFrame.time) / (float) timeDelta);

				transVec.x = prevFrame.x + (curFrame.x - prevFrame.x) * interpValue;
				transVec.y = prevFrame.y + (curFrame.y - prevFrame.y) * interpValue;
				transVec.z = prevFrame.z + (curFrame.z - prevFrame.z) * interpValue;
			}

			//
			frame = joint.currentRotationKeyframe;

			while (frame < joint.numRotationKeyframes
					&& joint.rotationKeyframes[frame].time < currentTime) {
				frame++;
			}
			joint.currentRotationKeyframe = frame;

			if (frame == 0) {
				setRzRyRxRotationTranspose(transform,joint.rotationKeyframes[0].z,joint.rotationKeyframes[0].y,joint.rotationKeyframes[0].x);
			} else if (frame == joint.numRotationKeyframes) {
				setRzRyRxRotationTranspose(transform,joint.rotationKeyframes[frame - 1].z,joint.rotationKeyframes[frame - 1].y,joint.rotationKeyframes[frame - 1].x);
			} else {
				MS3DKeyframe curFrame = joint.rotationKeyframes[frame];
				MS3DKeyframe prevFrame = joint.rotationKeyframes[frame - 1];

				float timeDelta = ((float) (curFrame.time - prevFrame.time));
				float interpValue = (float) ((currentTime - prevFrame.time) / timeDelta);

				Vector3f rotVec = new Vector3f();

				rotVec.x = prevFrame.x + (curFrame.x - prevFrame.x) * interpValue;
				rotVec.y = prevFrame.y + (curFrame.y - prevFrame.y) * interpValue;
				rotVec.z = prevFrame.z + (curFrame.z - prevFrame.z) * interpValue;

				setRzRyRxRotationTranspose(transform, rotVec.z, rotVec.y, rotVec.x);

			}

			// Translation
			setTranslationTranspose(transform, transVec.x, transVec.y, transVec.z);

			Matrix4f relativeFinal = new Matrix4f();

			mulTransposeBothTanspose(relativeFinal, joint.relativeMatrix, transform);

			if (joint.parentName.equals("")) {

				joint.finalMatrix = relativeFinal;

			} else {

				MS3DJoint father = (MS3DJoint) allJoints.get(joint.parentName);

				joint.finalMatrix = new Matrix4f();

				mulTransposeBothTanspose(joint.finalMatrix, father.finalMatrix, relativeFinal);

			}

		}

	}

	public static void setRzRyRxRotationTranspose(Matrix4f matrix, float z, float y, float x) {
		if (matrix == null) {
			matrix = new Matrix4f();
			matrix.setIdentity();
		}

		double cosinusX = Math.cos(x);
		double sinusX = Math.sin(x);
		double cosinusY = Math.cos(y);
		double sinusY = Math.sin(y);
		double cosinusZ = Math.cos(z);
		double sinusZ = Math.sin(z);

		matrix.m00 = (float) (cosinusY * cosinusZ);
		matrix.m01 = (float) (cosinusY * sinusZ);
		matrix.m02 = (float) (-sinusY);
		// do not alter m03

		matrix.m10 = (float) (sinusX * sinusY * cosinusZ - cosinusX * sinusZ);
		matrix.m11 = (float) (sinusX * sinusY * sinusZ + cosinusX * cosinusZ);
		matrix.m12 = (float) (sinusX * cosinusY);
		// do not alter m13

		matrix.m20 = (float) (cosinusX * sinusY * cosinusZ + sinusX * sinusZ);
		matrix.m21 = (float) (cosinusX * sinusY * sinusZ - sinusX * cosinusZ);
		matrix.m22 = (float) (cosinusX * cosinusY);
		// do not alter m23

		// do not alter m30 - m33
	}

	public static void setTranslationTranspose(Matrix4f matrix, float x, float y, float z) {
		if (matrix == null) {
			matrix = new Matrix4f();
			matrix.setIdentity();
		}

		// do not alter m00 - m23
		matrix.m30 = x;
		matrix.m31 = y;
		matrix.m32 = z;

		matrix.m33 = 1.0f;

	}

	public static void mulTransposeBothTanspose(Matrix4f matrix, Matrix4f matrixA, Matrix4f matrixB) {
		if (matrix == null) {
			matrix = new Matrix4f();
		}

		matrix.m00 = matrixA.m00 * matrixB.m00 + matrixA.m10 * matrixB.m01
				+ matrixA.m20 * matrixB.m02;
		matrix.m01 = matrixA.m01 * matrixB.m00 + matrixA.m11 * matrixB.m01
				+ matrixA.m21 * matrixB.m02;
		matrix.m02 = matrixA.m02 * matrixB.m00 + matrixA.m12 * matrixB.m01
				+ matrixA.m22 * matrixB.m02;
		matrix.m03 = 0.0f;

		matrix.m10 = matrixA.m00 * matrixB.m10 + matrixA.m10 * matrixB.m11
				+ matrixA.m20 * matrixB.m12;
		matrix.m11 = matrixA.m01 * matrixB.m10 + matrixA.m11 * matrixB.m11
				+ matrixA.m21 * matrixB.m12;
		matrix.m12 = matrixA.m02 * matrixB.m10 + matrixA.m12 * matrixB.m11
				+ matrixA.m22 * matrixB.m12;
		matrix.m13 = 0.0f;

		matrix.m20 = matrixA.m00 * matrixB.m20 + matrixA.m10 * matrixB.m21
				+ matrixA.m20 * matrixB.m22;
		matrix.m21 = matrixA.m01 * matrixB.m20 + matrixA.m11 * matrixB.m21
				+ matrixA.m21 * matrixB.m22;
		matrix.m22 = matrixA.m02 * matrixB.m20 + matrixA.m12 * matrixB.m21
				+ matrixA.m22 * matrixB.m22;
		matrix.m23 = 0.0f;

		matrix.m30 = matrixA.m00 * matrixB.m30 + matrixA.m10 * matrixB.m31
				+ matrixA.m20 * matrixB.m32 + matrixA.m30;
		matrix.m31 = matrixA.m01 * matrixB.m30 + matrixA.m11 * matrixB.m31
				+ matrixA.m21 * matrixB.m32 + matrixA.m31;
		matrix.m32 = matrixA.m02 * matrixB.m30 + matrixA.m12 * matrixB.m31
				+ matrixA.m22 * matrixB.m32 + matrixA.m32;
		matrix.m33 = 1.0f;
	}

	public void addAnimation(MS3DAnimation ms3dAnimation) {
		allAnimations.addElement(ms3dAnimation);
	}

	public void deleteAnimations() {
		for (int i = 0; i < allAnimations.size(); i++) {
			allAnimations.remove(i);
		}
	}

	public int numberAnimations() {
		return allAnimations.size();
	}

	/**
	 * 初始化骨骼和绑定顶点
	 */
	private void makeBones() {
		MS3DJoint joint = null;
		MS3DVertex vertex = null;

		MS3DJoint father = null;

		// make the bone hierarchy
		for (int i = 0; i < numJoints; i++) {
			joint = joints[i];

			joint.relativeMatrix = new Matrix4f();

			// Rotation
			MS3DModel.setRzRyRxRotationTranspose(joint.relativeMatrix,joint.rotation[2], joint.rotation[1], joint.rotation[0]);

			// Translation
			MS3DModel.setTranslationTranspose(joint.relativeMatrix,joint.translation[0], joint.translation[1],joint.translation[2]);

			if (!joint.parentName.equals("")) {
				// 如果是子关节,那么将上一个节点的绝对矩阵乘上这个节点的变幻矩 阵就可以得到这个子节点的绝对矩阵了.
				father = (MS3DJoint) allJoints.get(joint.parentName);

				joint.absoluteMatrix = new Matrix4f();

				MS3DModel.mulTransposeBothTanspose(joint.absoluteMatrix,
						father.absoluteMatrix, joint.relativeMatrix);

			} else {
				// 如果是根关节那么它的绝对矩阵就是它的相对变换矩阵
				joint.absoluteMatrix = new Matrix4f(joint.relativeMatrix);

			}
		}

		// initialize the vertices
		for (int i = 0; i < numVertices; i++) {
			vertex = vertices[i];

			if (vertex.boneID != -1) {
				Matrix4f matrix = joints[vertex.boneID].absoluteMatrix;

				float x = vertex.vertex.x - matrix.m30;
				float y = vertex.vertex.y - matrix.m31;
				float z = vertex.vertex.z - matrix.m32;

				this.vertex[3 * i] = x * matrix.m00 + y * matrix.m01 + z * matrix.m02;
				this.vertex[3 * i + 1] = x * matrix.m10 + y * matrix.m11 + z * matrix.m12;
				this.vertex[3 * i + 2] = x * matrix.m20 + y * matrix.m21 + z * matrix.m22;

			}
		}

	}
	
	private void makeBounding()
	{
		float minX,minY,minZ,maxX,maxY,maxZ;
		minX=minY=minZ=maxX=maxY=maxZ=0;
		Vector3f vertex;
		for(int i=0;i<this.vertices.length;i++)
		{
			vertex=this.vertices[i].vertex;
			if (i == 0) {
				minX = maxX = vertex.x;
				minY = maxY = vertex.y;
				minZ = maxZ = vertex.z;
			} else {
				if (vertex.x < minX)
					minX = vertex.x;
				else if (vertex.x > maxX)
					maxX = vertex.x;

				if (vertex.y < minY)
					minY = vertex.y;
				else if (vertex.y > maxY)
					maxY = vertex.y;
				if (vertex.z < minZ)
					minZ = vertex.z;
				else if (vertex.z > maxZ)
					maxZ = vertex.z;

			}
		}
		this.bounding=new Bounding(minX, minY, minZ, maxX, maxY, maxZ);
	}

	/***************************************************************************************************************************************************************************************************
	 * Header of a ms3d file
	 **************************************************************************************************************************************************************************************************/
	private class MS3DHeader {

		/** Read the header */
		public MS3DHeader(BinaryFileReader modelFile) {

			this.ID = modelFile.readString(10);
			this.version = modelFile.readInt();
		}

		/** Check whether the header is valid */
		public boolean isValid() {

			if ((this.ID.equals("MS3D000000") && this.version >= 3 && this.version <= 4))
				return true;
			else
				return false;
		}

		String ID;
		int version;
	}

	/***************************************************************************************************************************************************************************************************
	 * Vertex as used in ms3d files
	 **************************************************************************************************************************************************************************************************/
	@SuppressWarnings("unused")
	private class MS3DVertex {

		/** Read a vertex */
		public MS3DVertex(BinaryFileReader modelFile) {

			this.flags = modelFile.readByte();
			this.vertex = new Vector3f(modelFile.readFloat(), modelFile.readFloat(), modelFile.readFloat());
			this.boneID = modelFile.readByte();
			this.refCount = modelFile.readByte();
		}

		Vector3f vertex;
		int boneID;
		int flags;
		int refCount;
	}

	/***************************************************************************************************************************************************************************************************
	 * Triangle as used in ms3d files
	 **************************************************************************************************************************************************************************************************/
	@SuppressWarnings("unused")
	private class MS3DTriangle {

		/** Read a triangle */
		public MS3DTriangle(BinaryFileReader modelFile) {

			this.flags = modelFile.readShort();
			this.vertexIndices[0] = modelFile.readShort();
			this.vertexIndices[1] = modelFile.readShort();
			this.vertexIndices[2] = modelFile.readShort();
			this.vertexNormals[0][0] = modelFile.readFloat();
			this.vertexNormals[0][1] = modelFile.readFloat();
			this.vertexNormals[0][2] = modelFile.readFloat();
			this.vertexNormals[1][0] = modelFile.readFloat();
			this.vertexNormals[1][1] = modelFile.readFloat();
			this.vertexNormals[1][2] = modelFile.readFloat();
			this.vertexNormals[2][0] = modelFile.readFloat();
			this.vertexNormals[2][1] = modelFile.readFloat();
			this.vertexNormals[2][2] = modelFile.readFloat();
			this.s[0] = modelFile.readFloat();
			this.s[1] = modelFile.readFloat();
			this.s[2] = modelFile.readFloat();
			this.t[0] = 1 - modelFile.readFloat();
			this.t[1] = 1 - modelFile.readFloat();
			this.t[2] = 1 - modelFile.readFloat();
			this.smoothingMesh = modelFile.readByte();
			this.meshIndex = modelFile.readByte();
		}

		int flags;
		int vertexIndices[] = new int[3];
		float[][] vertexNormals = new float[3][3];
		float[] s = new float[3];
		float[] t = new float[3];
		int smoothingMesh;
		int meshIndex;
	}

	/***************************************************************************************************************************************************************************************************
	 * Mesh to group triangles which use the same material
	 **************************************************************************************************************************************************************************************************/
	@SuppressWarnings("unused")
	private class MS3DMesh {

		// Read a mesh
		public MS3DMesh(BinaryFileReader modelFile) {

			this.flags = modelFile.readByte();
			this.name = modelFile.readString(32);
			this.numTriangles = modelFile.readShort();
			this.triangleIndices = new int[this.numTriangles];
			for (int i = 0; i < this.numTriangles; i++)
				this.triangleIndices[i] = modelFile.readShort();
			this.materialIndex = modelFile.readByte();
		}

		String name;
		int materialIndex;
		int numTriangles;
		int[] triangleIndices;
		int flags;
	}

	/***************************************************************************************************************************************************************************************************
	 * Material as used in ms3d files
	 **************************************************************************************************************************************************************************************************/
	@SuppressWarnings("unused")
	private class MS3DMaterial {

		// Read a material
		public MS3DMaterial(BinaryFileReader modelFile) {

			this.name = modelFile.readString(32);
			float[] ambientArray = new float[] { modelFile.readFloat(),modelFile.readFloat(), modelFile.readFloat(),modelFile.readFloat() };
			float[] diffuseArray = new float[] { modelFile.readFloat(),modelFile.readFloat(), modelFile.readFloat(),modelFile.readFloat() };
			float[] specularArray = new float[] { modelFile.readFloat(),modelFile.readFloat(), modelFile.readFloat(),modelFile.readFloat() };
			float[] emissiveArray = new float[] { modelFile.readFloat(),modelFile.readFloat(), modelFile.readFloat(),modelFile.readFloat() };
			this.shininess = modelFile.readFloat();
			this.transparency = modelFile.readFloat();
			this.mode = modelFile.readByte();
			this.texturemap = modelFile.readString(128);
			this.alphamap = modelFile.readString(128);

			// // Fix paths
			if (this.texturemap.startsWith("..\\"))
				this.texturemap = this.texturemap.substring(3);

			if (this.texturemap.startsWith(".\\"))
				this.texturemap = this.texturemap.substring(2);

			if (this.alphamap.startsWith("..\\"))
				this.alphamap = this.alphamap.substring(3);

			if (this.alphamap.startsWith(".\\"))
				this.alphamap = this.alphamap.substring(2);

			// Fill buffers
			this.ambient.put(ambientArray).flip();
			this.diffuse.put(diffuseArray).flip();
			this.specular.put(specularArray).flip();
			this.emissive.put(emissiveArray).flip();
		}

		String name;
		String texturemap;
		int textureID;
		String alphamap;
		FloatBuffer ambient = BufferUtils.createFloatBuffer(4);
		FloatBuffer diffuse = BufferUtils.createFloatBuffer(4);
		FloatBuffer specular = BufferUtils.createFloatBuffer(4);
		FloatBuffer emissive = BufferUtils.createFloatBuffer(4);
		float shininess;
		float transparency;
		int mode;
	}

	/***************************************************************************************************************************************************************************************************
	 * Joint information as used in ms3d files
	 **************************************************************************************************************************************************************************************************/
	@SuppressWarnings("unused")
	private class MS3DJoint {

		// Read Joint
		public MS3DJoint(BinaryFileReader modelFile) {
			this.flag = modelFile.readByte();
			this.name = modelFile.readString(32);
			System.out.print(name + ":");
			this.parentName = modelFile.readString(32);
			this.rotation[0] = modelFile.readFloat();
			this.rotation[1] = modelFile.readFloat();
			this.rotation[2] = modelFile.readFloat();
			this.translation[0] = modelFile.readFloat();
			this.translation[1] = modelFile.readFloat();
			this.translation[2] = modelFile.readFloat();
			this.numRotationKeyframes = modelFile.readShort();
			this.numTranslationKeyframes = modelFile.readShort();
			System.out.println(this.numRotationKeyframes + ","
					+ this.numTranslationKeyframes);

			this.rotationKeyframes = new MS3DKeyframe[numRotationKeyframes];
			for (int i = 0; i < this.numRotationKeyframes; i++)
				this.rotationKeyframes[i] = new MS3DKeyframe(modelFile);

			this.translationKeyframes = new MS3DKeyframe[numTranslationKeyframes];
			for (int i = 0; i < this.numTranslationKeyframes; i++)
				this.translationKeyframes[i] = new MS3DKeyframe(modelFile);

		}

		int flag;
		String name;
		String parentName;
		float[] rotation = new float[3];
		float[] translation = new float[3];
		int numRotationKeyframes;
		int numTranslationKeyframes;
		MS3DKeyframe[] rotationKeyframes;
		MS3DKeyframe[] translationKeyframes;

		Matrix4f absoluteMatrix;
		Matrix4f relativeMatrix;
		Matrix4f finalMatrix;
		short currentRotationKeyframe;
		short currentTranslationKeyframe;
	}

	/***************************************************************************************************************************************************************************************************
	 * Keyframe as used in ms3d files
	 **************************************************************************************************************************************************************************************************/
	private class MS3DKeyframe {

		// Read Keyframe
		public MS3DKeyframe(BinaryFileReader modelFile) {
			this.time = (long) (modelFile.readFloat() * 1000);
			this.x = modelFile.readFloat();
			this.y = modelFile.readFloat();
			this.z = modelFile.readFloat();
		}

		float time; // time in seconds
		float x, y, z;
	}

	@SuppressWarnings("unused")
	private class MS3DAnimation {

		short startFrame;
		short endFrame;

		public MS3DAnimation() {
			this.startFrame = 0;
			this.endFrame = 0;
		}

		/** Creates a new instance of MS3DAnimation */
		public MS3DAnimation(short startFrame, short endFrame) {
			this.startFrame = startFrame;
			this.endFrame = endFrame;
		}

		public MS3DAnimation(int startFrame, int endFrame) {
			this.startFrame = (short) startFrame;
			this.endFrame = (short) endFrame;
		}

	}

	public Bounding getBounding() {
		return bounding;
	}

	
}

演示效果如下:

分享到:
评论

相关推荐

    演示ms3d动画的例子

    【标题】"演示ms3d动画的例子"是一个关于如何在编程环境中展示MS3D(Microsoft 3D)模型和动画的实例。这个示例项目包含了从加载到渲染MS3D模型的所有关键步骤,旨在帮助开发者理解和应用3D图形技术。 【描述】"ms...

    MS3D模型骨骼动画

    ### MS3D模型骨骼动画详解 #### 一、模型动画技术概述 模型动画技术是现代三维图形学中不可或缺的一部分,广泛应用于游戏开发、电影制作、虚拟现实等领域。根据实现方式的不同,模型动画主要分为两大类:**顶点...

    ms3d模型ms3d模型ms3d模型ms3d模型

    ms3d模型ms3d模型ms3d模型ms3d模型ms3d模型ms3d模型ms3d模型

    3d 模型 带动画

    在IT行业中,3D模型与动画的结合是一个重要的领域,特别是在增强现实(AR)、游戏开发、影视制作以及可视化设计中。这里的"3D模型带动画"指的是具有三维形状和细节的数字对象,它们不仅有静态的外观,还能通过预设的...

    【C++】3D模型载入演示demo by浅墨

    其中的3D模型使用的是初音,模型质量很高,可以自己用鼠标和键盘控制视角。 【Visual C++】游戏开发笔记之【浅墨DirectX提高班】系列博文 配套详细注释源码之十二 源码配套博文 《【Visual C++】游戏开发笔记四十...

    Unity 3D模型展示,3D标注、拆装动画

    总结来说,这个“Unity 3D模型展示”项目涵盖了3D模型导入与优化、3D标注的创建、环绕相机的实现、步骤列表与拆装动画的构建等多个关键知识点。通过这些技术,开发者可以构建出具有高度互动性和教育价值的3D应用,...

    opengl读ms3d模型

    opengl读取一个ms3d的飞行器模型,挺有用的

    带动画的3d模型

    它支持模型、纹理、骨骼、动画和相机数据。FBX的跨平台特性使得它成为游戏开发、影视特效和视觉设计等行业中广泛使用的标准格式。 "Body.tga" 是一种图像文件,可能作为模型的身体部分的纹理。TGA(Truevision ...

    Hands On MilkShape 的MS3D模型文件

    本书提供的MS3D模型文件是MilkShape支持的一种特定格式,用于存储3D模型数据,包括几何形状、纹理、骨架和动画等信息。 MS3D(MilkShape 3D)模型文件格式是专为游戏设计而优化的,它以紧凑和高效的方式保存数据,...

    Unity3D游戏开发FBX模型载入与人物行走动画的播放

    在Unity3D游戏开发中,FBX模型的载入与人物行走动画的播放是至关重要的环节,这涉及到游戏场景的构建、角色交互以及游戏体验的提升。FBX是一种跨平台的三维模型交换格式,广泛应用于游戏开发、电影制作等领域。Unity...

    安川机器人3D模型 MS165

    标题中的“安川机器人3D模型 MS165”指的是由日本知名自动化设备制造商安川电机(Yaskawa)生产的MS165型号机器人的一种三维(3D)模型。这款模型通常用于工业自动化领域的设计、仿真和规划,帮助工程师在实际部署前...

    ms3d教程一套

    【标题】"ms3d教程一套"所涉及的知识点主要围绕MS3D模型格式和相关的3D建模与动画制作技术展开。MS3D是一种流行的3D模型文件格式,尤其在游戏开发和实时渲染领域中常见。这个教程可能包含从基础到高级的各个层次的...

    Hands On MilkShape 书中的MS3D模型和图片

    4. **导出与导入**:学习如何将MS3D模型导出为其他游戏引擎支持的格式,如Wavefront OBJ、3DS或MD5,并了解导入其他格式的模型到MilkShape进行编辑。 5. **实例操作**:书中可能提供了一些实际案例,如创建简单的...

    maya3D模型 棒球选手(有动画)

    《maya3D模型:棒球选手与动画制作解析》 在数字艺术和影视特效领域,maya3D模型是不可或缺的重要元素。本资源“maya3D模型 棒球选手(有动画)”正是这样一个专业级别的3D模型,为创作者提供了丰富的表现力和动态...

    MS3D人物骨骼动画

    MS3D支持多种3D模型和动画格式的导入导出,其中就包括我们关注的骨骼动画系统。 骨骼动画,是3D角色动画的一种核心技术,通过将3D模型的各个部分与虚拟骨骼关联,然后对骨骼进行移动、旋转,就能实现角色的动态表现...

    CS模型制作-MS3D-Milkshape 3D

    4. **支持多种游戏引擎**:MS3D可以直接导出模型数据到各种游戏引擎支持的格式,如Valve的MDL(用于半条命系列)、ID Software的MDL(用于毁灭战士系列)、以及Unreal Engine的UNR等。 5. **轻量级与高效**:与其他...

    ms3d-loader

    总的来说,"ms3d-loader"是一个学习和演示如何在OpenGL环境中处理3D模型和材质的实用工具。它涵盖了文件解析、OpenGL纹理操作、3D模型渲染等多个关键知识点,对于理解3D图形编程和游戏开发具有很高的参考价值。

    WPF 官方3D模型和3D动画库(helix-toolkit)

    Helix Toolkit是一个开源项目,专为Windows Presentation Foundation (WPF) 平台提供3D模型和3D动画功能。这个库极大地扩展了WPF的原生3D支持,使得开发者可以更加轻松地创建复杂的3D应用程序,包括但不限于游戏、...

    3D模型加载(漂亮妹纸)

    在IT领域,3D模型加载是一项关键的技术,尤其在游戏开发、虚拟现实、建筑设计和可视化应用中至关重要。本文将深入探讨3D模型加载的过程、相关的技术以及如何实现一个可移植的3D模型加载软件。 首先,3D模型是通过...

    XNA 载入3D模型

    在XNA框架中,载入3D模型是游戏开发中的重要步骤,这使得我们能够将复杂的3D几何体、纹理和动画引入到游戏环境中。XNA是一个由Microsoft开发的开源游戏开发平台,它为.NET Framework提供了游戏开发工具,特别适合...

Global site tag (gtag.js) - Google Analytics