Reputation: 1
I have an object loader that right now takes in textures but I have tried making some textures and they never turn out exactly how I want also I found out that lot of them use a colour I want in one place and puts it on to a different place that I don't want that colour also I have been using like a texture map thingy that has numbers and letters on it like A1 and so on and have been using that to help texture them and lot of times the numbers are shared in different places in the texture and usally its where I don't want them to be also it takes lot longer to texture them then just make the object and colour it regularly...... So how would I be able to add a materials into my Object Loader.... heres the Object Loader
package renderEngine;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import models.RawModel;
public class OBJLoader {
public static RawModel loadObjModel(String fileName, Loader loader) {
FileReader fr = null;
try {
fr = new FileReader(new File("res/objects/"+fileName+".obj"));
} catch (FileNotFoundException e) {
System.err.println("Could not read file!");
e.printStackTrace();
}
BufferedReader reader = new BufferedReader(fr);
String line;
List<Vector3f> vertices = new ArrayList<Vector3f>();
List<Vector2f> textures = new ArrayList<Vector2f>();
List<Vector3f> normals = new ArrayList<Vector3f>();
List<Integer> indices = new ArrayList<Integer>();
float[] verticesArray = null;
float[] normalsArray = null;
float[] textureArray = null;
int[] indicesArray = null;
try {
while(true) {
line = reader.readLine();
String[] currentLine = line.split(" ");
if(line.startsWith("v ")) {
Vector3f vertex = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]),Float.parseFloat(currentLine[3]));
vertices.add(vertex);
}else if(line.startsWith("vt ")) {
Vector2f texture = new Vector2f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]));
textures.add(texture);
}else if(line.startsWith("vn ")) {
Vector3f normal = new Vector3f(Float.parseFloat(currentLine[1]),Float.parseFloat(currentLine[2]),Float.parseFloat(currentLine[3]));
normals.add(normal);
}else if(line.startsWith("f ")) {
textureArray = new float[vertices.size()*2];
normalsArray = new float[vertices.size()*3];
break;
}
}
while(line!=null) {
if(!line.startsWith("f ")) {
line = reader.readLine();
continue;
}
String[] currentLine = line.split(" ");
String[] vertex1 = currentLine[1].split("/");
String[] vertex2 = currentLine[2].split("/");
String[] vertex3 = currentLine[3].split("/");
processVertex(vertex1,indices,textures,normals,textureArray,normalsArray);
processVertex(vertex2,indices,textures,normals,textureArray,normalsArray);
processVertex(vertex3,indices,textures,normals,textureArray,normalsArray);
line = reader.readLine();
}
reader.close();
}catch(Exception e) {
e.printStackTrace();
}
verticesArray = new float[vertices.size()*3];
indicesArray = new int [indices.size()];
int vertexPointer = 0;
for(Vector3f vertex:vertices) {
verticesArray[vertexPointer++] = vertex.x;
verticesArray[vertexPointer++] = vertex.y;
verticesArray[vertexPointer++] = vertex.z;
}
for(int i=0;i<indices.size();i++) {
indicesArray[i] = indices.get(i);
}
return loader.loadToVAO(verticesArray, textureArray, indicesArray);
}
private static void processVertex(String[] vertexData, List<Integer> indices,List<Vector2f> textures, List<Vector3f> normals,
float[] textureArray, float[] normalsArray) {
int currentVertexPointer = Integer.parseInt(vertexData[0]) - 1;
indices.add(currentVertexPointer);
Vector2f currentTex = textures.get(Integer.parseInt(vertexData[1])-1);
textureArray[currentVertexPointer*2] = currentTex.x;
textureArray[currentVertexPointer*2+1] = 1 - currentTex.y;
Vector3f currentNorm = normals.get(Integer.parseInt(vertexData[2])-1);
normalsArray[currentVertexPointer*3] = currentNorm.x;
normalsArray[currentVertexPointer*3+1] = currentNorm.y;
normalsArray[currentVertexPointer*3+2] = currentNorm.z;
}
}
and heres a little thing I have for material
package textures;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.Texture;
public class Material
{
public Texture texture;
public int id;
public String name;
public Vector3f ambient, diffuse, specular;
public float shininess;
public int shader;
}
So how would I use that so it takes those in the OBJLoader? So I don't have to bother with textures anymore also heres the object loader in use Loaded Object
Also the language it's using is Java so it needs to be a way it can be added in Java..... also i serarched all over the internet and I can't find anything on material/mtl file in LWJGL only stuff to like put it in C++ but this has to be for Java.............
Upvotes: -1
Views: 1164
Reputation: 51845
In order to make this work you have to:
create list of materials with selected "default" material
so you have a struct/class holding all the material properties so you just make a dynamic list of it. You know something like:
List<Material> mat;
You just use whatever dynamic list you have at your disposal (not coding in JAVA so I do not know).
Now add first default material which will be used in case of no material present or selected and also select it as default/selected material:
int ix_mat=0;
mat.add(Material(some default values ...)); // add some default material to list
separate your meshes by used material and optionally also by object to list of meshes
so you should have a dynamic list of meshes (which are empty at start) and each have its own material id and optionally mesh id. And create/chose one default one in case *.obj
file does not contain o
entries.
class Mesh
{
public:
int ix_mat;
... here mesh data ...
};
List<Mesh> mesh;
int ix_mesh=0;
mesh.add(Mesh()); // add new empty mesh to the list
mesh[ix_mesh].ix_mat=ix_mat; // and set its material is default one
handle mtllib filename.mtl
while parsing *.obj
by parsing the filename.mtl
and extracting all the materials from it and add them to the mat
list.
optionally handle o mesh_name
while parsing *.obj
handle usemtl material_name
while parsing *.obj
This means that stuff after this will use material_name
so look at the mat[]
and find material with the same name. If found set ix_mat
to it, if not use ix_mat=0
.
ix_mat=0;
for (i=0;i<mat.count;i++)
if (mat[i].name==material_name)
{ ix_mat=i; break; }
Now find target mesh so loop the mesh and find the one with the same ix_mat
and set ix_mesh to its index. If not found create new such mesh and add it to list.
ix_mesh=-1;
for (i=0;i<mesh.count;i++)
if (mesh.ix_mat==ix_mat)
{ ix_mesh=i; break; }
if (ix_mesh<0) // not found
{
ix_mesh=mesh.count;
mesh.add(Mesh()); // add new empty mesh to the list
mesh[ix_mesh].ix_mat=ix_mat; // and set its material is default one
}
If you handling also objects then you have to test for combination of mat and mesh id or search in only meshes belonging to selected object (depends on if you have single list of meshes or list of lists ...)
handle f
entries while parsing
by add ing the faces to selected mesh[ix_mesh]
render using your materials
simply by setting the glMaterial
properties you use in old GL api or by passing them as uniforms before you render your VBO/VAO
for (i=0;i<mesh.count;i++)
{
// set matrices for mesh[i]
// set material mat[mesh[i].ix_mat]
// render mesh[i]
}
Here example obj (first simple with mtl file I found):
# Blender v2.79 (sub 0) OBJ File: ''
# www.blender.org
mtllib cube3.mtl
o Cube_Cube.000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
vt 0.736102 0.263898
vt 0.263898 0.736102
vt 0.263898 0.263898
vt 0.736102 0.263898
vt 0.263898 0.736102
vt 0.263898 0.263898
vt 0.736102 0.263898
vt 0.263898 0.736102
vt 0.263898 0.263898
vt 0.736102 0.263898
vt 0.263898 0.736102
vt 0.263898 0.263898
vt 0.736102 0.263898
vt 0.263898 0.736102
vt 0.263898 0.263898
vt 0.736102 0.736102
vt 0.736102 0.736102
vt 0.736102 0.736102
vt 0.736102 0.736102
vt 0.736102 0.736102
vn -0.5774 0.5774 0.5774
vn -0.5774 -0.5774 -0.5774
vn -0.5774 -0.5774 0.5774
vn -0.5774 0.5774 -0.5774
vn 0.5774 -0.5774 -0.5774
vn 0.5774 0.5774 -0.5774
vn 0.5774 -0.5774 0.5774
vn 0.5774 0.5774 0.5774
usemtl Material.002
s 1
f 1/1/1 2/2/2 3/3/3
f 4/4/4 5/5/5 2/6/2
f 6/7/6 7/8/7 5/9/5
f 8/10/8 3/11/3 7/12/7
f 5/13/5 3/11/3 2/6/2
f 4/4/4 8/14/8 6/15/6
f 1/1/1 4/16/4 2/2/2
f 4/4/4 6/17/6 5/5/5
f 6/7/6 8/18/8 7/8/7
f 8/10/8 1/19/1 3/11/3
f 5/13/5 7/20/7 3/11/3
f 4/4/4 1/19/1 8/14/8
and it's mtl file:
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material.002
Ns 92.156863
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd cube3.png
Here example of simple C++ parser using textures from mtl file:
Upvotes: 0