Files
Android-OpenGL-Simple/第8章 3D基本形状/Sample8_1/src/com/bn/Sample8_1/CylinderSideL.java
2022-09-19 18:05:01 +08:00

235 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.bn.Sample8_1;
import static com.bn.Sample8_1.ShaderUtil.createProgram;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import android.opengl.GLES20;
//圆柱侧面骨架类
public class CylinderSideL
{
int mProgram;//自定义渲染管线着色器程序id
int muMVPMatrixHandle;//总变换矩阵引用
int maPositionHandle; //顶点位置属性引用
int maColorHandle; //顶点颜色属性引用
int muMMatrixHandle;//位置、旋转、缩放变换矩阵
int maCameraHandle; //摄像机位置属性引用
int maNormalHandle; //顶点法向量属性引用
int maLightLocationHandle;//光源位置属性引用
String mVertexShader;//顶点着色器代码脚本
String mFragmentShader;//片元着色器代码脚本
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
FloatBuffer mColorBuffer; //顶点颜色数据缓冲
FloatBuffer mNormalBuffer;//顶点法向量数据缓冲
int vCount=0;
float xAngle=0;//绕x轴旋转的角度
float yAngle=0;//绕y轴旋转的角度
float zAngle=0;//绕z轴旋转的角度
public CylinderSideL(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[] colors=new float[vCount*4];//顶点颜色值数组
//坐标数据初始化
int count=0;
int colorCount=0;
for(float angdeg=0;Math.ceil(angdeg)<360;angdeg+=angdegSpan)//侧面
{
double angrad=Math.toRadians(angdeg);//当前弧度
double angradNext=Math.toRadians(angdeg+angdegSpan);//下一弧度
//底圆当前点---0
vertices[count++]=(float) (-r*Math.sin(angrad));
vertices[count++]=0;
vertices[count++]=(float) (-r*Math.cos(angrad));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
//顶圆下一点---3
vertices[count++]=(float) (-r*Math.sin(angradNext));
vertices[count++]=h;
vertices[count++]=(float) (-r*Math.cos(angradNext));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
//顶圆当前点---2
vertices[count++]=(float) (-r*Math.sin(angrad));
vertices[count++]=h;
vertices[count++]=(float) (-r*Math.cos(angrad));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
//底圆当前点---0
vertices[count++]=(float) (-r*Math.sin(angrad));
vertices[count++]=0;
vertices[count++]=(float) (-r*Math.cos(angrad));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
//底圆下一点---1
vertices[count++]=(float) (-r*Math.sin(angradNext));
vertices[count++]=0;
vertices[count++]=(float) (-r*Math.cos(angradNext));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
//顶圆下一点---3
vertices[count++]=(float) (-r*Math.sin(angradNext));
vertices[count++]=h;
vertices[count++]=(float) (-r*Math.cos(angradNext));
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
colors[colorCount++]=1;
}
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
vbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
mVertexBuffer.position(0);//设置缓冲区起始位置
//法向量数据初始化
for(int i=0;i<vertices.length;i++){
if(i%3==1){
vertices[i]=0;
}
}
ByteBuffer nbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点法向量数据缓冲
nbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mNormalBuffer = nbb.asFloatBuffer();//转换为float型缓冲
mNormalBuffer.put(vertices);//向缓冲区中放入顶点法向量数据
mNormalBuffer.position(0);//设置缓冲区起始位置
//创建顶点着色数据缓冲
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());//设置字节顺序为本地操作系统顺序
mColorBuffer = cbb.asFloatBuffer();//转换为Float型缓冲
mColorBuffer.put(colors);//向缓冲区中放入顶点着色数据
mColorBuffer.position(0);//设置缓冲区起始位置
}
//初始化着色器
public void initShader(MySurfaceView mv)
{
//加载顶点着色器的脚本内容
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_color_light.sh", mv.getResources());
//加载片元着色器的脚本内容
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_color_light.sh", mv.getResources());
//基于顶点着色器与片元着色器创建程序
mProgram = createProgram(mVertexShader, mFragmentShader);
//获取程序中顶点位置属性引用id
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
//获取程序中顶点颜色属性引用id
maColorHandle= GLES20.glGetAttribLocation(mProgram, "aColor");
//获取程序中总变换矩阵引用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()
{
//制定使用某套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
(
maColorHandle,
4,
GLES20.GL_FLOAT,
false,
4*4,
mColorBuffer
);
//传送顶点法向量数据
GLES20.glVertexAttribPointer
(
maNormalHandle,
4,
GLES20.GL_FLOAT,
false,
3*4,
mNormalBuffer
);
//启用顶点位置数据
GLES20.glEnableVertexAttribArray(maPositionHandle);
//启用顶点颜色数据
GLES20.glEnableVertexAttribArray(maColorHandle);
//启用顶点法向量数据
GLES20.glEnableVertexAttribArray(maNormalHandle);
//绘制线条的粗细
GLES20.glLineWidth(2);
//绘制
GLES20.glDrawArrays(GLES20.GL_LINES, 0, vCount);
}
}