OpenGLES—拾取

Posted GameCocos2dx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGLES—拾取相关的知识,希望对你有一定的参考价值。

本人学的OpenGL ES 都是从http://edu.csdn.net/lecturer/440 地方学的!喜欢的支持一下

{拾取
	1:给碰撞的物体整个盒子-->包围盒AxisAlignedBox(别名aabb)
	2:用射线与盒子相交 ray.intersects(盒子)
	3:加过程
}

1:给碰撞的物体整个盒子-->包围盒AxisAlignedBox(别名aabb)

//轴向包围盒
template<typename T>
class   AxisAlignedBox
{
public:
    enum Extent
    {
        EXTENT_NULL,//是否被初始化
        EXTENT_FINITE,//有限大
        EXTENT_INFINITE//无限大
    };
public:
    tvec3<T>    _minimum;//最小值
    tvec3<T>    _maximum;//最大值
    Extent      _extent;//扩展变量
public:
    /*
    1-----2
    /|    /|
    / |   / |
    5-----4  |
    |  0--|--3
    | /   | /
    |/    |/
    6-----7
    */
    typedef enum 
    {
	    FAR_LEFT_BOTTOM     =   0,
	    FAR_LEFT_TOP        =   1,
	    FAR_RIGHT_TOP       =   2,
	    FAR_RIGHT_BOTTOM    =   3,
	    NEAR_RIGHT_BOTTOM   =   7,
	    NEAR_LEFT_BOTTOM    =   6,
	    NEAR_LEFT_TOP       =   5,
	    NEAR_RIGHT_TOP      =   4
    } CornerEnum;

    AxisAlignedBox()
    {
	    _minimum    =   tvec3<T>( T(-0.5), T(-0.5), T(-0.5) );
	    _maximum    =   tvec3<T>( T(0.5), T(0.5), T(0.5) );
        _extent     =   EXTENT_NULL;
    }
    AxisAlignedBox(const AxisAlignedBox & rkBox)
    {
        setExtents( rkBox._minimum, rkBox._maximum );
        _extent =   rkBox._extent;
    }

    AxisAlignedBox( const tvec3<T>& min, const tvec3<T>& max )
    {
	    setExtents( min, max );
    }

    AxisAlignedBox(T mx, T my, T mz, T Mx, T My, T Mz )
    {
	    setExtents( mx, my, mz, Mx, My, Mz );
    }

    AxisAlignedBox<T>& operator=(const AxisAlignedBox<T>& right)
    {
        setExtents(right._minimum, right._maximum);
	    return *this;
    }

    ~AxisAlignedBox(){}

    //设置/获取最小值
	void setMinimum(const tvec3<T>& mins) { _minimum    =   mins; }
	void setMinimum(T x,T y, T z){  _minimum  = tvec3<T>(x,y,z); }
    const tvec3<T>& getMinimum(void) const {  return _minimum;  }
    tvec3<T>&       getMinimum(void) {  return _minimum;  }

  
    //设置/获取最大值
    const tvec3<T>& getMaximum(void) const{ return _maximum; }
    tvec3<T>& getMaximum(void) { return _maximum; }
    void setMaximum( const tvec3<T>& vec ){
	    _maximum = vec;
    }
    void setMaximum( T x, T y, T z ){
	    _maximum.x = x;
	    _maximum.y = y;
	    _maximum.z = z;
    }
	void setMaximumX( T x ){_maximum.x = x;}
    void setMaximumY( T y ){_maximum.y = y;}
    void setMaximumZ( T z ){_maximum.z = z;}

    /** 设置包围盒大小
	* @param min 最小值
	* @param max 最大值
    */
    void setExtents( const tvec3<T>& min, const tvec3<T>& max ) {
	    _minimum    =   min;
	    _maximum    =   max;
        _extent     =   EXTENT_FINITE;
    }
	/** 设置包围盒大小
	* @param mx my mz 最小值xyz
	* @param Mx My Mz 最大值xyz
    */
    void setExtents(T mx, T my, T mz, T Mx, T My, T Mz ){
	    _minimum.x  =   mx;
	    _minimum.y  =   my;
	    _minimum.z  =   mz;

	    _maximum.x  =   Mx;
	    _maximum.y  =   My;
	    _maximum.z  =   Mz;
        _extent     =   EXTENT_FINITE;
    }

