package com.bn.Sample9_4;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import android.content.res.Resources;
import android.util.Log;
public class LoadUtil
{
//求两个向量的叉积
public static float[] getCrossProduct(float x1,float y1,float z1,float x2,float y2,float z2)
{
//求出两个矢量叉积矢量在XYZ轴的分量ABC
float A=y1*z2-y2*z1;
float B=z1*x2-z2*x1;
float C=x1*y2-x2*y1;
return new float[]{A,B,C};
}
//向量规格化
public static float[] vectorNormal(float[] vector)
{
//求向量的模
float module=(float)Math.sqrt(vector[0]*vector[0]+vector[1]*vector[1]+vector[2]*vector[2]);
return new float[]{vector[0]/module,vector[1]/module,vector[2]/module};
}
//从obj文件中加载携带顶点信息的物体,并自动计算每个顶点的平均法向量
public static LoadedObjectVertexNormalTexture loadFromFile
(String fname, Resources r,MySurfaceView mv)
{
//加载后物体的引用
LoadedObjectVertexNormalTexture lo=null;
//原始顶点坐标列表--直接从obj文件中加载
ArrayList<Float> alv=new ArrayList<Float>();
//顶点组装面索引列表--根据面的信息从文件中加载
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();
//结果顶点坐标列表--按面组织好
ArrayList<Float> alvResult=new ArrayList<Float>();
//平均前各个索引对应的点的法向量集合Map
//此HashMap的key为点的索引, value为点所在的各个面的法向量的集合
HashMap<Integer,HashSet<Normal>> hmn=new HashMap<Integer,HashSet<Normal>>();
//原始纹理坐标列表
ArrayList<Float> alt=new ArrayList<Float>();
//纹理坐标结果列表
ArrayList<Float> altResult=new ArrayList<Float>();
try
{
InputStream in=r.getAssets().open(fname);
InputStreamReader isr=new InputStreamReader(in);
BufferedReader br=new BufferedReader(isr);
String temps=null;
//扫面文件,根据行类型的不同执行不同的处理逻辑
while((temps=br.readLine())!=null)
{
//用空格分割行中的各个组成部分
String[] tempsa=temps.split("[ ]+");
if(tempsa[0].trim().equals("v"))
{//此行为顶点坐标
//若为顶点坐标行则提取出此顶点的XYZ坐标添加到原始顶点坐标列表中
alv.add(Float.parseFloat(tempsa[1]));
alv.add(Float.parseFloat(tempsa[2]));
alv.add(Float.parseFloat(tempsa[3]));
}
else if(tempsa[0].trim().equals("vt"))
{//此行为纹理坐标行
//若为纹理坐标行则提取ST坐标并添加进原始纹理坐标列表中
alt.add(Float.parseFloat(tempsa[1])/2.0f);
alt.add(Float.parseFloat(tempsa[2])/2.0f);
}
else if(tempsa[0].trim().equals("f"))
{//此行为三角形面
/*
*若为三角形面行则根据 组成面的顶点的索引从原始顶点坐标列表中
*提取相应的顶点坐标值添加到结果顶点坐标列表中,同时根据三个
*顶点的坐标计算出此面的法向量并添加到平均前各个索引对应的点
*的法向量集合组成的Map中
*/
int[] index=new int[3];//三个顶点索引值的数组
//计算第0个顶点的索引,并获取此顶点的XYZ三个坐标
index[0]=Integer.parseInt(tempsa[1].split("/")[0])-1;
float x0=alv.get(3*index[0]);
float y0=alv.get(3*index[0]+1);
float z0=alv.get(3*index[0]+2);
alvResult.add(x0);
alvResult.add(y0);
alvResult.add(z0);
//计算第1个顶点的索引,并获取此顶点的XYZ三个坐标
index[1]=Integer.parseInt(tempsa[2].split("/")[0])-1;
float x1=alv.get(3*index[1]);
float y1=alv.get(3*index[1]+1);
float z1=alv.get(3*index[1]+2);
alvResult.add(x1);
alvResult.add(y1);
alvResult.add(z1);
//计算第2个顶点的索引,并获取此顶点的XYZ三个坐标
index[2]=Integer.parseInt(tempsa[3].split("/")[0])-1;
float x2=alv.get(3*index[2]);
float y2=alv.get(3*index[2]+1);
float z2=alv.get(3*index[2]+2);
alvResult.add(x2);
alvResult.add(y2);
alvResult.add(z2);
//记录此面的顶点索引
alFaceIndex.add(index[0]);
alFaceIndex.add(index[1]);
alFaceIndex.add(index[2]);
//通过三角形面两个边向量0-1,0-2求叉积得到此面的法向量
//求0号点到1号点的向量
float vxa=x1-x0;
float vya=y1-y0;
float vza=z1-z0;
//求0号点到2号点的向量
float vxb=x2-x0;
float vyb=y2-y0;
float vzb=z2-z0;
//通过求两个向量的叉积计算法向量
float[] vNormal=vectorNormal(getCrossProduct
(
vxa,vya,vza,vxb,vyb,vzb
));
for(int tempInxex:index)
{//记录每个索引点的法向量到平均前各个索引对应的点的法向量集合组成的Map中
//获取当前索引对应点的法向量集合
HashSet<Normal> hsn=hmn.get(tempInxex);
if(hsn==null)
{//若集合不存在则创建
hsn=new HashSet<Normal>();
}
//将此点的法向量添加到集合中
//由于Normal类重写了equals方法,因此同样的法向量不会重复出现在此点
//对应的法向量集合中
hsn.add(new Normal(vNormal[0],vNormal[1],vNormal[2]));
//将集合放进HsahMap中
hmn.put(tempInxex, hsn);
}
//将纹理坐标组织到结果纹理坐标列表中
//第0个顶点的纹理坐标
int indexTex=Integer.parseInt(tempsa[1].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第1个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[2].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
//第2个顶点的纹理坐标
indexTex=Integer.parseInt(tempsa[3].split("/")[1])-1;
altResult.add(alt.get(indexTex*2));
altResult.add(alt.get(indexTex*2+1));
}
}
//生成顶点数组
int size=alvResult.size();
float[] vXYZ=new float[size];
for(int i=0;i<size;i++)
{
vXYZ[i]=alvResult.get(i);
}
//生成法向量数组
float[] nXYZ=new float[alFaceIndex.size()*3];
int c=0;
for(Integer i:alFaceIndex)
{
//根据当前点的索引从Map中取出一个法向量的集合
HashSet<Normal> hsn=hmn.get(i);
//求出平均法向量
float[] tn=Normal.getAverage(hsn);
//将计算出的平均法向量存放到法向量数组中
nXYZ[c++]=tn[0];
nXYZ[c++]=tn[1];
nXYZ[c++]=tn[2];
}
//生成纹理数组
size=altResult.size();
float[] tST=new float[size];
for(int i=0;i<size;i++)
{
tST[i]=altResult.get(i);
}
//创建3D物体对象
lo=new LoadedObjectVertexNormalTexture(mv,vXYZ,nXYZ,tST);
}
catch(Exception e)
{
Log.d("load error", "load error");
e.printStackTrace();
}
return lo;
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
Sample9_4.rar (36个子文件)
Sample9_4
bin
classes.dex 19KB
Sample9_4.apk 166KB
com
bn
Sample9_4
Sample9_4_Activity.class 1KB
R$drawable.class 422B
ShaderUtil.class 3KB
R$attr.class 334B
Normal.class 1KB
LoadedObjectVertexNormalTexture.class 3KB
LoadUtil.class 6KB
R.class 429B
MySurfaceView$SceneRenderer.class 3KB
MySurfaceView.class 3KB
R$string.class 392B
MatrixState.class 3KB
resources.ap_ 154KB
res
drawable-ldpi
icon.png 2KB
drawable-hdpi
icon.png 4KB
ghxp.png 131KB
values
strings.xml 111B
drawable-mdpi
icon.png 3KB
layout
assets
vertex.sh 2KB
ch_t.obj 65KB
frag.sh 439B
default.properties 449B
gen
com
bn
Sample9_4
R.java 540B
.settings
org.eclipse.jdt.core.prefs 629B
src
com
bn
Sample9_4
MatrixState.java 4KB
Normal.java 1KB
MySurfaceView.java 5KB
ShaderUtil.java 4KB
Sample9_4_Activity.java 1KB
LoadUtil.java 7KB
LoadedObjectVertexNormalTexture.java 6KB
.project 845B
.classpath 280B
AndroidManifest.xml 694B
共 36 条
- 1
资源评论
小贝德罗
- 粉丝: 70
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功