当前位置:  编程技术>移动开发
本页文章导读:
    ▪模仿QQ空间的上拉更新的功能实现        模仿QQ空间的下拉更新的功能实现           暑假第三十三天,唯一的感觉就是时间过的好快,转眼间暑假一个月已经过去了,嗯,好快,好快哦!而自己自学android之路还有很长,虽然说:.........
    ▪ OpenGL学习札记        OpenGL学习笔记1、帧缓存:一般指保存我们正在渲染图像的那块内存。渲染可以在显示器屏幕上进行,一个文件上进行,一个AVI中的一帧,或者是一张纹理上。 The frame buffer is the memory of the grap.........
    ▪ 深入显出gstreamer开发       深入浅出gstreamer开发Gstreamer解决什么问题? —上层接口和应用方式的相对稳定与底层接口、平台环境的多样化。例如:codec不同种类不同实现,音视频处理不同,硬件输入、输出、采集播放.........

[1]模仿QQ空间的上拉更新的功能实现
    来源: 互联网  发布时间: 2014-02-18
模仿QQ空间的下拉更新的功能实现

           暑假第三十三天,唯一的感觉就是时间过的好快,转眼间暑假一个月已经过去了,嗯,好快,好快哦!而自己自学android之路还有很长,虽然说:“前途是光明的,但是道路是崎岖的,生活是迷茫的,想家是必须滴... ...”。呵呵,好了废话不多说了,看看今天模仿的QQ空间的下拉更新个应用吧

首先看看布局

1.main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/write"
        android:lines="1"
        android:padding="5px"
        android:singleLine="true"
        android:text="写说说" />

    <TabHost
        android:id="@+id/tabhost"
        android:background="@drawable/bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:id="@+id/linearLayout1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </TabWidget>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

                <LinearLayout
                    android:id="@+id/tab1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    >

                    <com.wang.MyListView
                        android:id="@+id/listView"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
                        />
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab2"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                     >
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab3"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                     >
                </LinearLayout>
            </FrameLayout>
        </LinearLayout>
    </TabHost>

</LinearLayout>
2.list的条目布局list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/imageView_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dp"
        android:src="/blog_article/@drawable/icon/index.html" />

    <TextView
        android:id="@+id/textView_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:textColor="#FFFFFF"
        />

</LinearLayout>

3, 刷新布局refresh.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >

    <RelativeLayout
        android:id="@+id/head_contentLayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="30dp" >

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true" >

            <ImageView
                android:id="@+id/head_arrowImageView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="/blog_article/@drawable/down/index.html" />

            <ProgressBar
                android:id="@+id/head_progressBar"
                
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/head_tipsTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉可以刷新"
                android:textSize="15dp" />

            <TextView
                android:id="@+id/head_lastUpdatedTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="上次更新时间:"
                android:textSize="12dp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>
4.看看主活动实现的过程PullrefreshDemoActivity.xml

package com.wang;

import java.util.LinkedList;

import com.wang.MyListView.OnRefreshListener;

import android.app.Activity;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.BaseAdapter;
import android.widget.TabHost;
import android.widget.TextView;

public class PullrefreshDemoActivity extends Activity {
	private LinkedList<String> data;
	private BaseAdapter adapter;

