第十章 曲线和表面
学习通过对控制点和结点序列进行调整,创建弯曲和皱折的表面,并学习通过几个较小的表面和更容易处理的NURBS或Bezier表面来组成复杂的表面。还有,学习只用几个指定边界的点来绘制复杂的表面、形状和模式,还学习使用GLU函数库的分格器对象把凹形区域以及中间有洞的区域分解为更为简单的凸形图元。
a) 内部支持的表面 OpenGL所附带的工具函数库(GLU)包含了一些函数,它们可以渲染3种二次方程表面。这些二次方程函数可以渲染球体、圆柱体和圆盘。球体:void gluSphere(GLUQuadricObj *obj, GLdouble radius, Glint slices, Glint stacks);//后两个参数分别表示球体的片(slice)和栈(stack)。圆柱体:void gluCylinder(GLUquadricObj *obj, GLdouble baseRadius, GLdouble topRadius, GLdouble height, Glint slices, GLstacks);// 当topRadius参数为0,从而形成一个圆锥体。圆盘:void gluDisk(GLUquadricObj *, GLdouble innerRadius, GLdouble outerRadius, GLint slices, Glint loops);//内半径为0时,表示一个实心的圆盘,不为0则是有洞的圆盘。
b) Bezier曲线和表面这是一种简单的数学模型,仅仅指定几个控制点就可以表示曲线和表面。控制点:曲线是有一组控制点来表示,这些控制点影响着曲线的形状。对Bezier曲线而言,第一个控制点和最后一个控制点实际上是曲线的一部分,其他控制点的作用就像是磁铁,把曲线拉向它们。求值器evaluate:需要制定控制点以及参数方程中u和v参数的定义域。然后,通过调用适当的求值函数,OpenGL可以生成组成曲线或表面的点。
c) NURBS 随着添加的控制点越来越多,创建一条具有良好连续性的曲线将变得非常困难,通过NURBS函数获得更高层次的控制。NURBS的真正威力在于我们可以对一条曲线的任一特定片段的4个控制点所施加的影响进行调整,以产生所需要的平滑性,这种调整是通过一系列的称为结点knot的值进行的。
d) 创建NURBS表面首先创建一个NURBS对象,这样在调用NURBS相关函数对曲线或表面的外观进行修改时就可以引用它。gluNewNurbsRender函数为NURB创建一个渲染器,gluDeleteNurbsRenderer则用于销毁这个渲染器。定义表面:一个控制点数组和结点序列传递给gluNurbsSurface函数,这个函数位于一对gluBeginSurface/gluEndSurface之间。修剪:在NURBS表面上创建删除部分。在一对gluBeginSurface/gluEndSurface之间,调用gluBeginTrim函数,用gluPwlCurve函数指定一条修剪曲线,然后用gluEndTrim函数完成曲线的修剪。
e) 分格化(tessellation)为了使OpenGL的速度尽可能快,所有的几何图元都必须是凸的。但是许多情况是凹或者是更为复杂,有洞的多边形。为将该形状分解为更容易管理的三角形。分格器回调函数:void gluTessCallback(GLUTesselator *tobj, GLenum which, void (*fn)());第一个参数是分格器对象,第二个参数指定被注册的回调函数的类型,最后一个参数是个指向回调函数本身的指针。
第十一章 这就是管线:更快的几何图形渲染
这章讨论了提高几何图形吞吐量的几种不同方法,使用索引数组、显示列表和顶点数组等方法。还学习如何使用顶点缓冲区对象实现最大限度的性能优化,既有显示列表的速度优势,又具有顶点数组的极大灵活性。
a)显示列表为了提高性能,运用预批处理的方法,使它们能够快速复制到命令缓冲区,以获得更快的执行速度,这种预编译的命令集称为显示列表。
b)顶点数组创建一些数组,存储模型所使用的顶点数据,从而大大地节省计算时间。步骤:加载几何图形,启用数组,读取数据,用数据绘图。
c)索引顶点数组就是并不按顺序从头遍历到尾的顶点数组,它的访问顺序是由一个单独的索引数组指定。可以节省内存,并减少变换开销。
d)顶点缓冲区对象当使用顶点数组时,可以把单个的数组从客户内存传输到图形硬件,此特性称为顶点缓冲区对象,允许我们按照与加载和管理纹理相似的方式使用和管理顶点数组数据。步骤:使用顶点数组,然后创建缓冲区对象,方式与创建纹理对象相似。
使用presentModalViewControllerAnimated方法从A->B->C,若想在C中直接返回A,则可这样实现:
C中返回事件:
然后在B中,
通过广播来实现开机启动activity
1. 创建activity
2. 创建广播
3. 在清单文件中注册
具体实现:
1、界面Activity:SayHello.java
package com.ghstudio.BootStartDemo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class SayHello extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
tv.setText("Hello. I started!");
setContentView(tv);
}
}
2、接收广播消息:BootBroadcastReceiver.java
package com.ghstudio.BootStartDemo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class BootBroadcastReceiver extends BroadcastReceiver {
static final String ACTION = "android.intent.action.BOOT_COMPLETED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION)){
Intent sayHelloIntent=new Intent(context,SayHello.class);
sayHelloIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(sayHelloIntent);
}
}
}
3、配置文件:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ghstudio.BootStartDemo"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".SayHello"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
</application>
<uses-sdk android:minSdkVersion="3" />
<uses-permission
android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
</manifest>
4、完成后,编译出apk 包,安装到模拟器或手机中。关机,重新开机。