public boolean loadShader(ModelMD3 model, String fileShader) { try { // Wrap a buffer to make reading more efficient (faster) BufferedReader reader = new BufferedReader(new FileReader(fileShader)); // These variables are used to read in a line at a time from the file, and also // to store the current line being read so that we can use that as an index for the // textures, in relation to the index of the sub-object loaded in from the weapon model. String strLine; int currentIndex = 0; // Go through and read in every line of text from the file while ((strLine = reader.readLine()) != null) { // Create a local material info structure MaterialInfo texture = new MaterialInfo(); // Copy the name of the file into our texture file name variable texture.setName(strLine); // The tile or scale for the UV's is 1 to 1 (but Quake saves off a 0-256 ratio) texture.setUTile(1); texture.setVTile(1); // Add the local material info to our model's material list // Store the material ID for this object and set the texture boolean to true model.getObject(currentIndex).setMaterialID(model.getMaterials().size()); model.getObject(currentIndex).setbHasTexture(true); // Add the local material info structure to our model's material list model.addMaterials(texture); // Here we increase the material index for the next texture (if any) currentIndex++; } // Close the file and return a success reader.close(); } catch (Exception e) { return false; } return true; }
private void convertDataStructures(ModelMD3 model, MeshInfoMD3 meshHeader) { int i = 0; Object3d currentMesh = new Object3d(); // Assign the vertex, texture coord and face count to our new structure currentMesh.setNumVertices(meshHeader.numVertices * meshHeader.numMeshFrames); currentMesh.setNumVert(meshHeader.numVertices); currentMesh.setNumTexcoords(meshHeader.numVertices); currentMesh.setNumFaces(meshHeader.numTriangles); currentMesh.setName(meshHeader.strName); // Go through all of the vertices and assign them over to our structure for (i = 0; i < currentMesh.getNumVertices() * meshHeader.numMeshFrames; i++) { Vector3f temp = new Vector3f( vertices[i].vertex[0] / 64.0f, vertices[i].vertex[1] / 64.0f, vertices[i].vertex[2] / 64.0f); currentMesh.setVertices(temp, i); } for (i = 0; i < currentMesh.getNumTexcoords(); i++) { Vector3f temp = new Vector3f(texCoords[i].u, -texCoords[i].v, 0); currentMesh.setTexcoords(temp, i); } // Go through all of the face data and assign it over to OUR structure for (i = 0; i < currentMesh.getNumFaces(); i++) { // Assign the vertex indices to our face data currentMesh.getFace(i).setVertices(0, triangles[i].vertexIndices[0]); currentMesh.getFace(i).setVertices(1, triangles[i].vertexIndices[1]); currentMesh.getFace(i).setVertices(2, triangles[i].vertexIndices[2]); // Assign the texture coord indices to our face data currentMesh.getFace(i).setTexCoords(0, triangles[i].vertexIndices[0]); currentMesh.getFace(i).setTexCoords(1, triangles[i].vertexIndices[1]); currentMesh.getFace(i).setTexCoords(2, triangles[i].vertexIndices[2]); } currentMesh.setDimension(); // Here we add the current object (or frame) to our list object list model.addObject(currentMesh); }
/** * This loads the texture information for the model from the *.skin file. * * @param model Current model. * @param fileSkin Skin path. */ public boolean loadSkin(ModelMD3 model, String fileSkin) { // Make sure valid data was passed in if (model == null || fileSkin == null) return false; // This function is used to load a .skin file for the .md3 model associated // with it. The .skin file stores the textures that need to go with each // object and subject in the .md3 files. For instance, in our Lara Croft model, // her upper body model links to 2 texture; one for her body and the other for // her face/head. The .skin file for the lara_upper.md3 model has 2 textures: // // u_torso,models/players/laracroft/default.bmp // u_head,models/players/laracroft/default_h.bmp // // Notice the first word, then a comma. This word is the name of the object // in the .md3 file. Remember, each .md3 file can have many sub-objects. // The next bit of text is the Quake3 path into the .pk3 file where the // texture for that model is stored Since we don't use the Quake3 path // because we aren't making Quake, I just grab the texture name at the // end of the string and disregard the rest. of course, later this is // concatenated to the original MODEL_PATH that we passed into load our character. // So, for the torso object it's clear that default.bmp is assigned to it, where // as the head model with the pony tail, is assigned to default_h.bmp. Simple enough. // What this function does is go through all the lines of the .skin file, and then // goes through all of the sub-objects in the .md3 file to see if their name is // in that line as a sub string. We use our cool IsInString() function for that. // If it IS in that line, then we know that we need to grab it's texture file at // the end of the line. I just parse backwards until I find the last '/' character, // then copy all the characters from that index + 1 on (I.E. "default.bmp"). // Remember, it's important to note that I changed the texture files from .tga // files to .bmp files because that is what all of our tutorials use. That way // you don't have to sift through tons of image loading code. You can write or // get your own if you really want to use the .tga format. try { // Wrap a buffer to make reading more efficient (faster) BufferedReader reader = new BufferedReader(new FileReader(fileSkin)); // These 2 variables are for reading in each line from the file, then storing // the index of where the bitmap name starts after the last '/' character. String strLine; int textureNameStart = 0; // Go through every line in the .skin file while ((strLine = reader.readLine()) != null) { // Loop through all of our objects to test if their name is in this line for (int i = 0; i < model.getObject().size(); i++) { // Check if the name of this object appears in this line from the skin file if (strLine.contains(model.getObject(i).getName())) { // To extract the texture name, we loop through the string, starting // at the end of it until we find a '/' character, then save that index + 1. textureNameStart = strLine.lastIndexOf("/") + 1; // Create a local material info structure MaterialInfo texture = new MaterialInfo(); // Copy the name of the file into our texture file name variable. texture.setName(strLine.substring(textureNameStart)); // The tile or scale for the UV's is 1 to 1 (but Quake saves off a 0-256 ratio) texture.setUTile(1); texture.setVTile(1); // Add the local material info to our model's material list // Store the material ID for this object and set the texture boolean to true model.getObject(i).setMaterialID(model.getMaterials().size()); model.getObject(i).setbHasTexture(true); // Add the local material info structure to our model's material list model.addMaterials(texture); } } } // Close the file and return a success reader.close(); } catch (Exception e) { return false; } return true; }
private void readMD3Data(ModelMD3 model) throws Exception { int i; // Here we allocate memory for the bone information and read the bones in. bones = new BoneMD3[header.numFrames]; for (i = 0; i < header.numFrames; i++) bones[i] = new BoneMD3(); // Free the unused bones bones = null; // Next, after the bones are read in, we need to read in the tags. model.setNumTags(header.numFrames * header.numTags); for (i = 0; i < model.getTags().length; i++) { TagMD3 pTags = new TagMD3(); model.setTags(pTags, i); } // Assign the number of tags to our model model.setNumOfTags(header.numTags); // Now we want to initialize our links. model.setNumLinks(header.numTags); // Get the current offset into the file // loader.markPos(); int meshOffset = loader.getFileIndex(); // Create a local meshHeader that stores the info about the mesh MeshInfoMD3 meshHeader; // Go through all of the sub-objects in this mesh for (int j = 0; j < header.numMeshes; j++) { // Seek to the start of this mesh and read in it's header loader.setOffset(meshOffset); meshHeader = new MeshInfoMD3(); // Here we allocate all of our memory from the header's information skins = new SkinMD3[meshHeader.numSkins]; texCoords = new TexCoordMD3[meshHeader.numVertices]; triangles = new FaceMD3[meshHeader.numTriangles]; vertices = new TriangleMD3[meshHeader.numVertices * meshHeader.numMeshFrames]; // Read in the skin information loader.setOffset(meshOffset + meshHeader.numSkins); for (i = 0; i < meshHeader.numSkins; i++) skins[i] = new SkinMD3(); // Seek to the start of the triangle/face data, then read it in loader.setOffset(meshOffset + meshHeader.triStart); for (i = 0; i < meshHeader.numTriangles; i++) triangles[i] = new FaceMD3(); // Seek to the start of the UV coordinate data, then read it in loader.setOffset(meshOffset + meshHeader.uvStart); for (i = 0; i < meshHeader.numVertices; i++) texCoords[i] = new TexCoordMD3(); // Seek to the start of the vertex/face index information, then read it in. loader.setOffset(meshOffset + meshHeader.vertexStart); for (i = 0; i < meshHeader.numMeshFrames * meshHeader.numVertices; i++) vertices[i] = new TriangleMD3(); // Now that we have the data loaded into the md3 structures, let's convert them to // our data types like ModelMD3 and Object3D. convertDataStructures(model, meshHeader); // Free all the memory for this mesh since we just converted it to our structures skins = null; texCoords = null; triangles = null; vertices = null; // Increase the offset into the file meshOffset += meshHeader.meshSize; } }