	public void onCreate(Bundle savedInstanceState) {
		// 去除标题栏
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// 设置全屏,取消状态栏
		this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		 TabHost tabhost=(TabHost)findViewById(R.id.tabhost);
	        tabhost.setup();
	        tabhost.addTab(tabhost.newTabSpec("tab1").setIndicator("好友动态").setContent(R.id.tab1));
	        
	        tabhost.addTab(tabhost.newTabSpec("tab2").setIndicator("我的动态").setContent(R.id.tab2));
	        tabhost.addTab(tabhost.newTabSpec("tab3").setIndicator("我的应用").setContent(R.id.tab3));

		data = new LinkedList<String>();
		for (int i = 30; i < 40; i++) {
			// 输出list——item上的数据
			data.add(String.valueOf("暑假第" + i + "天,我们一直很宅,想家ing ..."));
		}

		final MyListView listView = (MyListView) findViewById(R.id.listView);
		adapter = new BaseAdapter() {

			// 得到一个视图,显示在指定位置上的数据在数据集,可以创建一个视图从XML布局文件
			public View getView(int position, View convertView, ViewGroup parent) {
				// 上下文全局应用程序对象
				convertView = LayoutInflater.from(getApplicationContext())
						.inflate(R.layout.list_item, null);
				// 实例化组件
				TextView textView = (TextView) convertView
						.findViewById(R.id.textView_item);
				// 设置文本本内容
				textView.setText(data.get(position));
				return convertView;
			}

			// 得到行相关联id列表中指定的位置。
			public long getItemId(int position) {
				return position;
			}

			// 获得相关的数据项中的指定位置的数据集
			public Object getItem(int position) {
				return data.get(position);
			}

			// 获得项目在数据集适配器的个数。
			public int getCount() {
				return data.size();
			}

		};

		listView.setAdapter(adapter);

		listView.setonRefreshListener(new OnRefreshListener() {
			public void onRefresh() {

				new AsyncTask<Void, Void, Void>() {
					// ...b表示多个参数
					protected Void doInBackground(Void... params) {
						try {
							// 
							Thread.sleep(1000);
						} catch (Exception e) {
							e.printStackTrace();
						}
							
							// 增加一条数据到list中
							data.addFirst("刷新后内容:每天都是新的一天!!!,親!要努力奋斗哦!!!");
						
						return null;
					}

					protected void onPostExecute(Void result) {
						adapter.notifyDataSetChanged();
						listView.onRefreshComplete();
					}

				}.execute(null);
			}
		});
	}
}

5.接着是列表实现个过程MyListView.xml

package com.wang;