    /** 获取包围盒8个顶点的坐标
	Returns a pointer to an array of 8 corner points, useful for
    collision vs. non-aligned objects.
    @remarks
    If the order of these corners is important, they are as
    follows: The 4 points of the minimum Z face (note that
    because Ogre uses right-handed coordinates, the minimum Z is
    at the 'back' of the box) starting with the minimum point of
    all, then anticlockwise around this face (if you are looking
    onto the face from outside the box). Then the 4 points of the
    maximum Z face, starting with maximum point of all, then
    anticlockwise around this face (looking onto the face from
    outside the box). Like this:
    <pre>
    1-----2
    /|    /|
    / |   / |
    5-----4  |
    |  0--|--3
    | /   | /
    |/    |/
    6-----7
    </pre>
    @remarks as this implementation uses a static member, make sure to use your own copy !
    */
    void    getAllCorners(tvec3<T> mpCorners[8] ) const {
	    mpCorners[0]    = _minimum;
	    mpCorners[1].x  = _minimum.x; mpCorners[1].y = _maximum.y; mpCorners[1].z = _minimum.z;
	    mpCorners[2].x  = _maximum.x; mpCorners[2].y = _maximum.y; mpCorners[2].z = _minimum.z;
	    mpCorners[3].x  = _maximum.x; mpCorners[3].y = _minimum.y; mpCorners[3].z = _minimum.z;            

	    mpCorners[4]    = _maximum;
	    mpCorners[5].x  = _minimum.x; mpCorners[5].y = _maximum.y; mpCorners[5].z = _maximum.z;
	    mpCorners[6].x  = _minimum.x; mpCorners[6].y = _minimum.y; mpCorners[6].z = _maximum.z;
	    mpCorners[7].x  = _maximum.x; mpCorners[7].y = _minimum.y; mpCorners[7].z = _maximum.z;
    }

    /** 获取局部顶点
	* @param cornerToGet 方向枚举值
    *  gets the position of one of the corners
    */
    tvec3<T> getCorner(CornerEnum cornerToGet) const
    {
	    switch(cornerToGet)
	    {
	    case FAR_LEFT_BOTTOM:
		    return _minimum;
	    case FAR_LEFT_TOP:
		    return tvec3<T>(_minimum.x, _maximum.y, _minimum.z);
	    case FAR_RIGHT_TOP:
		    return tvec3<T>(_maximum.x, _maximum.y, _minimum.z);
	    case FAR_RIGHT_BOTTOM:
		    return tvec3<T>(_maximum.x, _minimum.y, _minimum.z);
	    case NEAR_RIGHT_BOTTOM:
		    return tvec3<T>(_maximum.x, _minimum.y, _maximum.z);
	    case NEAR_LEFT_BOTTOM:
		    return tvec3<T>(_minimum.x, _minimum.y, _maximum.z);
	    case NEAR_LEFT_TOP:
		    return tvec3<T>(_minimum.x, _maximum.y, _maximum.z);
	    case NEAR_RIGHT_TOP:
		    return _maximum;
	    default:
		    return tvec3<T>();
	    }
    }

    /** 合并包围盒
	*	两个包围盒合到一起,就是取并集
    *   Merges the passed in box into the current box. The result is the
    *   box which encompasses both.
    */
    void merge( const AxisAlignedBox<T>& right )
    {

        if ((right._extent == EXTENT_NULL) || (_extent == EXTENT_INFINITE)){
            return;
        }else if (right._extent == EXTENT_INFINITE){
            _extent =   EXTENT_INFINITE;
        }else if (_extent == EXTENT_NULL){
            setExtents(right._minimum, right._maximum);
        }else{
            //! merge
            tvec3<T> min =   _minimum;
            tvec3<T> max =   _maximum;
            max.makeCeil(right._maximum);//取最大值
            min.makeFloor(right._minimum);//取最小值
            setExtents(min, max);
        }
    }

