Java写OpenGL项目时总要去加载一个Obj模型,或者导出导入操作,没必要用一大堆第三方包,一个类完事,兼容Window和Android
测试可以打开3DMax导出的Obj格式
导出的Obj也可以在3DMax打开
该类仅满足我个人的需求,不是完整的Obj标准
使用方法:
YSOBJModel ysom=new YSOBJModel("OBJ模型数据"/*不填则为自己建造模型*/);
ysom.toModelString();//模型数据转换成字符串
ysom.writeModelString(new FileOutputStream("路径"));//跟上述一样,直接写入文件可以支持大文本。
ysom.vertex;//顶点坐标,三个一组
ysom.vertexTexture;//纹理坐标,两个一组
ysom.vertexNormal;//法线坐标,三个一组
YSOBJModel.Group group=ysom.group[0];//多个面构成的的组
group.name;//组的名字
YSOBJModel.Face face=group.face[0];//获取一个组里的面,对应f xxx
//OBJ模型索引由1开始,而下面解析的索引从0开始。
face.vertexIndex;//顶点的索引
face.textureIndex;//纹理的索引
face.normalIndex;//法线的索引
face.length;//几个索引构成一个面,常规由3或4个顶点构成。一组面可以混合
使用示例
加载OBJ读取数据
YSOBJModel ysom=new YSOBJModel("OBJ模型数据");
YSOBJModel.Group group=ysom.group[0];//多个组需要遍历
YSOBJModel.Face face=group.face[0];//多个面需要遍历
ysom.vertex[face.vertexIndex[0]*3];//获取一个顶点坐标,顶点数据三个一组
ysom.vertexTexture[face.textureIndex[0]*2];//获取一个纹理坐标,纹理数据两个一组
数据输出OBJ
容错机制足够,可以不用纹理、法线坐标
YSOBJModel ysom=new YSOBJModel();
ysom.vertex=new float[]{
-1,0,0,0,1,0,-1,0,0};//三角形坐标
YSOBJModel.Group group=new YSOBJModel.Group();
group.name="测试";
YSOBJModel.Face face=new YSOBJModel.Face();
face.vertexIndex=new int[]{
0,1,2};//添加索引
face.length=3;
group.face=new YSOBJModel.Face[]{
face};
ysom.group=new YSOBJModel.Group[]{
group};
ysom.toModelString();//输出字符串
类代码,可以直接复制到自己工程使用
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
public class YSOBJModel
{
private String lineSeparator;
public float vertex[]=new float[0];//顶点每3个一组
public float vertexTexture[]=new float[0];//纹理坐标每2个一组
public float vertexNormal[]=new float[0];//法线每3个一组
public Group group[]=new Group[0];//每一组obj
public YSOBJModel()
{
lineSeparator=System.getProperty("line.separator");
}
public YSOBJModel(StringBuffer sb)//解析obj文件
{
lineSeparator=System.getProperty("line.separator");
if(sb!=null)
{
sb.append(" ");//数据结尾要多一个字符
//先把顶点拎出来
int vLinePos[]=getStringLinePos(sb,"v ",0,-1);
int vtLinePos[]=getStringLinePos(sb,"vt ",0,-1);
int vnLinePos[]=getStringLinePos(sb,"vn ",0,-1);
ArrayList<Float> v=new ArrayList<>(vLinePos.length*3);
ArrayList<Float> vt=new ArrayList<>(vtLinePos.length*2);
ArrayList<Float> vn=new ArrayList<>(vnLinePos.length*3);
int length=sb.length();
for(int x=0;x<vLinePos.length;x++)
{
int end=length;
if(x<vLinePos.length-1)
{
end