import java.text.SimpleDateFormat;
import java.util.Date;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MyListView extends ListView implements OnScrollListener {

	private static final String TAG = "listview";

	private final static int RELEASE_To_REFRESH = 0;
	private final static int PULL_To_REFRESH = 1;
	private final static int REFRESHING = 2;
	private final static int DONE = 3;
	private final static int LOADING = 4;

	// 实际的padding的距离与界面上偏移距离的比例
	private final static int RATIO = 3;

	private LayoutInflater inflater;

	private LinearLayout headView;

	private TextView tipsTextview;
	private TextView lastUpdatedTextView;
	private ImageView arrowImageView;
	private ProgressBar progressBar;

	private RotateAnimation animation;
	private RotateAnimation reverseAnimation;

	// 用于保证startY的值在一个完整的touch事件中只被记录一次
	private boolean isRecored;

	private int headContentWidth;
	private int headContentHeight;

	private int startY;
	private int firstItemIndex;

	private int state;

	private boolean isBack;

	private OnRefreshListener refreshListener;

	private boolean isRefreshable;

	public MyListView(Context context) {
		super(context);
		// 调用下面初始化的函数
		init(context);
	}

	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		// 调用下面初始化的函数
		init(context);
	}

	private void init(Context context) {

		// 获得LayoutInflater从给定的上下文。
		inflater = LayoutInflater.from(context);

		// 实例化布局XML文件转换成相应的视图对象。
		headView = (LinearLayout) inflater.inflate(R.layout.refresh, null);

		arrowImageView = (ImageView) headView
				.findViewById(R.id.head_arrowImageView);
		// 设置最小宽度 和高度
		arrowImageView.setMinimumWidth(70);
		arrowImageView.setMinimumHeight(50);
		// 实例化布局XML文件转换成相应的视图对象。
		progressBar = (ProgressBar) headView
				.findViewById(R.id.head_progressBar);
		tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
		lastUpdatedTextView = (TextView) headView
				.findViewById(R.id.head_lastUpdatedTextView);

		// 调用下拉刷新的方法
		measureView(headView);
		// d得到原始高度和宽度
		headContentHeight = headView.getMeasuredHeight();
		headContentWidth = headView.getMeasuredWidth();

		// 设置填充。视图可能添加的空间要求显示滚动条,这取决于风格和知名度的滚动条
		headView.setPadding(0, -1 * headContentHeight, 0, 0);
		headView.invalidate();

		// 标签用来识别一个日志消息的来源。标识类或活动日志调用发生
		Log.v("size", "width:" + headContentWidth + " height:"
				+ headContentHeight);

		// 添加一个固定视图出现在列表的顶部
		addHeaderView(headView, null, false);
		// 设置监听事件
		setOnScrollListener(this);

		// 动画效果实现下拉和松开时候图片的 180度 旋转 注意0, -180,和他是有区别的 -180, 0,
		animation = new RotateAnimation(0, -180,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		// 设置加速度曲线为这个动画。默认值为一个线性插值。
		animation.setInterpolator(new LinearInterpolator());
		animation.setDuration(300);
		// 如果fillAfter是真的,转换,该动画执行完成时将会持续下去
		animation.setFillAfter(true);

		reverseAnimation = new RotateAnimation(-180, 0,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		// 设置加速度曲线为这个动画。默认值为一个线性插值。
		reverseAnimation.setInterpolator(new LinearInterpolator());
		reverseAnimation.setDuration(300);
		// 如果fillAfter是真的,转换,该动画执行完成时将会持续下去
		reverseAnimation.setFillAfter(true);

		// 设置状态
		state = DONE;
		// 设置不可刷新状态
		isRefreshable = false;
	}

	// 回调方法时要调用的列表或网格已经滚动。这将完成之后调用的滚动方法
	public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2,
			int arg3) {
		firstItemIndex = firstVisiableItem;
	}

	/*
	 * 回调方法调用而列表视图或网格视图被滚动。 如果这个视图被滚动,将调用此方法在接下来的一局画卷的呈现 *
	 */
	public void onScrollStateChanged(AbsListView arg0, int arg1) {
	}

	// 触摸事件监听
	public boolean onTouchEvent(MotionEvent event) {

		// 判断是否可以刷新
		if (isRefreshable) {
			// 根据动作相应不同的方法
			switch (event.getAction()) {

			// 当按住屏幕向下拉屏幕的时候
			case MotionEvent.ACTION_DOWN:
				if (firstItemIndex == 0 && !isRecored) {
					isRecored = true;
					startY = (int) event.getY();
					Log.v(TAG, "在下拉的时候记录当前位置‘");
				}
				break;

			// 当按住屏幕向上松屏幕的时候
			case MotionEvent.ACTION_UP:

				if (state != REFRESHING && state != LOADING) {
					if (state == DONE) {

					}
					if (state == PULL_To_REFRESH) {
						state = DONE;
						changeHeaderViewByState();

						Log.v(TAG, "由下拉刷新状态,到done状态");
					}
					if (state == RELEASE_To_REFRESH) {
						state = REFRESHING;
						changeHeaderViewByState();
						onRefresh();

						Log.v(TAG, "由松开刷新状态,到done状态");
					}
				}

				isRecored = false;
				isBack = false;

				break;

			// 当按住屏幕移动时候
			case MotionEvent.ACTION_MOVE:
				int tempY = (int) event.getY();

				if (!isRecored && firstItemIndex == 0) {
					Log.v(TAG, "在move时候记录下位置");
					isRecored = true;
					startY = tempY;
				}

				if (state != REFRESHING && isRecored && state != LOADING) {

					/***
					 * , 当前的位置一直是在head,否则如果当列表超出屏幕的话, 当在上推的时候,列表会同时进行滚动
					 */
					// 可以松手去刷新了
					if (state == RELEASE_To_REFRESH) {

						setSelection(0);

						// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步
						if (((tempY - startY) / RATIO < headContentHeight)
								&& (tempY - startY) > 0) {
							state = PULL_To_REFRESH;
							changeHeaderViewByState();

							Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");
						}
						// 一下子推到顶了
						else if (tempY - startY <= 0) {
							state = DONE;
							// 调用改变时候的方法,更新UI
							changeHeaderViewByState();

							Log.v(TAG, "由松开刷新状态转变到done状态");
						} else {
						}
					}
					// 还没有到达显示松开刷新的时候
					if (state == PULL_To_REFRESH) {

						setSelection(0);

						// 下拉到可以进入RELEASE_TO_REFRESH的状态
						if ((tempY - startY) / RATIO >= headContentHeight) {
							state = RELEASE_To_REFRESH;
							isBack = true;
							// 调用改变时候的方法,更新UI
							changeHeaderViewByState();

							Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");
						}
						// 上推到顶了
						else if (tempY - startY <= 0) {
							state = DONE;
							// 调用改变时候的方法,更新UI
							changeHeaderViewByState();

							Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");
						}
					}

					// done状态下
					if (state == DONE) {
						if (tempY - startY > 0) {
							state = PULL_To_REFRESH;
							// 调用改变时候的方法,更新UI
							changeHeaderViewByState();
						}
					}

					// 更新headView的size
					if (state == PULL_To_REFRESH) {
						headView.setPadding(0, -1 * headContentHeight
								+ (tempY - startY) / RATIO, 0, 0);

					}

					// 更新headView的paddingTop
					if (state == RELEASE_To_REFRESH) {
						headView.setPadding(0, (tempY - startY) / RATIO
								- headContentHeight, 0, 0);
					}

				}

				break;
			}
		}

		return super.onTouchEvent(event);
	}

	// 当状态改变时候,调用该方法,以更新界面
	private void changeHeaderViewByState() {
		// 根据当前的状态进行判断
		switch (state) {

		// 下拉时候,松开既可刷新
		case RELEASE_To_REFRESH:
			// 设置视图 VISIBLE 可见 ,GONE 不可见
			arrowImageView.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			// 现在开始指定的动画。
			arrowImageView.clearAnimation();
			arrowImageView.startAnimation(animation);

			tipsTextview.setText("松开既可刷新");

			Log.v(TAG, "当前状态,松开即可刷新");
			break;

		// 开始时候,下拉刷新
		case PULL_To_REFRESH:
			// 设置视图 VISIBLE 可见 ,GONE 不可见
			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);
			// 现在开始指定的动画。
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.VISIBLE);

			if (isBack) {
				isBack = false;
				// 现在开始指定的动画。
				arrowImageView.clearAnimation();
				arrowImageView.startAnimation(reverseAnimation);

				tipsTextview.setText("下拉刷新");
			} else {
				tipsTextview.setText("下拉刷新");
			}
			Log.v(TAG, "当前状态,下拉刷新");
			break;

		case REFRESHING:

			headView.setPadding(0, 0, 0, 0);
			// 设置视图 VISIBLE 可见 ,GONE 不可见
			progressBar.setVisibility(View.VISIBLE);
			// 现在开始指定的动画。
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.GONE);
			tipsTextview.setText("正在刷新...");
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			Log.v(TAG, "当前状态,正在刷新...");
			break;
		case DONE:
			// 设置填充。视图可能添加的空间要求显示滚动条
			headView.setPadding(0, -1 * headContentHeight, 0, 0);
			// 设置视图 VISIBLE 可见 ,GONE 不可见
			progressBar.setVisibility(View.GONE);
			// 现在开始指定的动画。
			arrowImageView.clearAnimation();
			arrowImageView.setImageResource(R.drawable.down);
			tipsTextview.setText("下拉刷新");
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			Log.v(TAG, "当前状态");
			break;
		}
	}

	public void setonRefreshListener(OnRefreshListener refreshListener) {
		this.refreshListener = refreshListener;
		isRefreshable = true;
	}

	public interface OnRefreshListener {
		public void onRefresh();
	}

	// 设置更新时间
	public void onRefreshComplete() {
		state = DONE;
		//
		SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
		String date = format.format(new Date());
		lastUpdatedTextView.setText("最近更新:" + date);
		changeHeaderViewByState();
	}

	private void onRefresh() {
		if (refreshListener != null) {
			refreshListener.onRefresh();
		}
	}

	// 下拉刷新的
	private void measureView(View child) {
		// v这组布局参数宽度和高度
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			// 创建一个新组布局参数指定的宽度(填充)和高度(包裹)。
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
					ViewGroup.LayoutParams.WRAP_CONTENT);
		}

		// d得到childWidthSpec(高度或宽度)的子视图
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			// 创建一个测量规范基于所提供的大小和模式
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,
					MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}
		// 找出一个视图应该多大。父供应约束信息在宽度和高度参数
		child.measure(childWidthSpec, childHeightSpec);
	}

	public void setAdapter(BaseAdapter adapter) {
		// 设置最近刷新的时间
		SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");
		String date = format.format(new Date());
		lastUpdatedTextView.setText("最近更新:" + date);
		super.setAdapter(adapter);
	}

}