    /** 
    *   Extends the box to encompass the specified point (if needed).
    */
    void merge( const tvec3<T>& point )
    {
        switch (_extent)
        {
        case EXTENT_NULL: // if null, use this point
            setExtents(point, point);
            return;

        case EXTENT_FINITE:
            _maximum.makeCeil(point);
            _minimum.makeFloor(point);
            return;

        case EXTENT_INFINITE:
            return;
        }
    }

	/*** 模型变换了,从新计算最大值/最小值
	* 正方形6个面一共36顶点,在算出最大值和最小值,在和模型相乘
	* 原理:8个顶点和矩阵相乘,得到新的8个顶点,在求最大值和最小值
	* @param matrix 模型矩阵
	*/
    void transform( const tmat4x4<T>& matrix )
    {
        tvec3<T>    oldMin;
        tvec3<T>    oldMax;
        tvec3<T>    currentCorner;

        oldMin  = _minimum;
        oldMax  = _maximum;


        // We sequentially compute the corners in the following order :
        // 0, 6, 5, 1, 2, 4 ,7 , 3
        // This sequence allows us to only change one member at a time to get at all corners.

        // For each one, we transform it using the matrix
        // Which gives the resulting point and merge the resulting point.

        currentCorner   =   oldMin;
        tvec3<T> vVert  =   currentCorner * matrix;
        setExtents(vVert,vVert);

        // First corner 
        // min min min
        currentCorner = oldMin;
        merge( currentCorner * matrix );

        // min,min,max
        currentCorner.z = oldMax.z;
        merge( currentCorner * matrix );

        // min max max
        currentCorner.y = oldMax.y;
        merge( currentCorner * matrix );

        // min max min
        currentCorner.z = oldMin.z;
        merge( currentCorner * matrix );

        // max max min
        currentCorner.x = oldMax.x;
        merge( currentCorner * matrix );

        // max max max
        currentCorner.z = oldMax.z;
        merge( currentCorner * matrix );

        // max min max
        currentCorner.y = oldMin.y;
        merge( currentCorner * matrix);

        // max min min
        currentCorner.z = oldMin.z;
        merge( currentCorner * matrix); 
    }

    /** 和盒子相交(两个盒子相交)
    *   Returns whether or not this box intersects another. 
	* @param b2 第二个盒子
	* @return true 相交,false 不相交
    */
    bool intersects(const AxisAlignedBox& b2) const
    {
	    if (_maximum.x < b2._minimum.x)
		    return false;
	    if (_maximum.y < b2._minimum.y)
		    return false;
	    if (_maximum.z < b2._minimum.z)
		    return false;

	    if (_minimum.x > b2._maximum.x)
		    return false;
	    if (_minimum.y > b2._maximum.y)
		    return false;
	    if (_minimum.z > b2._maximum.z)
		    return false;
	    return true;

    }

    /** 和盒子相交(两个盒子相交),不考虑z轴
    *   Returns whether or not this box intersects another. 
	* @param b2 第二个盒子
	* @return true 相交,false 不相交
    */
    bool intersectsNoZ(const AxisAlignedBox& b2) const
    {
	    if (_maximum.x < b2._minimum.x)
		    return false;
	    if (_maximum.y < b2._minimum.y)
		    return false;

	    if (_minimum.x > b2._maximum.x)
		    return false;
	    if (_minimum.y > b2._maximum.y)
		    return false;
	    return true;

    }

    /** 和盒子相交(两个盒子相交)
    *   Returns whether or not this box intersects another. 
	* @param b2 第二个盒子
	* @return  返回交集
    */
    AxisAlignedBox<T> intersection(const AxisAlignedBox<T>& b2) const
    {
	    tvec3<T> intMin = _minimum;
        tvec3<T> intMax = _maximum;

        intMin.makeCeil(b2.getMinimum());
        intMax.makeFloor(b2.getMaximum());

        if (intMin.x < intMax.x && intMin.y < intMax.y &&intMin.z < intMax.z){
            return AxisAlignedBox<T>(intMin, intMax);
        }

        return AxisAlignedBox<T>();
    }
	//是否被初始化
	bool  isNull(void) const {return (_extent == EXTENT_NULL); }
    void  setNull() {_extent = EXTENT_NULL; }
  
