初次提交
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Sample8_7</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,12 @@
|
||||
#Wed Nov 30 20:35:20 CST 2011
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.bn.Sample8_7"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<uses-sdk android:minSdkVersion="8" />
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name">
|
||||
<activity android:name=".MyActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -0,0 +1,8 @@
|
||||
precision mediump float;
|
||||
varying vec2 vTextureCoord;//接收从顶点着色器过来的参数
|
||||
uniform sampler2D sTexture;//纹理内容数据
|
||||
void main()
|
||||
{
|
||||
//给此片元从纹理中采样出颜色值
|
||||
gl_FragColor = texture2D(sTexture, vTextureCoord);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
uniform mat4 uMVPMatrix; //总变换矩阵
|
||||
attribute vec3 aPosition; //顶点位置
|
||||
attribute vec2 aTexCoor; //顶点纹理坐标
|
||||
varying vec2 vTextureCoord; //用于传递给片元着色器的变量
|
||||
void main()
|
||||
{
|
||||
gl_Position = uMVPMatrix * vec4(aPosition,1); //根据总变换矩阵计算此次绘制此顶点位置
|
||||
vTextureCoord = aTexCoor;//将接收的纹理坐标传递给片元着色器
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "build.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
|
||||
# Project target.
|
||||
target=android-8
|
||||
@@ -0,0 +1,31 @@
|
||||
/* AUTO-GENERATED FILE. DO NOT MODIFY.
|
||||
*
|
||||
* This class was automatically generated by the
|
||||
* aapt tool from the resource data it found. It
|
||||
* should not be modified by hand.
|
||||
*/
|
||||
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
public final class R {
|
||||
public static final class attr {
|
||||
}
|
||||
public static final class drawable {
|
||||
public static final int icon=0x7f020000;
|
||||
public static final int white=0x7f020001;
|
||||
}
|
||||
public static final class id {
|
||||
public static final int RadioButton01=0x7f050003;
|
||||
public static final int RadioButton02=0x7f050004;
|
||||
public static final int RadioGroup01=0x7f050001;
|
||||
public static final int main_liner=0x7f050000;
|
||||
public static final int textView1=0x7f050002;
|
||||
}
|
||||
public static final class layout {
|
||||
public static final int main=0x7f030000;
|
||||
}
|
||||
public static final class string {
|
||||
public static final int app_name=0x7f040001;
|
||||
public static final int hello=0x7f040000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
-optimizationpasses 5
|
||||
-dontusemixedcaseclassnames
|
||||
-dontskipnonpubliclibraryclasses
|
||||
-dontpreverify
|
||||
-verbose
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:id="@+id/main_liner"
|
||||
>
|
||||
<RadioGroup
|
||||
android:id="@+id/RadioGroup01"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:text="填充方式:"
|
||||
android:id="@+id/textView1"
|
||||
android:textSize="16dip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</TextView>
|
||||
<RadioButton
|
||||
android:text="面填充"
|
||||
android:id="@+id/RadioButton01"
|
||||
android:checked="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
android:text="线填充"
|
||||
android:id="@+id/RadioButton02"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
</RadioButton>
|
||||
</RadioGroup>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="hello">Hello World, Sample9_1Activity!</string>
|
||||
<string name="app_name">Sample8_7</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
public class BNPosition
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
|
||||
public BNPosition(float x,float y)
|
||||
{
|
||||
this.x=(int) x;
|
||||
this.y=(int) y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class BezierUtil
|
||||
{
|
||||
static ArrayList<BNPosition> al=new ArrayList<BNPosition>();
|
||||
|
||||
public static ArrayList<BNPosition> getBezierData(float span)
|
||||
{
|
||||
ArrayList<BNPosition> result=new ArrayList<BNPosition>();
|
||||
|
||||
int n=al.size()-1;
|
||||
|
||||
if(n<1)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
int steps=(int) (1.0f/span);
|
||||
long[] jiechengNA=new long[n+1];
|
||||
|
||||
for(int i=0;i<=n;i++)
|
||||
{
|
||||
jiechengNA[i]=jiecheng(i);
|
||||
}
|
||||
|
||||
for(int i=0;i<=steps;i++)
|
||||
{
|
||||
float t=i*span;
|
||||
if(t>1)
|
||||
{
|
||||
t=1;
|
||||
}
|
||||
float xf=0;
|
||||
float yf=0;
|
||||
|
||||
float[] tka=new float[n+1];
|
||||
float[] otka=new float[n+1];
|
||||
for(int j=0;j<=n;j++)
|
||||
{
|
||||
tka[j]=(float) Math.pow(t, j);
|
||||
otka[j]=(float) Math.pow(1-t, j);
|
||||
}
|
||||
|
||||
for(int k=0;k<=n;k++)
|
||||
{
|
||||
float xs=(jiechengNA[n]/(jiechengNA[k]*jiechengNA[n-k]))*tka[k]*otka[n-k];
|
||||
xf=xf+al.get(k).x*xs;
|
||||
yf=yf+al.get(k).y*xs;
|
||||
}
|
||||
result.add(new BNPosition(xf,yf));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//Çó½×³Ë
|
||||
public static long jiecheng(int n)
|
||||
{
|
||||
long result=1;
|
||||
if(n==0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int i=2;i<=n;i++)
|
||||
{
|
||||
result=result*i;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
/*
|
||||
* 整体建筑物
|
||||
*/
|
||||
|
||||
public class Building {
|
||||
float scale;//建筑的大小
|
||||
|
||||
Top top;//穹顶
|
||||
Tower tower;//塔
|
||||
TowerTop towertop;
|
||||
Cube cube;//立方体
|
||||
Cube cube2;//立方体
|
||||
Cube cube3;//立方体
|
||||
Cube cube4;//立方体
|
||||
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
Building( MySurfaceView mv,
|
||||
float scale,//建筑的大小
|
||||
int nCol,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//创建对象
|
||||
top=new Top(mv,0.5f*scale,nCol,nRow);//穹顶
|
||||
tower=new Tower(mv,1*scale,nCol,nRow);//塔
|
||||
|
||||
towertop=new TowerTop(mv,1*scale,nCol,nRow);//塔
|
||||
|
||||
|
||||
cube=new Cube(mv,1.4f*scale,new float[]{2,3f,3f} );//立方体
|
||||
cube2=new Cube(mv,1.4f*scale,new float[]{2f,3f,2f} );//立方体
|
||||
cube3=new Cube(mv,1.4f*scale,new float[]{1.4f,3f,1.4f} );//立方体
|
||||
|
||||
cube4=new Cube(mv,1.4f*scale,new float[]{10f,1f,10f} );//立方体
|
||||
|
||||
}
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
|
||||
//穹顶
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 0f*scale, 0f);
|
||||
top.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//****************************塔********************************
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(6f*scale, -1.6f*scale, 6f*scale);
|
||||
tower.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//塔
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-6f*scale, -1.6f*scale, 6f*scale);
|
||||
tower.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//塔
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(6f*scale, -1.6f*scale, -6f*scale);
|
||||
tower.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//塔
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-6f*scale, -1.6f*scale, -6f*scale);
|
||||
tower.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
//****************************塔********************************
|
||||
|
||||
//*******************塔顶************************
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-2.5f*scale, -3.8f*scale, 0f);
|
||||
towertop.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(2.5f*scale, -3.8f*scale, 0f);
|
||||
towertop.drawSelf(texId);//穹顶
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//*******************塔顶************************
|
||||
|
||||
//*********************立方体*********************************
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, -2.7f*scale, 0f);
|
||||
MatrixState.translate(0, 0.05f, 0f);
|
||||
cube.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-2.0f*scale, -2.7f*scale, 0f);
|
||||
cube2.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(2.0f*scale, -2.7f*scale, 0f);
|
||||
cube2.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-3.43f*scale, -2.7f*scale, 0f);
|
||||
MatrixState.translate(0, -0.05f, 0f);
|
||||
MatrixState.rotate(45, 0, 1, 0);
|
||||
cube3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(3.43f*scale, -2.7f*scale, 0f);
|
||||
MatrixState.translate(0, -0.05f, 0f);
|
||||
MatrixState.rotate(45, 0, 1, 0);
|
||||
cube3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//*********************立方体*********************************
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, -5f*scale, 0f);
|
||||
cube4.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
public class Constant {
|
||||
public static float DATA_RATIO=0.025f;//数据点的缩放比
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
public class Cube
|
||||
{
|
||||
Texture[] rect=new Texture[6];
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
float a;
|
||||
float b;
|
||||
float c;
|
||||
float scale;//尺寸
|
||||
|
||||
boolean texFlag;//是否绘制纹理的标志位
|
||||
public Cube(MySurfaceView mv,float scale,float[] abc)
|
||||
{
|
||||
a=abc[0];
|
||||
b=abc[1];
|
||||
c=abc[2];
|
||||
rect[0]=new Texture(mv,scale,a,b,1,1);
|
||||
rect[1]=new Texture(mv,scale,a,b,1,1);
|
||||
rect[2]=new Texture(mv,scale,c,b,1,1);
|
||||
rect[3]=new Texture(mv,scale,c,b,1,1);
|
||||
rect[4]=new Texture(mv,scale,a,c,1,1);
|
||||
rect[5]=new Texture(mv,scale,a,c,1,1);
|
||||
// 初始化完成后再改变各量的值
|
||||
|
||||
a*=scale;
|
||||
b*=scale;
|
||||
c*=scale;
|
||||
}
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
//前面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0, 0, c/2);
|
||||
rect[0].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//后面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0, 0, -c/2);
|
||||
MatrixState.rotate(180.0f, 0, 1, 0);
|
||||
rect[1].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//右面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(a/2, 0, 0);
|
||||
MatrixState.rotate(90.0f, 0, 1, 0);
|
||||
rect[2].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//左面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-a/2, 0, 0);
|
||||
MatrixState.rotate(-90.0f, 0, 1, 0);
|
||||
rect[3].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//下面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0, -b/2, 0);
|
||||
MatrixState.rotate(90.0f, 1, 0, 0);
|
||||
rect[4].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//上面
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0, b/2, 0);
|
||||
MatrixState.rotate(-90.0f, 1, 0, 0);
|
||||
rect[5].drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.bn.Sample8_7;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import android.opengl.Matrix;
|
||||
|
||||
//存储系统矩阵状态的类
|
||||
public class MatrixState
|
||||
{
|
||||
private static float[] mProjMatrix = new float[16];//4x4矩阵 投影用
|
||||
private static float[] mVMatrix = new float[16];//摄像机位置朝向9参数矩阵
|
||||
private static float[] currMatrix;//当前变换矩阵
|
||||
public static float[] lightLocation=new float[]{0,0,0};//定位光光源位置
|
||||
public static FloatBuffer cameraFB;
|
||||
public static FloatBuffer lightPositionFB;
|
||||
|
||||
//保护变换矩阵的栈
|
||||
static float[][] mStack=new float[10][16];
|
||||
static int stackTop=-1;
|
||||
|
||||
public static void setInitStack()//获取不变换初始矩阵
|
||||
{
|
||||
currMatrix=new float[16];
|
||||
Matrix.setRotateM(currMatrix, 0, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
public static void pushMatrix()//保护变换矩阵
|
||||
{
|
||||
stackTop++;
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
mStack[stackTop][i]=currMatrix[i];
|
||||
}
|
||||
}
|
||||
|
||||
public static void popMatrix()//恢复变换矩阵
|
||||
{
|
||||
for(int i=0;i<16;i++)
|
||||
{
|
||||
currMatrix[i]=mStack[stackTop][i];
|
||||
}
|
||||
stackTop--;
|
||||
}
|
||||
|
||||
public static void translate(float x,float y,float z)//设置沿xyz轴移动
|
||||
{
|
||||
Matrix.translateM(currMatrix, 0, x, y, z);
|
||||
}
|
||||
|
||||
public static void rotate(float angle,float x,float y,float z)//设置绕xyz轴移动
|
||||
{
|
||||
Matrix.rotateM(currMatrix,0,angle,x,y,z);
|
||||
}
|
||||
|
||||
public static void scale(float x,float y,float z)
|
||||
{
|
||||
Matrix.scaleM(currMatrix,0, x, y, z);
|
||||
}
|
||||
|
||||
//插入自带矩阵
|
||||
public static void matrix(float[] self)
|
||||
{
|
||||
float[] result=new float[16];
|
||||
Matrix.multiplyMM(result,0,currMatrix,0,self,0);
|
||||
currMatrix=result;
|
||||
}
|
||||
|
||||
|
||||
//设置摄像机
|
||||
static ByteBuffer llbb= ByteBuffer.allocateDirect(3*4);
|
||||
static float[] cameraLocation=new float[3];//摄像机位置
|
||||
public static void setCamera
|
||||
(
|
||||
float cx, //摄像机位置x
|
||||
float cy, //摄像机位置y
|
||||
float cz, //摄像机位置z
|
||||
float tx, //摄像机目标点x
|
||||
float ty, //摄像机目标点y
|
||||
float tz, //摄像机目标点z
|
||||
float upx, //摄像机UP向量X分量
|
||||
float upy, //摄像机UP向量Y分量
|
||||
float upz //摄像机UP向量Z分量
|
||||
)
|
||||
{
|
||||
Matrix.setLookAtM
|
||||
(
|
||||
mVMatrix,
|
||||
0,
|
||||
cx,
|
||||
cy,
|
||||
cz,
|
||||
tx,
|
||||
ty,
|
||||
tz,
|
||||
upx,
|
||||
upy,
|
||||
upz
|
||||
);
|
||||
|
||||
cameraLocation[0]=cx;
|
||||
cameraLocation[1]=cy;
|
||||
cameraLocation[2]=cz;
|
||||
|
||||
llbb.clear();
|
||||
llbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
cameraFB=llbb.asFloatBuffer();
|
||||
cameraFB.put(cameraLocation);
|
||||
cameraFB.position(0);
|
||||
}
|
||||
|
||||
//设置透视投影参数
|
||||
public static void setProjectFrustum
|
||||
(
|
||||
float left, //near面的left
|
||||
float right, //near面的right
|
||||
float bottom, //near面的bottom
|
||||
float top, //near面的top
|
||||
float near, //near面距离
|
||||
float far //far面距离
|
||||
)
|
||||
{
|
||||
Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);
|
||||
}
|
||||
|
||||
//设置正交投影参数
|
||||
public static void setProjectOrtho
|
||||
(
|
||||
float left, //near面的left
|
||||
float right, //near面的right
|
||||
float bottom, //near面的bottom
|
||||
float top, //near面的top
|
||||
float near, //near面距离
|
||||
float far //far面距离
|
||||
)
|
||||
{
|
||||
Matrix.orthoM(mProjMatrix, 0, left, right, bottom, top, near, far);
|
||||
}
|
||||
//获取具体物体的总变换矩阵
|
||||
static float[] mMVPMatrix=new float[16];
|
||||
public static float[] getFinalMatrix()
|
||||
{
|
||||
Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, currMatrix, 0);
|
||||
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
|
||||
return mMVPMatrix;
|
||||
}
|
||||
|
||||
//获取具体物体的变换矩阵
|
||||
public static float[] getMMatrix()
|
||||
{
|
||||
return currMatrix;
|
||||
}
|
||||
|
||||
//获取投影矩阵
|
||||
public static float[] getProjMatrix()
|
||||
{
|
||||
return mProjMatrix;
|
||||
}
|
||||
|
||||
//获取摄像机朝向的矩阵
|
||||
public static float[] getCaMatrix()
|
||||
{
|
||||
return mVMatrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//设置灯光位置的方法
|
||||
static ByteBuffer llbbL = ByteBuffer.allocateDirect(3*4);
|
||||
public static void setLightLocation(float x,float y,float z)
|
||||
{
|
||||
llbbL.clear();
|
||||
|
||||
lightLocation[0]=x;
|
||||
lightLocation[1]=y;
|
||||
lightLocation[2]=z;
|
||||
|
||||
llbbL.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
lightPositionFB=llbbL.asFloatBuffer();
|
||||
lightPositionFB.put(lightLocation);
|
||||
lightPositionFB.position(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
|
||||
public class MyActivity extends Activity {
|
||||
MySurfaceView mySurfaceView;
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//设置为全屏
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN ,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
//设置为横屏模式
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
|
||||
//初始化GLSurfaceView
|
||||
mySurfaceView = new MySurfaceView(this);
|
||||
|
||||
//切换到主界面
|
||||
setContentView(mySurfaceView);
|
||||
|
||||
mySurfaceView.requestFocus();//获取焦点
|
||||
mySurfaceView.setFocusableInTouchMode(true);//设置为可触控
|
||||
}
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mySurfaceView.onResume();
|
||||
mySurfaceView.lightFlag=true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mySurfaceView.onPause();
|
||||
mySurfaceView.lightFlag=false;
|
||||
}
|
||||
public boolean onKeyDown(int keyCode,KeyEvent e)
|
||||
{
|
||||
switch(keyCode)
|
||||
{
|
||||
case 4:
|
||||
System.exit(0);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import android.opengl.GLSurfaceView;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLUtils;
|
||||
import android.view.MotionEvent;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
class MySurfaceView extends GLSurfaceView {
|
||||
|
||||
private final float TOUCH_SCALE_FACTOR = 180.0f/480;//角度缩放比例
|
||||
|
||||
private float cameraX=0;//摄像机的位置
|
||||
private float cameraY=0;
|
||||
private float cameraZ=8;
|
||||
|
||||
private float targetX=0;//看点
|
||||
private float targetY=-2;
|
||||
private float targetZ=-15;
|
||||
|
||||
private float sightDis=30;//摄像机和目标的距离
|
||||
private float angdegElevation=45;//仰角
|
||||
private float angdegAzimuth=90;//方位角
|
||||
|
||||
|
||||
|
||||
private float mPreviousY;//上次的触控位置Y坐标
|
||||
private float mPreviousX;//上次的触控位置X坐标
|
||||
|
||||
private SceneRenderer mRenderer;//场景渲染器
|
||||
|
||||
int textureId; //系统分配的纹理id
|
||||
|
||||
boolean lightFlag=true; //光照旋转的标志位
|
||||
|
||||
public MySurfaceView(Context context) {
|
||||
super(context);
|
||||
this.setEGLContextClientVersion(2); //设置使用OPENGL ES2.0
|
||||
mRenderer = new SceneRenderer(); //创建场景渲染器
|
||||
setRenderer(mRenderer); //设置渲染器
|
||||
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);//设置渲染模式为主动渲染
|
||||
}
|
||||
|
||||
//触摸事件回调方法
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent e) {
|
||||
float y = e.getY();
|
||||
float x = e.getX();
|
||||
switch (e.getAction()) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
float dy = y - mPreviousY;//计算触控笔Y位移
|
||||
float dx = x - mPreviousX;//计算触控笔X位移
|
||||
angdegAzimuth += dx * TOUCH_SCALE_FACTOR;//设置沿y轴旋转角度
|
||||
angdegElevation+= dy * TOUCH_SCALE_FACTOR;//设置沿x轴旋转角度
|
||||
|
||||
//方位角
|
||||
if(angdegAzimuth>=360){
|
||||
angdegAzimuth=0;
|
||||
}else if(angdegAzimuth<=0){
|
||||
angdegAzimuth=360;
|
||||
}
|
||||
//仰角
|
||||
if(angdegElevation>=85){
|
||||
angdegElevation=85;
|
||||
}else if(angdegElevation<=0){
|
||||
angdegElevation=0;
|
||||
}
|
||||
}
|
||||
mPreviousY = y;//记录触控笔位置
|
||||
mPreviousX = x;//记录触控笔位置
|
||||
return true;
|
||||
}
|
||||
|
||||
private class SceneRenderer implements GLSurfaceView.Renderer
|
||||
{
|
||||
|
||||
Building building;
|
||||
|
||||
public void onDrawFrame(GL10 gl)
|
||||
{
|
||||
//清除深度缓冲与颜色缓冲
|
||||
GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
double angradElevation=Math.toRadians(angdegElevation);//仰角(弧度)
|
||||
double angradAzimuth=Math.toRadians(angdegAzimuth);//方位角
|
||||
cameraX=(float) (targetX+sightDis*Math.cos(angradElevation)*Math.cos(angradAzimuth));
|
||||
cameraY=(float) (targetY+sightDis*Math.sin(angradElevation));
|
||||
cameraZ=(float) (targetZ+sightDis*Math.cos(angradElevation)*Math.sin(angradAzimuth));
|
||||
|
||||
MatrixState.setCamera(//设置camera位置
|
||||
cameraX, //人眼位置的X
|
||||
cameraY, //人眼位置的Y
|
||||
cameraZ, //人眼位置的Z
|
||||
|
||||
targetX, //人眼球看的点X
|
||||
targetY, //人眼球看的点Y
|
||||
targetZ, //人眼球看的点Z
|
||||
|
||||
0, //头的朝向
|
||||
1,
|
||||
0
|
||||
);
|
||||
|
||||
//保护现场
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0, 0, -15);
|
||||
building.drawSelf(textureId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int width, int height) {
|
||||
//设置视窗大小及位置
|
||||
GLES20.glViewport(0, 0, width, height);
|
||||
//计算GLSurfaceView的宽高比
|
||||
float ratio= (float) width / height;
|
||||
//调用此方法计算产生透视投影矩阵
|
||||
MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 4f, 100);
|
||||
// //调用此方法产生摄像机9参数位置矩阵
|
||||
// MatrixState.setCamera(0,0,8.0f,0f,0f,0f,0f,1.0f,0.0f);
|
||||
|
||||
//初始化光源
|
||||
MatrixState.setLightLocation(10 , 0 , -10);
|
||||
|
||||
//启动一个线程定时修改灯光的位置
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
float redAngle = 0;
|
||||
while(lightFlag)
|
||||
{
|
||||
//根据角度计算灯光的位置
|
||||
redAngle=(redAngle+5)%360;
|
||||
float rx=(float) (15*Math.sin(Math.toRadians(redAngle)));
|
||||
float rz=(float) (15*Math.cos(Math.toRadians(redAngle)));
|
||||
MatrixState.setLightLocation(rx, 0, rz);
|
||||
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
//设置屏幕背景色RGBA
|
||||
GLES20.glClearColor(0.0f,0.0f,0.0f, 1.0f);
|
||||
//启用深度测试
|
||||
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
|
||||
//设置为打开背面剪裁
|
||||
GLES20.glEnable(GLES20.GL_CULL_FACE);
|
||||
//初始化变换矩阵
|
||||
MatrixState.setInitStack();
|
||||
|
||||
//加载纹理
|
||||
textureId=initTexture(R.drawable.white);
|
||||
|
||||
//创建对象
|
||||
building=new Building(MySurfaceView.this,0.8f,8,8);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public int initTexture(int drawableId)//textureId
|
||||
{
|
||||
//生成纹理ID
|
||||
int[] textures = new int[1];
|
||||
GLES20.glGenTextures
|
||||
(
|
||||
1, //产生的纹理id的数量
|
||||
textures, //纹理id的数组
|
||||
0 //偏移量
|
||||
);
|
||||
int textureId=textures[0];
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_CLAMP_TO_EDGE);
|
||||
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_CLAMP_TO_EDGE);
|
||||
|
||||
//通过输入流加载图片===============begin===================
|
||||
InputStream is = this.getResources().openRawResource(drawableId);
|
||||
Bitmap bitmapTmp;
|
||||
try
|
||||
{
|
||||
bitmapTmp = BitmapFactory.decodeStream(is);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
is.close();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//通过输入流加载图片===============end=====================
|
||||
|
||||
//实际加载纹理
|
||||
GLUtils.texImage2D
|
||||
(
|
||||
GLES20.GL_TEXTURE_2D, //纹理类型,在OpenGL ES中必须为GL10.GL_TEXTURE_2D
|
||||
0, //纹理的层次,0表示基本图像层,可以理解为直接贴图
|
||||
bitmapTmp, //纹理图像
|
||||
0 //纹理边框尺寸
|
||||
);
|
||||
bitmapTmp.recycle(); //纹理加载成功后释放图片
|
||||
|
||||
return textureId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.opengl.GLES20;
|
||||
import android.util.Log;
|
||||
|
||||
//加载顶点Shader与片元Shader的工具类
|
||||
public class ShaderUtil
|
||||
{
|
||||
//加载制定shader的方法
|
||||
public static int loadShader
|
||||
(
|
||||
int shaderType, //shader的类型 GLES20.GL_VERTEX_SHADER GLES20.GL_FRAGMENT_SHADER
|
||||
String source //shader的脚本字符串
|
||||
)
|
||||
{
|
||||
//创建一个新shader
|
||||
int shader = GLES20.glCreateShader(shaderType);
|
||||
//若创建成功则加载shader
|
||||
if (shader != 0)
|
||||
{
|
||||
//加载shader的源代码
|
||||
GLES20.glShaderSource(shader, source);
|
||||
//编译shader
|
||||
GLES20.glCompileShader(shader);
|
||||
//存放编译成功shader数量的数组
|
||||
int[] compiled = new int[1];
|
||||
//获取Shader的编译情况
|
||||
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
|
||||
if (compiled[0] == 0)
|
||||
{//若编译失败则显示错误日志并删除此shader
|
||||
Log.e("ES20_ERROR", "Could not compile shader " + shaderType + ":");
|
||||
Log.e("ES20_ERROR", GLES20.glGetShaderInfoLog(shader));
|
||||
GLES20.glDeleteShader(shader);
|
||||
shader = 0;
|
||||
}
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
//创建shader程序的方法
|
||||
public static int createProgram(String vertexSource, String fragmentSource)
|
||||
{
|
||||
//加载顶点着色器
|
||||
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
|
||||
if (vertexShader == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//加载片元着色器
|
||||
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
|
||||
if (pixelShader == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//创建程序
|
||||
int program = GLES20.glCreateProgram();
|
||||
//若程序创建成功则向程序中加入顶点着色器与片元着色器
|
||||
if (program != 0)
|
||||
{
|
||||
//向程序中加入顶点着色器
|
||||
GLES20.glAttachShader(program, vertexShader);
|
||||
checkGlError("glAttachShader");
|
||||
//向程序中加入片元着色器
|
||||
GLES20.glAttachShader(program, pixelShader);
|
||||
checkGlError("glAttachShader");
|
||||
//链接程序
|
||||
GLES20.glLinkProgram(program);
|
||||
//存放链接成功program数量的数组
|
||||
int[] linkStatus = new int[1];
|
||||
//获取program的链接情况
|
||||
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
|
||||
//若链接失败则报错并删除程序
|
||||
if (linkStatus[0] != GLES20.GL_TRUE)
|
||||
{
|
||||
Log.e("ES20_ERROR", "Could not link program: ");
|
||||
Log.e("ES20_ERROR", GLES20.glGetProgramInfoLog(program));
|
||||
GLES20.glDeleteProgram(program);
|
||||
program = 0;
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
//检查每一步操作是否有错误的方法
|
||||
public static void checkGlError(String op)
|
||||
{
|
||||
int error;
|
||||
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR)
|
||||
{
|
||||
Log.e("ES20_ERROR", op + ": glError " + error);
|
||||
throw new RuntimeException(op + ": glError " + error);
|
||||
}
|
||||
}
|
||||
|
||||
//从sh脚本中加载shader内容的方法
|
||||
public static String loadFromAssetsFile(String fname,Resources r)
|
||||
{
|
||||
String result=null;
|
||||
try
|
||||
{
|
||||
InputStream in=r.getAssets().open(fname);
|
||||
int ch=0;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
while((ch=in.read())!=-1)
|
||||
{
|
||||
baos.write(ch);
|
||||
}
|
||||
byte[] buff=baos.toByteArray();
|
||||
baos.close();
|
||||
in.close();
|
||||
result=new String(buff,"UTF-8");
|
||||
result=result.replaceAll("\\r\\n","\n");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import android.opengl.GLES20;
|
||||
/*
|
||||
* 矩形平面类
|
||||
*/
|
||||
public class Texture
|
||||
{
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
public Texture(MySurfaceView mv,float scale,float a, float b, int nS, int nT)
|
||||
{
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,a,b,nS,nT);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale,float a, float b, int nS, int nT) {
|
||||
|
||||
a*=scale;
|
||||
b*=scale;
|
||||
float xOffset=a/2;
|
||||
float yOffset=b/2;
|
||||
vCount=6;
|
||||
//坐标数据初始化
|
||||
float[] vertices=new float[]{
|
||||
-xOffset,-yOffset,0,
|
||||
xOffset,yOffset,0,
|
||||
-xOffset,yOffset,0,
|
||||
|
||||
-xOffset,-yOffset,0,
|
||||
xOffset,-yOffset,0,
|
||||
xOffset,yOffset,0
|
||||
};
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
float[] textures={
|
||||
0,1, 1,0, 0,0,
|
||||
0,1, 1,1, 1,0
|
||||
};
|
||||
//创建顶点着色数据缓冲
|
||||
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.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
/*
|
||||
* 绘制穹顶的类
|
||||
*/
|
||||
|
||||
public class Top {
|
||||
float scale;//穹顶的大小
|
||||
|
||||
TopPart1 top1;//穹顶的第一部分
|
||||
TopPart2 top2;//穹顶的第二部分
|
||||
TopPart3 top3;//穹顶的第三部分
|
||||
TopPart4 top4;//穹顶的第四部分
|
||||
|
||||
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
|
||||
Top(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;//茶壶大小赋值
|
||||
|
||||
//创建对象
|
||||
top1=new TopPart1(mv,0.4f*scale,nCol,nRow);//穹顶的第一部分
|
||||
top2=new TopPart2(mv,0.4f*scale,nCol,nRow);//穹顶的第二部分
|
||||
top3=new TopPart3(mv,0.8f*scale,nCol,nRow);//穹顶的第三部分
|
||||
top4=new TopPart4(mv,0.8f*scale,nCol,nRow);//穹顶的第四部分
|
||||
|
||||
}
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
|
||||
//穹顶的第一部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 4.0f*scale, 0f);
|
||||
top1.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
//穹顶的第二部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 3.7f*scale, 0f);
|
||||
top2.drawSelf(texId);//穹顶的第二部分
|
||||
MatrixState.popMatrix();
|
||||
//穹顶的第三部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 0f*scale, 0f);
|
||||
top3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
//穹顶的第四部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, -1.9f*scale, 0f);
|
||||
top4.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import android.opengl.GLES20;
|
||||
/*
|
||||
* 泰姬陵顶部组建1
|
||||
*/
|
||||
public class TopPart1 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TopPart1(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(-1, 171));
|
||||
BezierUtil.al.add(new BNPosition(14, 191));
|
||||
BezierUtil.al.add(new BNPosition(17, 183));
|
||||
BezierUtil.al.add(new BNPosition(5, 154));
|
||||
BezierUtil.al.add(new BNPosition(31, 274));
|
||||
BezierUtil.al.add(new BNPosition(32, 243));
|
||||
BezierUtil.al.add(new BNPosition(30, 230));
|
||||
BezierUtil.al.add(new BNPosition(0, 253));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵顶部组建2
|
||||
*/
|
||||
public class TopPart2 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TopPart2(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(0, 113));
|
||||
BezierUtil.al.add(new BNPosition(28, 128));
|
||||
BezierUtil.al.add(new BNPosition(57, 150));
|
||||
BezierUtil.al.add(new BNPosition(24, 135));
|
||||
BezierUtil.al.add(new BNPosition(42, 125));
|
||||
BezierUtil.al.add(new BNPosition(36, 152));
|
||||
BezierUtil.al.add(new BNPosition(28, 175));
|
||||
BezierUtil.al.add(new BNPosition(14, 226));
|
||||
BezierUtil.al.add(new BNPosition(38, 191));
|
||||
BezierUtil.al.add(new BNPosition(21, 202));
|
||||
BezierUtil.al.add(new BNPosition(-1, 208));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵顶部组建3
|
||||
*/
|
||||
public class TopPart3 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TopPart3(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(97, 35));
|
||||
BezierUtil.al.add(new BNPosition(165, 175));
|
||||
BezierUtil.al.add(new BNPosition(81, 143));
|
||||
BezierUtil.al.add(new BNPosition(58, 162));
|
||||
BezierUtil.al.add(new BNPosition(42, 172));
|
||||
BezierUtil.al.add(new BNPosition(26, 186));
|
||||
BezierUtil.al.add(new BNPosition(72, 231));
|
||||
BezierUtil.al.add(new BNPosition(38, 187));
|
||||
BezierUtil.al.add(new BNPosition(18, 159));
|
||||
BezierUtil.al.add(new BNPosition(77, 214));
|
||||
BezierUtil.al.add(new BNPosition(83, 186));
|
||||
BezierUtil.al.add(new BNPosition(69, 169));
|
||||
BezierUtil.al.add(new BNPosition(55, 206));
|
||||
BezierUtil.al.add(new BNPosition(0, 246));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵顶部组建4
|
||||
*/
|
||||
public class TopPart4 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TopPart4(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(97, 35));
|
||||
BezierUtil.al.add(new BNPosition(98, 61));
|
||||
BezierUtil.al.add(new BNPosition(100, 92));
|
||||
BezierUtil.al.add(new BNPosition(75, 121));
|
||||
BezierUtil.al.add(new BNPosition(167, 104));
|
||||
BezierUtil.al.add(new BNPosition(81, 74));
|
||||
BezierUtil.al.add(new BNPosition(97, 119));
|
||||
BezierUtil.al.add(new BNPosition(97, 130));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
/*
|
||||
* 绘制塔的类
|
||||
*/
|
||||
public class Tower {
|
||||
float scale;//塔的大小
|
||||
boolean texFlag;//是否绘制纹理的标志位
|
||||
|
||||
TowerPart1 tower1;//塔的第一部分
|
||||
TowerPart2 tower2;//塔中圆柱部分
|
||||
TowerPart3 tower3;//
|
||||
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
|
||||
Tower(MySurfaceView mv,float scale, int nCol ,int nRow){
|
||||
this.scale=scale;//大小赋值
|
||||
//创建对象
|
||||
tower1=new TowerPart1(mv,0.4f*scale,nCol,nRow);//穹顶的第一部分
|
||||
tower2=new TowerPart2(mv,0.35f*scale,nCol,nRow);//穹顶的第二部分
|
||||
tower3=new TowerPart3(mv,0.4f*scale,nCol,nRow);//穹顶的第二部分
|
||||
|
||||
}
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//塔的第一部分——穹顶
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 3.0f*scale, 0f);
|
||||
tower1.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//**************塔的第二部分——四根圆柱****************************************
|
||||
//四根圆柱
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0.62f*scale, 2.15f*scale, 0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-0.62f*scale, 2.15f*scale, 0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0.62f*scale, 2.15f*scale, -0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-0.62f*scale, 2.15f*scale, -0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
//**************塔的第二部分****************************************
|
||||
|
||||
//塔的第一部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 0.7f*scale, 0f);
|
||||
tower3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, -1.4f*scale, 0f);
|
||||
tower3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, -3.55f*scale, 0f);
|
||||
tower3.drawSelf(texId);
|
||||
MatrixState.popMatrix();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵塔顶部组建1
|
||||
*/
|
||||
public class TowerPart1 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TowerPart1(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(76, 91));
|
||||
BezierUtil.al.add(new BNPosition(168, 102));
|
||||
BezierUtil.al.add(new BNPosition(-69, 107));
|
||||
BezierUtil.al.add(new BNPosition(183, 74));
|
||||
BezierUtil.al.add(new BNPosition(143, 205));
|
||||
BezierUtil.al.add(new BNPosition(12, 179));
|
||||
BezierUtil.al.add(new BNPosition(-1, 220));
|
||||
BezierUtil.al.add(new BNPosition(36, 197));
|
||||
BezierUtil.al.add(new BNPosition(6, 165));
|
||||
BezierUtil.al.add(new BNPosition(0, 233));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵顶部组建2
|
||||
*/
|
||||
public class TowerPart2 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TowerPart2(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(22, 94));
|
||||
BezierUtil.al.add(new BNPosition(22, 207));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import static com.bn.Sample8_7.ShaderUtil.createProgram;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
/*
|
||||
* 泰姬陵顶部组建3
|
||||
*/
|
||||
public class TowerPart3 {
|
||||
int mProgram;//自定义渲染管线着色器程序id
|
||||
int muMVPMatrixHandle;//总变换矩阵引用
|
||||
int maPositionHandle; //顶点位置属性引用
|
||||
int maTexCoorHandle; //顶点纹理坐标属性引用
|
||||
|
||||
String mVertexShader;//顶点着色器代码脚本
|
||||
String mFragmentShader;//片元着色器代码脚本
|
||||
|
||||
FloatBuffer mVertexBuffer;//顶点坐标数据缓冲
|
||||
FloatBuffer mTexCoorBuffer;//顶点纹理坐标数据缓冲
|
||||
|
||||
int vCount=0;
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
float scale;
|
||||
|
||||
public TowerPart3(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;
|
||||
//调用初始化顶点数据的initVertexData方法
|
||||
initVertexData(scale,nCol,nRow);
|
||||
//调用初始化着色器的intShader方法
|
||||
initShader(mv);
|
||||
}
|
||||
|
||||
//自定义的初始化顶点数据的方法
|
||||
public void initVertexData(float scale, int nCol ,int nRow //大小,列数,行数(行数要保证可以被1除尽)
|
||||
){
|
||||
//成员变量初始化
|
||||
float angdegSpan=360.0f/nCol;
|
||||
vCount=3*nCol*nRow*2;//顶点个数,共有nColumn*nRow*2个三角形,每个三角形都有三个顶点
|
||||
//坐标数据初始化
|
||||
ArrayList<Float> alVertix=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex=new ArrayList<Integer>();//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
|
||||
//以下是贝赛尔曲线的实现代码
|
||||
BezierUtil.al.clear();//清空数据点列表
|
||||
|
||||
//加入数据点
|
||||
BezierUtil.al.add(new BNPosition(87, 22));
|
||||
BezierUtil.al.add(new BNPosition(83, 229));
|
||||
BezierUtil.al.add(new BNPosition(77, 226));
|
||||
BezierUtil.al.add(new BNPosition(72, 205));
|
||||
BezierUtil.al.add(new BNPosition(75, 233));
|
||||
BezierUtil.al.add(new BNPosition(137, 240));
|
||||
BezierUtil.al.add(new BNPosition(94, 212));
|
||||
BezierUtil.al.add(new BNPosition(65, 248));
|
||||
BezierUtil.al.add(new BNPosition(78, 245));
|
||||
|
||||
|
||||
//通过数据点,获取贝赛尔曲线上的点的列表
|
||||
ArrayList<BNPosition> alCurve=BezierUtil.getBezierData(1.0f/nRow);
|
||||
//顶点
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
double r=alCurve.get(i).x*Constant.DATA_RATIO*scale;//当前圆的半径
|
||||
float y=alCurve.get(i).y*Constant.DATA_RATIO*scale;//当前y值
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列顶点,方便了索引的计算
|
||||
{
|
||||
double angrad=Math.toRadians(angdeg);//当前列弧度
|
||||
float x=(float) (-r*Math.sin(angrad));
|
||||
float z=(float) (-r*Math.cos(angrad));
|
||||
//将计算出来的XYZ坐标加入存放顶点坐标的ArrayList
|
||||
alVertix.add(x); alVertix.add(y); alVertix.add(z);
|
||||
}
|
||||
}
|
||||
//索引
|
||||
for(int i=0;i<nRow;i++){
|
||||
for(int j=0;j<nCol;j++){
|
||||
int index=i*(nCol+1)+j;//当前索引
|
||||
//卷绕索引
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+2);//下一行下一列---3
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
|
||||
alFaceIndex.add(index+1);//下一列---1
|
||||
alFaceIndex.add(index+nCol+1);//下一列---2
|
||||
alFaceIndex.add(index);//当前---0
|
||||
}
|
||||
}
|
||||
//计算卷绕顶点
|
||||
float[] vertices=new float[vCount*3];
|
||||
vertices=VectorUtil.calVertices(alVertix, alFaceIndex);
|
||||
|
||||
//顶点坐标数据初始化
|
||||
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);//创建顶点坐标数据缓冲
|
||||
vbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mVertexBuffer = vbb.asFloatBuffer();//转换为float型缓冲
|
||||
mVertexBuffer.put(vertices);//向缓冲区中放入顶点坐标数据
|
||||
mVertexBuffer.position(0);//设置缓冲区起始位置
|
||||
|
||||
//纹理
|
||||
ArrayList<Float> alST=new ArrayList<Float>();//原顶点列表(未卷绕)
|
||||
|
||||
float yMin=999999999;//y最小值
|
||||
float yMax=0;//y最大值
|
||||
for(BNPosition pos:alCurve){
|
||||
yMin=Math.min(yMin, pos.y);//y最小值
|
||||
yMax=Math.max(yMax, pos.y);//y最大值
|
||||
}
|
||||
for(int i=0;i<nRow+1;i++)
|
||||
{
|
||||
float y=alCurve.get(i).y;//当前y值
|
||||
float t=1-(y-yMin)/(yMax-yMin);//t坐标
|
||||
for(float angdeg=0;Math.ceil(angdeg)<360+angdegSpan;angdeg+=angdegSpan)//重复了一列纹理坐标,以索引的计算
|
||||
{
|
||||
float s=angdeg/360;//s坐标
|
||||
//将计算出来的ST坐标加入存放顶点坐标的ArrayList
|
||||
alST.add(s); alST.add(t);
|
||||
}
|
||||
}
|
||||
//计算卷绕后纹理坐标
|
||||
float[] textures=VectorUtil.calTextures(alST, alFaceIndex);
|
||||
ByteBuffer tbb = ByteBuffer.allocateDirect(textures.length*4);//创建顶点纹理数据缓冲
|
||||
tbb.order(ByteOrder.nativeOrder());//设置字节顺序
|
||||
mTexCoorBuffer = tbb.asFloatBuffer();//转换为float型缓冲
|
||||
mTexCoorBuffer.put(textures);//向缓冲区中放入顶点纹理数据
|
||||
mTexCoorBuffer.position(0);//设置缓冲区起始位置
|
||||
}
|
||||
|
||||
//自定义初始化着色器initShader方法
|
||||
public void initShader(MySurfaceView mv)
|
||||
{
|
||||
//加载顶点着色器的脚本内容
|
||||
mVertexShader=ShaderUtil.loadFromAssetsFile("vertex_tex.sh", mv.getResources());
|
||||
//加载片元着色器的脚本内容
|
||||
mFragmentShader=ShaderUtil.loadFromAssetsFile("frag_tex.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");
|
||||
}
|
||||
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
//制定使用某套shader程序
|
||||
GLES20.glUseProgram(mProgram);
|
||||
|
||||
//将最终变换矩阵传入shader程序
|
||||
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, MatrixState.getFinalMatrix(), 0);
|
||||
|
||||
//传送顶点位置数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maPositionHandle,
|
||||
3,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
3*4,
|
||||
mVertexBuffer
|
||||
);
|
||||
//传送顶点纹理坐标数据
|
||||
GLES20.glVertexAttribPointer
|
||||
(
|
||||
maTexCoorHandle,
|
||||
2,
|
||||
GLES20.GL_FLOAT,
|
||||
false,
|
||||
2*4,
|
||||
mTexCoorBuffer
|
||||
);
|
||||
|
||||
//启用顶点位置数据
|
||||
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
||||
//启用顶点纹理数据
|
||||
GLES20.glEnableVertexAttribArray(maTexCoorHandle);
|
||||
|
||||
//绑定纹理
|
||||
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
||||
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texId);
|
||||
|
||||
//绘制纹理矩形
|
||||
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
/*
|
||||
* 绘制塔顶的类
|
||||
*/
|
||||
public class TowerTop {
|
||||
float scale;//塔的大小
|
||||
|
||||
TowerPart1 tower1;//塔的第一部分
|
||||
TowerPart2 tower2;//塔中圆柱部分
|
||||
TowerPart3 tower3;//
|
||||
|
||||
|
||||
float xAngle=0;//绕x轴旋转的角度
|
||||
float yAngle=0;//绕y轴旋转的角度
|
||||
float zAngle=0;//绕z轴旋转的角度
|
||||
|
||||
TowerTop(MySurfaceView mv,float scale, int nCol ,int nRow)
|
||||
{
|
||||
this.scale=scale;//茶壶大小赋值
|
||||
|
||||
//创建对象
|
||||
tower1=new TowerPart1(mv,0.4f*scale,20,40);//穹顶的第一部分
|
||||
tower2=new TowerPart2(mv,0.35f*scale,20,40);//穹顶的第二部分
|
||||
|
||||
}
|
||||
public void drawSelf(int texId)
|
||||
{
|
||||
MatrixState.rotate(xAngle, 1, 0, 0);
|
||||
MatrixState.rotate(yAngle, 0, 1, 0);
|
||||
MatrixState.rotate(zAngle, 0, 0, 1);
|
||||
|
||||
|
||||
//塔的第一部分
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0f, 3.0f*scale, 0f);
|
||||
tower1.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
//**************塔的第二部分****************************************
|
||||
//四根圆柱
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0.62f*scale, 2.15f*scale, 0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-0.62f*scale, 2.15f*scale, 0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(0.62f*scale, 2.15f*scale, -0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
|
||||
MatrixState.pushMatrix();
|
||||
MatrixState.translate(-0.62f*scale, 2.15f*scale, -0.62f*scale);
|
||||
tower2.drawSelf(texId);//穹顶的第一部分
|
||||
MatrixState.popMatrix();
|
||||
//**************塔的第二部分***************************************
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.bn.Sample8_7;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
//三维坐标系中法向量的工具类
|
||||
public class VectorUtil {
|
||||
|
||||
//根据原纹理坐标和索引,计算卷绕后的纹理的方法
|
||||
public static float[] calTextures(
|
||||
ArrayList<Float> alST,//原纹理坐标列表(未卷绕)
|
||||
ArrayList<Integer> alTexIndex//组织成面的纹理坐标的索引值列表(按逆时针卷绕)
|
||||
)
|
||||
{
|
||||
float[] textures=new float[alTexIndex.size()*2];
|
||||
//生成顶点的数组
|
||||
int stCount=0;
|
||||
for(int i:alTexIndex){
|
||||
textures[stCount++]=alST.get(2*i);
|
||||
textures[stCount++]=alST.get(2*i+1);
|
||||
}
|
||||
return textures;
|
||||
}
|
||||
|
||||
public static float[] calVertices(
|
||||
ArrayList<Float> alv,//原顶点列表(未卷绕)
|
||||
ArrayList<Integer> alFaceIndex//组织成面的顶点的索引值列表(按逆时针卷绕)
|
||||
)
|
||||
{
|
||||
float[] vertices=new float[alFaceIndex.size()*3];
|
||||
//生成顶点的数组
|
||||
int vCount=0;
|
||||
for(int i:alFaceIndex){
|
||||
vertices[vCount++]=alv.get(3*i);
|
||||
vertices[vCount++]=alv.get(3*i+1);
|
||||
vertices[vCount++]=alv.get(3*i+2);
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user