圆锥体
来源:互联网 发布:杭州软件信息技术开发 编辑:程序博客网 时间:2024/05/17 01:02
效果图如下:
1、首先给出的是圆锥面中的顶点坐标、纹理坐标和法向量生成的相关代码:
import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import android.opengl.GLES20;//圆锥侧面public class ConeSide {int mProgram;//自定义渲染管线着色器程序id int muMVPMatrixHandle;//总变换矩阵引用 int maPositionHandle; //顶点位置属性引用 int maTexCoorHandle; //顶点纹理坐标属性引用 int muMMatrixHandle;//位置、旋转、缩放变换矩阵 int maCameraHandle; //摄像机位置属性引用 int maNormalHandle; //顶点法向量属性引用 int maLightLocationHandle;//光源位置属性引用 String mVertexShader;//顶点着色器代码脚本 String mFragmentShader;//片元着色器代码脚本FloatBuffer mVertexBuffer;//顶点坐标数据缓冲FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲FloatBuffer mNormalBuffer;//顶点法向量数据缓冲 int vCount=0; float xAngle=0;//绕x轴旋转的角度 float yAngle=0;//绕y轴旋转的角度 float zAngle=0;//绕z轴旋转的角度 public ConeSide(MySurfaceView mv,float scale,float r,float h,int n) { //调用初始化顶点数据的initVertexData方法 initVertexData(scale,r,h,n); //调用初始化着色器的intShader方法 initShader(mv); } //自定义初始化顶点坐标数据的方法 public void initVertexData( float scale,//尺寸大小 float r,//半径 float h,//高度 int n//切分的份数 ) { r=scale*r; h=scale*h;float angdegSpan=360.0f/n;vCount=3*n*4;//顶点个数,共有3*n*4个三角形,每个三角形都有三个顶点//坐标数据初始化float[] vertices=new float[vCount*3];float[] textures=new float[vCount*2];//顶点纹理S、T坐标值数组float[] normals=new float[vertices.length];//法向量数组//坐标数据初始化int count=0;int stCount=0;int norCount=0;for(float angdeg=0;Math.ceil(angdeg)<360;angdeg+=angdegSpan)//侧面{double angrad=Math.toRadians(angdeg);//当前弧度double angradNext=Math.toRadians(angdeg+angdegSpan);//下一弧度//顶点(圆锥最高的点)vertices[count++]=0; vertices[count++]=h; vertices[count++]=0;//纹理坐标textures[stCount++]=0.5f;//st坐标textures[stCount++]=0;//当前点vertices[count++]=(float) (-r*Math.sin(angrad));vertices[count++]=0;vertices[count++]=(float) (-r*Math.cos(angrad));//纹理坐标textures[stCount++]=(float) (angrad/(2*Math.PI));textures[stCount++]=1;//下一点vertices[count++]=(float) (-r*Math.sin(angradNext));vertices[count++]=0;vertices[count++]=(float) (-r*Math.cos(angradNext));//纹理坐标textures[stCount++]=(float) (angradNext/(2*Math.PI));textures[stCount++]=1;}//法向量数据的初始化for(int i=0;i<vertices.length;i=i+3){//如果当前的顶点为圆锥的最高点if(vertices[i]==0&&vertices[i+1]==h&&vertices[i+2]==0){normals[norCount++]=0;normals[norCount++]=1;normals[norCount++]=0;}else{//当前的顶点为底面圆上的顶点float [] norXYZ=VectorUtil.calConeNormal(//通过三个顶点求出法向量0, 0, 0, //底面圆的中心点vertices[i], vertices[i+1], vertices[i+2], //当前的顶点坐标0, h, 0);//顶点坐标(圆锥最高点)normals[norCount++]=norXYZ[0];normals[norCount++]=norXYZ[1];normals[norCount++]=norXYZ[2];}}ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲 vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序 mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲 mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据 mVertexBuffer.position(0);//设置缓冲区起始位置 //法向量数据初始化 ByteBuffer nbb = ByteBuffer.allocateDirect(normals.length*4);//创建顶点法向量数据缓冲 nbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序 mNormalBuffer = nbb.asFloatBuffer();//转换为float型缓冲 mNormalBuffer.put(normals);//向缓冲区中放入顶点法向量数据 mNormalBuffer.position(0);//设置缓冲区起始位置 //st坐标数据初始化 ByteBuffer cbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲 cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序 mTexCoorBuffer = cbb.asFloatBuffer();//转换为float型缓冲 mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据 mTexCoorBuffer.position(0);//设置缓冲区起始位置 } //自定义初始化着色器的initShader方法 public void initShader(MySurfaceView mv) { //加载顶点着色器的脚本内容 mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex_light.sh", mv.getResources()); //加载片元着色器的脚本内容 mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex_light.sh", mv.getResources()); //基于顶点着色器与片元着色器创建程序 mProgram = createProgram(mVertexShader, mFragmentShader); //获取程序中顶点位置属性引用id maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); //获取程序中顶点纹理坐标属性引用id maTexCoorHandle= GLES20.glGetAttribLocation(mProgram, "aTexCoor"); //获取程序中总变换矩阵引用id muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); //获取程序中顶点法向量属性引用id maNormalHandle= GLES20.glGetAttribLocation(mProgram, "aNormal"); //获取程序中摄像机位置引用id maCameraHandle=GLES20.glGetUniformLocation(mProgram, "uCamera"); //获取程序中光源位置引用id maLightLocationHandle=GLES20.glGetUniformLocation(mProgram, "uLightLocation"); //获取位置、旋转变换矩阵引用id muMMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMMatrix"); } public void drawSelf(int texId) { //制定使用某套shader程序 GLES20.glUseProgram(mProgram); //将最终变换矩阵传入shader程序 GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0); //将位置、旋转变换矩阵传入shader程序 GLES20.glUniformMatrix4fv(muMMatrixHandle, 1, false, MatrixState.getMMatrix(), 0); //将摄像机位置传入shader程序 GLES20.glUniform3fv(maCameraHandle, 1, MatrixState.cameraFB); //将光源位置传入shader程序 GLES20.glUniform3fv(maLightLocationHandle, 1, MatrixState.lightPositionFB); //传送顶点位置数据 GLES20.glVertexAttribPointer ( maPositionHandle, 3, GLES20.GL_FLOAT, false, 3*4, mVertexBuffer ); //传送顶点纹理坐标数据 GLES20.glVertexAttribPointer ( maTexCoorHandle, 2, GLES20.GL_FLOAT, false, 2*4, mTexCoorBuffer ); //传送顶点法向量数据 GLES20.glVertexAttribPointer ( maNormalHandle, 4, GLES20.GL_FLOAT, false, 3*4, mNormalBuffer ); //启用顶点位置数据 GLES20.glEnableVertexAttribArray(maPositionHandle); //启用顶点纹理数据 GLES20.glEnableVertexAttribArray(maTexCoorHandle); //启用顶点法向量数据 GLES20.glEnableVertexAttribArray(maNormalHandle); //绑定纹理 GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId); //绘制纹理矩形 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount); }}
2、接着给出的是用于计算圆锥面顶点法向量的工具类:
public class VectorUtil {//计算圆锥顶点法向量的方法public static float[] calConeNormal(//三角形三个顶点坐标float x0,float y0,float z0,//A,中心点(底面圆的圆心)float x1,float y1,float z1,//B,底面圆上一点float x2,float y2,float z2 //C,顶点(最高的点)){float[] a={x1-x0, y1-y0, z1-z0};//向量ABfloat[] b={x2-x0, y2-y0, z2-z0};//向量ACfloat[] c={x2-x1, y2-y1, z2-z1};//向量BC//先球垂直于平面ABC的向量kfloat[] k=crossTwoVectors(a,b);//将c和k做叉乘,得出所求向量dfloat[] d=crossTwoVectors(c,k);return normalizeVector(d);//返回规格化后的法向量}//向量规格化的方法public static float[] normalizeVector(float [] vec){float mod=module(vec);return new float[]{vec[0]/mod, vec[1]/mod, vec[2]/mod};//返回规格化后的向量}//求向量的模的方法public static float module(float [] vec){return (float) Math.sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);}//两个向量叉乘的方法public static float[] crossTwoVectors(float[] a,float[] b){float x=a[1]*b[2]-a[2]*b[1];float y=a[2]*b[0]-a[0]*b[2];float z=a[0]*b[1]-a[1]*b[0];return new float[]{x, y, z};//返回法向量}}
0 0
- 圆锥体
- 圆锥体
- Cone圆锥体节点
- 从头开始绘制一个圆锥体
- opengles绘制圆锥体(光照+纹理)
- opengles绘制圆锥体(光照+纹理)
- 绘制一个被雾化的圆锥体
- Direct3D 9 入门例子程序 圆锥体
- 如何用几何画板绘制立体圆锥体
- [unity]在unity中创建圆锥体
- Unity之Handles绘制圆锥体立方体圆柱体五
- 算法:从键盘输入圆锥体的底面半径r=2.5米、高=5米等值,编写程序计算其体积
- android 添加随意拖动的桌面悬浮窗口
- 基于Freemarker的eclipse plugin代码生成器插件开发
- 无线传感网:基于6LoWPAN服务发现与控制协议(SDCP)的设计草稿
- 多态
- VC注册表操作
- 圆锥体
- P2P、P2C 、O2O 、B2C、B2B、 C2C
- 基于asp.net + easyui框架,一步步学习easyui-datagrid——界面(一)
- Protobuf-net在Unity中的序列化与反序列化
- 《C语言及程序设计》实践项目——数字游戏
- 关于各专业部门停止使用盗版工具软件的几点意见
- VR眼镜探究
- Structs2 HelloWorld-01 环境搭建
- JAVA 命名规则