	//是否是有限的
    bool  isFinite(void) const{ return (_extent == EXTENT_FINITE);}
    void  setInfinite() {_extent = EXTENT_INFINITE; }

    bool    isInfinite(void) const
    {
        return (_extent == EXTENT_INFINITE);
    }
	//缩放
    void    scale(const tvec3<T>& s){
	    tvec3<T> min = _minimum * s;
	    tvec3<T> max = _maximum * s;
	    setExtents(min, max);
    }
    /*** 和点相交
	* @param v 三维点
	*/
    bool    intersects(const tvec3<T>& v) const
    {
        return( v.x >= _minimum.x  &&  v.x <= _maximum.x  && 
                v.y >= _minimum.y  &&  v.y <= _maximum.y  && 
                v.z >= _minimum.z  &&  v.z <= _maximum.z);
    }

	/*** 和点相交
	* @param v 二维点
	*/
    bool    intersects(const tvec2<T>& v) const
    {
        return( v.x >= _minimum.x  &&  v.x <= _maximum.x  && 
                v.y >= _minimum.y  &&  v.y <= _maximum.y );
    }
    //获取包围盒中心点
    tvec3<T>    getCenter(void) const
    {
	    return tvec3<T>(
		                (_maximum.x + _minimum.x) * T(0.5f),
		                (_maximum.y + _minimum.y) * T(0.5f),
		                (_maximum.z + _minimum.z) * T(0.5f)
                        );
    }

    //获取包围盒大小 
    tvec3<T> getSize(void) const { return _maximum - _minimum;  }
    //获取包围盒一半的大小 
    tvec3<T> getHalfSize(void) const  { return (_maximum - _minimum) * T(0.5); }

	//是否包含点
    bool contains(const tvec3<T>& v) const
    {
        return _minimum.x <= v.x && v.x <= _maximum.x &&
               _minimum.y <= v.y && v.y <= _maximum.y &&
               _minimum.z <= v.z && v.z <= _maximum.z;
    }
	//是否包含盒子
    bool contains(const AxisAlignedBox& other) const
    {
        return this->_minimum.x <= other._minimum.x &&
               this->_minimum.y <= other._minimum.y &&
               this->_minimum.z <= other._minimum.z &&
               other._maximum.x <= this->_maximum.x &&
               other._maximum.y <= this->_maximum.y &&
               other._maximum.z <= this->_maximum.z;
    }
    bool operator== (const AxisAlignedBox& right) const
    {
        return this->_minimum == right._minimum &&
               this->_maximum == right._maximum;
    }
    bool operator!= (const AxisAlignedBox& right) const
    {
        return !(*this == right);
    }
};

2:用射线与盒子相交 ray.intersects(盒子)

//射线
template<typename T>
class  tray
{
    typedef T           value_type;
    typedef tray<T>     type;
protected:
    tvec3<T>    _origin;//起始点
    tvec3<T>    _direction;//方向
public:
    tray():
        _origin(value_type(0),value_type(0),value_type(0)),
        _direction(value_type(0),value_type(0),value_type(1))
    {}
    tray(const tvec3<T>& origin, const tvec3<T>& direction):
        _origin(origin), 
        _direction(direction)
    {}

    //设置射线的起点
    void setOrigin(const tvec3<T>& origin) {  _origin = origin; } 
    // 返回射线的起点
    const tvec3<T>&  getOrigin(void) const{   return _origin;   } 

    //设置射线的方向
    void  setDirection(const tvec3<T>& dir)  {  _direction = dir;  } 
    
    //返回射线的方向
    const tvec3<T>&  getDirection(void) const {   return _direction;   } 

    /** 
    *   Gets the position of a point t units along the ray. 
    */
    tvec3<T>  getPoint(T time) const { return tvec3<T>(_origin + (_direction * time));}