6.接着就可以看到运行结果了,运行结果如下:






    
[2] OpenGL学习札记
    来源: 互联网  发布时间: 2014-02-18
OpenGL学习笔记

1、帧缓存:一般指保存我们正在渲染图像的那块内存。渲染可以在显示器屏幕上进行,一个文件上进行,一个AVI中的一帧,或者是一张纹理上。

The frame buffer is the memory of the graphics display device, which means the image is displayed on your screen.

OpenGL does not render (draw) these primitives directly on the screen. Instead, rendering is done in a buffer, which is later swapped to the screen. We refer to these two buffers as thefront(the screen) and back color buffers. By default, OpenGL commands are rendered into the back buffer, and when you call glutSwapBuffers (or your operating system–specific buffer swap function), the front and back buffers are swapped so that you can see the rendering results. You can, however, render directly into the front buffer if you want. (glDrawBuffer)

When you do single-buffered rendering, it is important to call either glFlush or glFinish whenever you want to see the results actually drawn to screen. A buffer swap implicitly performs a flush of the pipeline and waits for rendering to complete before the swap actually occurs. 

2、3D中,水平方向上的缩放值和垂直方向上的比例要适中,否则图像将会变形。一般情况下,这个比例要和显示图像的窗口的水平方向和垂直方向的大小比例保持一致。