    /** 射线与box相交
    *   如果相交,返回值中的first == true.否则false
    *   second为射线到点的距离
    *   调用getPoint方法,则返回交点
	* @param box 盒子
	* @return	std::pair<bool, T>.first 是否碰上,true碰上,false没有碰上
	* @return	std::pair<bool, T>.second 射线到点的距离(这是个时间), getPoint(pair.second)得到交点
    */
    std::pair<bool, T> intersects(const AxisAlignedBox<T>& box) const
    {
        T           lowt    = 0.0f;
        T           t;
        bool        hit     = false;
        tvec3<T>    hitpoint;
        tvec3<T>    min      =   box.getMinimum();
        tvec3<T>    max      =   box.getMaximum();

        // 点在包围盒里面
        if ( _origin > min && _origin < max )
        {
            return std::pair<bool, T>(true, 0);
        }

        // Check each face in turn, only check closest 3
        // Min x
        if (_origin.x <= min.x && _direction.x > 0)
        {
            t   =   (min.x - _origin.x) / _direction.x;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.y >= min.y && 
                    hitpoint.y <= max.y &&
                    hitpoint.z >= min.z && 
                    hitpoint.z <= max.z &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        // Max x
        if (_origin.x >= max.x && _direction.x < 0)
        {
            t   =   (max.x - _origin.x) / _direction.x;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.y >= min.y && 
                    hitpoint.y <= max.y &&
                    hitpoint.z >= min.z &&
                    hitpoint.z <= max.z &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        // Min y
        if (_origin.y <= min.y && _direction.y > 0)
        {
            t   =   (min.y - _origin.y) / _direction.y;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.x >= min.x && 
                    hitpoint.x <= max.x &&
                    hitpoint.z >= min.z && 
                    hitpoint.z <= max.z &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        // Max y
        if (_origin.y >= max.y && _direction.y < 0)
        {
            t   =   (max.y - _origin.y) / _direction.y;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.x >= min.x &&
                    hitpoint.x <= max.x &&
                    hitpoint.z >= min.z &&
                    hitpoint.z <= max.z &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        // Min z
        if (_origin.z <= min.z && _direction.z > 0)
        {
            t   =   (min.z - _origin.z) / _direction.z;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.x >= min.x && 
                    hitpoint.x <= max.x &&
                    hitpoint.y >= min.y &&
                    hitpoint.y <= max.y &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        // Max z
        if (_origin.z >= max.z && _direction.z < 0)
        {
            t   =   (max.z - _origin.z) / _direction.z;
            if (t >= 0)
            {
                // Substitute t back into ray and check bounds and dist
                hitpoint = _origin + _direction * t;
                if (hitpoint.x >= min.x && 
                    hitpoint.x <= max.x &&
                    hitpoint.y >= min.y && 
                    hitpoint.y <= max.y &&
                    (!hit || t < lowt))
                {
                    hit     =   true;
                    lowt    =   t;
                }
            }
        }
        return std::pair<bool, T>(hit, lowt);
    }
};

 template<typename T>
/*** 射线与三角形相交
* @param orig 射线原点
* @param dir 射线方向
* @param v0, v1, v2 三角形三个点
* @param t 返回的时间
* @param u,v 返回各个方向的一个分量
*/
bool intersectTriangle( const tvec3<T>& orig,const tvec3<T>& dir,tvec3<T>& v0, tvec3<T>& v1,tvec3<T>& v2, T* t, T* u, T* v )
{
    // Find vectors for two edges sharing vert0
    tvec3<T>    edge1   =   v1 - v0;
    tvec3<T>    edge2   =   v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    tvec3<T>    pvec;
    pvec    =   cross(dir, edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    T   det =   dot( edge1,pvec );

    tvec3<T>    tvec;
    if( det > 0 )
    {
        tvec    =   orig - v0;
    }
    else
    {
        tvec    =   v0 - orig;
        det     =   -det;
    }
    if( det < 0.0001f )
        return false;
    // Calculate U parameter and test bounds
    *u  =   dot( tvec, pvec );
    if( *u < 0.0f || *u > det )
        return false;

    // Prepare to test V parameter
    tvec3<T>    qvec;
    qvec    =   cross(tvec, edge1 );

    // Calculate V parameter and test bounds
    *v  =   dot( dir, qvec );
    if( *v < T(0.0f) || *u + *v > det )
        return false;

    *t  =   dot( edge2,qvec );
    T   fInvDet = T(1.0) / det;
    *t  *=  fInvDet;
    *u  *=  fInvDet;
    *v  *=  fInvDet;

    return true;
}

3:加过程

typedef AxisAlignedBox<float>   aabb3d;
typedef tray<float>         Ray;

{初始化变量
	AABBVertex  ptLine[2];//射线的两个点(画射线用)

	CELL::aabb3d aabbBox;//包围盒
	CELL::aabb3d aabbTran;//记录aabbBox包围盒(包围盒改变后的大小,也是更新的大小)

	CELL::float3 vMin=(FLT_MAX,FLT_MAX,FLT_MAX);
	CELL::float3 vMax=(-FLT_MAX,-FLT_MAX,-FLT_MAX);
	//aabbBoxVertex 要添加盒子的模型数据
	size_t count=sizeof(aabbBoxVertex)/sizeof(aabbBoxVertex[0]);//正方形6个面,每个面6个顶点(两个三角形组成一个面)一共36顶点
	for (size_t i=0;i<count;i++){
		vMin.x=min(aabbBoxVertex[i].x,vMin.x);
		vMin.y=min(aabbBoxVertex[i].y,vMin.y);
		vMin.z=min(aabbBoxVertex[i].z,vMin.z);

		vMax.x=max(aabbBoxVertex[i].x,vMax.x);
		vMax.y=max(aabbBoxVertex[i].y,vMax.y);
		vMax.z=max(aabbBoxVertex[i].z,vMax.z);
	}
	aabbBox.setExtents(vMin,vMax);
}

{鼠标交互

	virtual void  onMousePress(int absx, int absy, MouseKeyCode id) {
		if(id==MouseKeyCode::Left) {
			CELL::Ray ray=camera.createRayFromScreen(absx,absy);//得到射线
			CELL::float3 post=ray.getOrigin();//射线起始点的位置
			float tm=(post.y)/ray.getDirection().y;

			//得到地面的焦点位置
			//CELL::float3 target= dd.getPoint(abs(tm));
			CELL::float3 target= ray.getOrigin()+ray.getDirection()*abs(tm);
			target=CELL::float3(target.x,0,target.z);

			//设置物体移动到什么位置
			role.setTarget(target);

			{//画射线(获取点)
				ptLine[0].x=post.x;//起始点
				ptLine[0].y=post.y;
				ptLine[0].z=post.z;

				ptLine[1].x=target.x;//终点(目标点)
				ptLine[1].y=target.y;
				ptLine[1].z=target.z;
			}
			std::pair<bool, float> parl=ray.intersects(aabbTran);//射线与box相交
			//intersectTriangle();射线与三角形相交
			static int index=0;
			if(parl.first){
				CELL::float3 jd=ray.getPoint(parl.second);
				printf("碰撞上了  %d --> 焦点(%f,%f,%f)\\n",++index,jd.x,jd.y,jd.z);
			}

		}else if(id==MouseKeyCode::Right){
			mousePos=CELL::float2(absx,absy);
			isRight=true;
		}
	}

}

{画
	{//画射线
		glLineWidth(5);
		glVertexAttribPointer(shader._positionAttr, 3,  GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].x);
		glVertexAttribPointer(shader._uvAttr,       2,  GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].u);
		glVertexAttribPointer(shader._colorAttr,    4,  GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].r);
		glDrawArrays(GL_LINES,0,2);
	}

		
	{//移动的立方盒
		glBindTexture(GL_TEXTURE_2D,textureRole);

		CELL::matrix4   matRot(1);
		CELL::matrix4   matModel;
		static float agle = 0.0f; agle +=  1.0f;
		matRot.rotateYXZ(agle,agle,agle);
		matModel.translate(role._pos);
		aabbTran    =   aabbBox;
		aabbTran.transform(matModel * matRot);
		CELL::matrix4  ddz= matModel * matRot;


		MVP =   matProj * matView * ddz;
		glUniformMatrix4fv(shader._MVP,1,false,MVP.data());
		glVertexAttribPointer(shader._positionAttr, 3,  GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].x);
		glVertexAttribPointer(shader._uvAttr,       2,  GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].u);
		glVertexAttribPointer(shader._colorAttr,    4,  GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].r);
		glDrawArrays(GL_TRIANGLES,0,sizeof(aabbBoxVertex)/sizeof(aabbBoxVertex[0]));
	}

			
	{//画包围盒
		CELL::float3  arBox[8];
		AABBVertex  vertexBox[8];
		aabbTran.getAllCorners(arBox);
		for (size_t i = 0 ; i < 8 ;++ i ){//顶点位置
			vertexBox[i].x  = arBox[i].x;
			vertexBox[i].y  = arBox[i].y;
			vertexBox[i].z  = arBox[i].z;
		}
		short  boxIndex[24] = {//索引--必须按照返回的vertexBox数组设置,具体看这个函数getAllCorners
			0,1,2,3,//后
			2,3,7,4,//右
			4,5,6,7,//前
			1,0,6,5,//左
			2,4,5,1,//上
			0,3,7,6//下
		};

		MVP  = matProj * matView;
		glUniformMatrix4fv(shader._MVP,1,false,MVP.data());
		glVertexAttribPointer(shader._positionAttr, 3,  GL_FLOAT,false,sizeof(AABBVertex),&vertexBox[0].x);
		size_t count=sizeof(boxIndex)/sizeof(boxIndex[0]);

		for (size_t i=0;i<count;i+=4){
			glDrawElements(GL_LINE_STRIP,4,GL_UNSIGNED_SHORT, &boxIndex[i]);
		}
	}
}