3、object space = modeling space = local space     ------------  model transformation

         camera space = eye space

         clip space = canonical view volume space  -------------- clip transformation

4、Two principal tasks are required to create an image of a three-dimensional scene: modeling and rendering. The modeling task generates a model, which is the description of an object that is going to be used by the graphics system. Models must be created for every object in a scene; they should accurately capture the geometric shape and appearance of the object. Some or all of this task commonly occurs when the application is being developed, by creating and storing model descriptions as part of the application’s data. 

The second task, rendering, takes models as input and generates pixel values for the final image. OpenGL is principally concerned with object rendering; it does not provide explicit support for creating object models. The model input data is left to the application to provide. The OpenGL architecture is focused primarily on rendering polygonal models; it doesn’t directly support more complex object descriptions, such as implicit surfaces. 

To provide accurate rendering of a model’s appearance or surface shading, the modeler may also have to determine color values, shading normals, and texture coordinates for the model’s vertices and faces.

5、To smoothly shade an object, a given vertex normal should be used by all polygons that share that vertex. Ideally, this vertex normal is the same as the surface normal at the corresponding point on the original surface. However, if the true surface normal isn’t available, the simplest way to approximate one is to add all (normalized) normals from the common facets then renormalize the result (Gouraud, 1971). This provides reasonable results for surfaces that are fairly smooth, but does not look good for surfaces with sharp edges.

6、Since the polygon winding may be used to cull back or front-facing triangles, for performance reasons it is important that models are made consistent; a polygon wound inconsistently with its neighbors should have its vertex order reversed. A good way to accomplish this is to find all common edges and verify that neighboring polygon edges are drawn in the opposite order.

To ensure that the rewound model is oriented properly (i.e., all polygons are wound so that their front faces are on the outside surface of the object), the algorithm begins by choosing and properly orienting the seed polygon. One way to do this is to find the geometric center of the object: compute the object’s bounding box, then compute its mid-point. Next, select a vertex that is the maximum distance from the center point and compute a (normalized) out vector from the center point to this vertex. One of the polygons using that vertex is chosen as the seed. Compute the normal of the seed polygon, then compute the dot product of the normalwith the out vector. A positive result indicates that seed is oriented correctly. A negative result indicates the polygon’s normal is facing inward. If the seed polygon is backward, reverse its winding before using it to rewind the rest of the model.

7、vertex buffer objects

In OpenGL 1.5, vertex buffer objects were added to the specification to enable the same server placement optimizations that are used with display lists. Vertex buffer objects allow the application to allocate vertex data storage that is managed by the OpenGL implementation and can be allocated from accelerator memory. The application can store vertex data to the buffer using an explicit transfer command (glBufferData), or by mapping the buffer (glMapBuffer). The vertex buffer data can also be examined by the application allowing dynamic modification of the data, though it may be slower if the buffer storage is now in the accelerator. Having dynamic read-write access allows geometric data to be modified each frame, without requiring the application to maintain a separate copy of the data or explicitly copy it to and from the accelerator. Vertex buffer objects are used with the vertex array drawing commands by binding a vertex buffer object to the appropriate array binding point (vertex, color, normal, texture coordinate) using the array point commands (for example, glNormalPointer). When an array has a bound buffer object, the array pointer is interpreted relative to the buffer object storage rather than application memory addresses. 

8、The OpenGL transformation pipeline can be thought of as a series of cartesian coordinate spaces connected by transformations that can be directly set by the application. Five spaces are used: object space, which starts with the application’s coordinates, eye space, where the scene is assembled, clip space, which defines the geometry that will be visible in the scene, NDC space, the canonical space resulting from perspective division, and window space, which maps to the framebuffer’s pixel locations.

The pipeline begins with texture, vertex, and light position coordinates, along with normal vectors, sent down from the application. These untransformed values are said to be in object space. If the application has enabled the generation of object space texture coordinates, they are created here from untransformed vertex positions.

The modelview matrix is typically used to assemble a series of objects into a coherent scene viewed from a particular vantage.

An important use of the modelview matrix is modifying the parameters of OpenGL light sources. When a light position is issued using the glLight() command, the position or direction of the light is transformed by the current modelview matrix before being stored. The transformed position is used in the lighting computations until it’s updated with a new call to glLight().

The eye space coordinate system is where object lighting is applied and eye-space texture coordinate generation occurs. OpenGL makes certain assumptions about eye space. The viewer position is defined to be at the origin of the eye-space coordinate system. The direction of view is assumed to be the negative z-axis, and the viewer’s up position is the y-axis.

Normals are consumed by the pipeline in eye space. If lighting is enabled, they are used by the lighting equation—along with eye position and light positions—to modify the current vertex color. The projection transform transforms the remaining vertex and texture coordinates into clip space. If the projection transform has perspective elements in it, the w values of the transformed vertices are modified.

If new vertices are generated as a result of clipping, the new vertices will have texture coordinates and colors interpolated to match the new vertex positions. The exact shape of the viewvolume depends on the type of projection transform; a perspective transformation results in a frustum (a pyramid with the tip cut off), while an orthographic projection will create a parallelepiped volume.

9. Render: Rendering is the act of taking a geometric description of a three-dimensional object and turning it into an image of that object onscreen. 

10. Perspective: Perspective refers to the angles between lines that lend the illusion of three dimensions.

11. You expect the front of an object to obscure the back of the object from view. For solid surfaces, we call this hidden surface removal.

12. This technique of applying an image to a polygon to supply additional detail is called texture mapping. The image you supply is called a texture, and the individual elements of the texture are called texels. Finally, the process of stretching or compressing the texels over the surface of an object is called filtering.

13. Blending(混合) is the combination of colors or objects on the screen.  By varying the amount each object is blended with the scene, you can make objects look transparent such that you see the object and what is behind it (such as glass or a ghost image).

14.  By carefully blending the lines with the back-ground color, you can eliminate the jagged edges and give the lines a smooth appearance, This blending technique is called antialiasing. 简单的说也就是将图像边缘及其两侧的像素颜色进行混合,然后用新生成的具有混合特性的点来替换原来位置上的点以达到柔化物体外形、消除锯齿的效果。

15. With both immediate mode and retained mode, new commands have no effect on rendering commands that have already been executed.

16. A window is measured physically in terms of pixels. Before you can start plotting points, lines, and shapes in a window, you must tell OpenGL how to translate specified coordinate pairs into screen coordinates. You do this by specifying the region of Cartesian space that occupies the window; this region is known as the clipping region. 

17. Viewports: Mapping Drawing Coordinates to Window Coordinates. Rarely will your clipping area width and height exactly match the width and height of the window in pixels. The coordinate system must therefore be mapped from logical Cartesian coordinates to physical screen pixel coordinates. This mapping is specified by a setting
known as the viewport. The viewport is the region within the window’s client area that is used for drawing the clipping area. The viewport simply maps the clipping area to a region of the window. Usually, the viewport is defined as the entire window, but this is not strictly necessary; for instance, you might want to draw only in the lower half of the window.

18. The Vertex—A Position in Space. A vertex is nothing more than a coordinate in 2D or 3D space. 

19.  Primitives are one- or two-dimensional entities or surfaces such as points, lines, and polygons (a flat, multisided shape) that are assembled in 3D space to create 3D objects. 

20. OpenGL is a procedural rather than a descriptive graphics API. Instead of describing the scene and how it should appear, the programmer actually prescribes the steps necessary to achieve a certain appearance or effect. These “steps” involve calls to the many OpenGL commands. These commands are used to draw graphics primitives such as points, lines, and polygons in three dimensions. In addition, OpenGL supports lighting and shading, texture mapping, blending, transparency, animation, and many other special effects and capabilities.