{Shader
	const char vs[]={
			"uniform   mat4 _MVP;"
			"attribute vec3 _positionAttr;"
			"attribute vec4 _colorAttr;"
			"attribute vec2 _uvAttr;"

			"varying   vec4 _outColor;"
			"varying   vec2 _outUV;"
			"void main(){"
			"   vec4    pos =   vec4(_positionAttr.x,_positionAttr.y,_positionAttr.z,1);"
			"   gl_Position =   _MVP * pos;"
			"   _outColor   =   _colorAttr;"
			"   _outUV      =   _uvAttr;"
			"}"
		};
		const char fs[]={
			"precision  lowp float; "
			"uniform    sampler2D   _texture;"
			"varying    vec4        _outColor;"
			"varying    vec2        _outUV;"
			"void main()"
			"{"
			"   vec4   color   =   texture2D(_texture,_outUV);"
			"   gl_FragColor   =   color * _outColor;"
			"}"
		};

		pValue=creteShaderProgram(vs,fs);//编译Shader程序


		_MVP=glGetUniformLocation(pValue.pID,"_MVP");
		_texture=glGetUniformLocation(pValue.pID,"_texture");

		_positionAttr=glGetAttribLocation(pValue.pID,"_positionAttr");
		_uvAttr=glGetAttribLocation(pValue.pID,"_uvAttr");
		_colorAttr=glGetAttribLocation(pValue.pID,"_colorAttr");
}

 
效果图 



文字有点模糊

蓝色的线是--射线

黄色的线是--模型
橙色的线是--包围盒

源码地址 http://pan.baidu.com/s/1geVargZ       拾取.zip


推荐博客

http://www.cnblogs.com/seebro/p/3801597.html


以上是关于OpenGLES—拾取的主要内容,如果未能解决你的问题,请参考以下文章

OpenGLES3.0创建着色器步骤

Android OpenGLES3绘图 - 音频可视化(模仿MIUI系统效果)

用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低

我的OpenGL学习进阶之旅OpenGL ES 3.0实现了具有可编程着色功能的图形管线

我的OpenGL学习进阶之旅OpenGL ES 3.0实现了具有可编程着色功能的图形管线

OpenGL ES之“深度测试”与“模板测试”的使用流程