21. OpenGL的数据类型

  • GLenum: 用于GL枚举的无符号整型。通常用于通知OpenGL由指针传递的存储于数组中数据的类型(例如,GL_FLOAT用于指示数组由GLfloat组成)。
  • GLboolean: 用于单布尔值。OpenGL ES还定义了其自己的“真”和“假”值(GL_TRUE和GL_FALSE)以避免平台和语言的差别。当向OpenGL传递布尔值时,请使用这些值而不是使用YES或NO(尽管由于它们的定义实际没有区别,即使你不小心使用了YES或NO。但是,使用GL-定义值是一个好的习惯。)
  • GLbitfield: 用于将多个布尔值(最多32个)打包到单个使用位操作变量的四字节整型。
  • GLbyte: 有符号单字节整型,包含数值从-128 到 127
  • GLshort: 有符号双字节整型,包含数值从−32,768 到 32,767
  • GLint: 有符号四字节整型,包含数值从−2,147,483,648 到 2,147,483,647
  • GLsizei: 有符号四字节整型,用于代表数据的尺寸(字节),类似于C中的size_t
  • GLubyte: 无符号单字节整型,包含数值从0 到 255。
  • GLushort: 无符号双字节整型,包含数值从0 到 65,535
  • GLuint: 无符号四字节整型,包含数值从0 到 4,294,967,295
  • GLfloat: 四字节精度IEEE 754-1985 浮点数
  • GLclampf: 这也是四字节精度浮点数,但OpenGL使用GLclampf特别表示数值为0.0 到 1.0
  • GLvoid: void值用于指示一个函数没有返回值,或没有参数
  • GLfixed: 定点数 使用整型数存储实数。由于大部分计算机处理器在处理整型数比处理浮点数快很多,这通常是对3D系统的优化方式。
  • GLclampx: 另一种定点型,用于使用定点运算来表示0.0 到 1.0之间的实数。
  • 22. OpenGL uses floats internally, and using anything other than the single-precision floating-point functions adds a performance bottleneck because the values are converted to floats anyhow before being processed by OpenGL.
  • 23.  GLUT_SINGLE: A single-buffered window means that all drawing commands are performed on the window displayed. An alternative is adouble-buffered window, where the drawing commands are actually executed on an offscreen buffer and then quickly swapped into view on the window. This method is often used to produce animation effects. 
  • Double buffering can serve two purposes. The first is that some complex drawings might take a long time to draw, and you might not want each step of the image composition to be visible. Using double buffering, you can compose an image and display it only after it is complete. The user never sees a partial image; only after the entire image is ready is it shown onscreen.  A second use for double buffering is animation. Each frame is drawn in the offscreen buffer and then swapped quickly to the screen when ready. The GLUT library supports double-buffered windows. 
  • 24. alpha component, which is used for blending and special effects such as transparency. Transparency refers to an object’s capability to allow light to pass through it. Suppose you would like to create a piece of red stained glass, and a blue light happens to be shining behind it. The blue light affects the appearance of the red in the glass (blue + red = purple). You can use the alpha component value to generate a red color that is semitransparent so that it works like a sheet of glass—an object  behind it shows through.
  • 25. A buffer is a storage area for image information. The red, green, and blue components of a drawing are usually collectively referred to as the color buffer or pixel buffer.  More than one kind of buffer (color, depth, stencil, and accumulation) is available in OpenGL. You will also see the term framebuffer, which refers to all these buffers collectively since they work in tandem.
  • 26. The aspect ratio is the ratio of the number of pixels along a unit of length in the vertical direction to the number of pixels along the same unit of length in the horizontal direction. In English, this just means the width of the window divided by the height.
  • 27. Rotation: To rotate an object about one of the three coordinate axes, or indeed any arbitrary vector, you have to devise a rotation matrix. Again, a high-level function comes to the rescue: glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); Here, we perform a rotation around the vector specified by the x, y, and z arguments. The
    angle of rotation is in the counterclockwise direction measured in degrees and specified by the argumentangle. 


    
[3] 深入显出gstreamer开发
    来源: 互联网  发布时间: 2014-02-18
深入浅出gstreamer开发

Gstreamer解决什么问题?

—上层接口和应用方式的相对稳定与底层接口、平台环境的多样化。例如:codec不同种类不同实现,音视频处理不同,硬件输入、输出、采集播放不同,芯片不同,操作系统不同。
—通用组件不灵活与需求的多变。色彩空间转换、缩放、编解码等组件功能是单一的。通过对这些组件进行组合,就可以满足多变的需求。要想拥有模块性、可移植性和通用的功能,通常是以极高的复杂性为代价。
—计算机系统的万能解决办法:加一层!
—Gstreamer媒体控制程序作为中间件,它可以解析上层指令,并对底层进行控制。

Gstreamer基础

—所有的gstreamer应用都是基于gobject的。
—除了理解封装、继承、多态的模拟以外,理解this指针,vtable的实现原理也很有帮助。
—参照下图理解gobject对象。
深入浅出Gstreamer基础概念
—是一个管道化多媒体框架。管道的属性:包含一系列不同功能的链接起来的元件以及元件之间的数据流动;管道的行为:包含一系列多媒体操作,如元件链接等。
—一个元件,由时钟、衬垫、总线、状态等组成。
—衬垫(pad)一个元件与外界通信的接口。
—互相链接的元件构成一个箱柜(BIN)。BIN作为一个整体,本身也可被认为是一个元件。
—管道(pipeline)是一个特殊的bin,是最高级别的bin。
—每一个pipeline都有一个默认的总线,该总线会在一个mainloop里去检查消息,并触发相应你的callback,实现与应用程序的通信。Bus含一个队列,每次post一个消息就加到队列里,然后出发maincontext的wakeup。这样就完成了将消息路由到maincontext去了。因为maincontext等待的有这个bus队列。
—Caps代表一个媒体文件的能力,通常包括该文件的mime类型和多媒体属性。
—bin是一个装载元素集合的容器。管道是特殊的bin类型,允许执行其中的所有子元素。由于bin本身是元素子类(subclass),通常可以像控制元素一样控制bin,从而简化应用程序。比如,可以通过改变bin本身的状态改变bin中所有元素的状态。bin还可以转发来自bin中的子元素的总线(bus)消息(例如错误消息,标签消息和EOS消息)。
—管道是顶级bin。将它的状态设置为暂停(PAUSED)或播放(PLAYING)时,则数据流启动,媒体处理开始。启动后,管道将在一个单独的线程中运行,直到被停止或数据流结束。数据流动是以缓冲传递来实际工作的。Buffer可以看成是一种容器,里边含data和events。
—事件是一种控制数据,能够在管道中上下流动。一般来说,上游的控制命令可能是真的在控制什么,来自下游的events可能大多数是些状态通知之类的
 
元件状态
—NULL:默认状态,内部会释放单元的所有资源,其实就是初始状态。
—READY:就绪状态,分配资源,打开设备。但是流不会打开,所以此时流信息都是零。如果之前打开了流,在这状态中将会被关闭,流信息都会被重设。
—PAUSED:已经打开了流,但是暂时不处理它。这个时候可以去修改例如seek位置等流信息。时间轴停止
—PLAYING:时间轴运行。设置为这个状态后,整个流程就开始启动了。内部会将消息发送从管道所在的线程转移到应用程序线程
抓住gstreamer核心

    Gstreamer Core,是gstreamer框架的骨干和核心。它提供的功能有:

(一)提供一些组件类型的基类的实现,以及这些组件之间的通信规则;

(二)提供给应用程序创建媒体实例的API,以及保证实例运行的各种机制API.

    Gstreamer  Core的本质是不在乎媒体文件是什么类型或什么格式的(media-agnostic),因为它不关心媒体编解码等具体细节。可以认为它是一个最高级的管理者和组织者,它提供了一个流媒体程序框架或者叫做蓝图,下属人员可以通过领会它的旨意去具体开展工作;你也可以理解它为一个服务供应商,提供了一切多媒体应用程序可能需要的元件,开发人员可以利用它来去实现自己的专属程序。Gstreamer在初始化时只注册了核心元件,包括bin和pipeline,用户需要以此为基础,实现自己的多样化的多媒体管道程序。多媒体应用程序的实现,需要用户自己利用好gstreamer,然后实现自己的东东。

 插件如何管理
 
把握core/plugin的重要联系
 
—Core/plugin是不同的模块。他们的存在都是为特定的多媒体控制程序服务的。特定的Plugin主要由媒体控制开发者提供,而core是所有基于gstreamer程序的共同体。
—Core里用到的每个element实际就是一个插件,在gst中得到组装成一个pipeline,数据从源单元流向目的单元,完成整个流程。单元间是可以链接起来的(必须得链接起来以组成pipeline).
—应用程序通过core使用factory_make和gst_object_unref函数来创建及释放元件。make需要两个参数,一个是工厂名,一个是单元名。工厂名实际就是插件名,所以需要先加载插件上来,才能创建对应的元件。作为工厂(插件),其功能还不仅限于创建元件,一个工厂有属性,它知道自己能创建怎样的元件。
 
Gstreamer核心类图
 
Gstreamer插件相关类图分析(可参考我上一篇文章)
Pipeline工作时序图
 
 
 

Smith先生版权所有,如需转载,请注明出处:http://blog.csdn.net/acs713/article/details/7777946

否者,保留追究其法律责任的权利

    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
编程技术 iis7站长之家
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3