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

时间: 2024-10-07 10:05:33

OpenGLES—拾取的相关文章

关于Unity中的道具拾取(专题六)

原理就是把道具做成触发器,触发器就是当我们有碰撞发生的时候,只会检测碰撞,而不会有任何改变物理运动状态的过程. 触发器非常适合道具拾取,因为它不会改变原本运动物体的任何物理属性,但是依然会检测碰撞,响应物理事件. 道具拾取实例 1.创建Unity项目和文件目录,保存场景 2.导入金币模型资源rc_fx_obj_04_mod.FBX和obj_04_tex.png,设置材质球的shader为Lagacy Shaders---->Diffuse,颜色设置为255,255,255,255 3.创建一个平

【转】Unity3D 射线Ray实现点击拾取

游戏中经常会有鼠标移动到某个对象上来拾取它的功能,我们可以用Unity3D中的射线Ray实现这一效果.原理是在我们鼠标的位置,从屏幕射出一条射向世界空间的射线,当这条射线碰撞到我们需要拾取的对象时,我们就销毁对象,把它添加到我们的背包中. 我们来做一个简单的Demo,我们在场景中添加一个方块Cube,一个小球Sphere,当我们鼠标放在方块上时没有任何反应,而当我们把鼠标放在小球上时,小球会消失. 新建一个项目,我们命名为"RayTest",然后在场景中新建一个小球,方块,和添加灯光,

2016年发布APASVO-p波震相自动拾取分析

Why automatic attractive? large amount of seismic data ; if manually,it depends om experience of analyst; Quliaty can be obscured by several factors such as background and non-stationary noise from diverse sources; 该软件使用的方法为 STA-LTA(针对振幅突变识别很有效): AMP

iOS给图片添加滤镜&amp;使用openGLES动态渲染图片

给图片增加滤镜有这两种方式: CoreImage / openGLES 下面先说明如何使用CoreImage给图片添加滤镜, 主要为以下步骤: #1.导入CIImage格式的原始图片 #2.创建CIFilter滤镜 #3.用CIContext将滤镜中的图片渲染出来 #4.导出渲染后的图片 参考代码: 1 //导入CIImage 2 CIImage *ciImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:@"hua"]]

图片拾取器-PicPicker

最近报名参加了360前端星计划,想当一名前端实习生,学习更多更流行的前端知识.然后需要完成一个作业,才能进培训,进了培训还得看运气才能留下,流程不少.书归正传,请看: 课后作业题目 请从下面两个题目中任意选择一道题完成. 题目1:使用网页做一份简历,可以根据自己的能力适当添加动画效果和交互. 题目2:开发一个网页图片查看器,可以缩放.拖动图片. 好吧,我果断选择了第二题,然后把自己的简历放在了图片查看器的图片中,真是机智啊.下面进入正题. PicPicker 光做个查看器好像也没什么意思,我绞尽

OpenGL拾取注意事项

GLFrame框架本身不支持拾取,需要自己实现.以下代码是实现拾取功能的注意事项: 1 void Test::doSelection(int xPos, int yPos) 2 { 3 GLfloat aspect; 4 GLint hits, viewport[4];//x,y,width,height 5 glSelectBuffer(BUFFER_LENGTH, pickBuffer); //设置选择缓冲区 6 glGetIntegerv(GL_VIEWPORT, viewport); /

OpenGLES 关于 数学 的分支 - 线性变化量、离散量、随机量

关于 数学 的分支 - 线性变化量.离散量.随机量 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 昨天看的资料有些多,一时没有想起来做个笔记,今天再回想起来,只是大概有个印象,确忘记了着实的内

iOS OpenGLES 框架相关 24 篇文档排序整理

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. OpenGLES Use a compact, efficient subset of the OpenGL API for 2D and 3D

OpenGL-选择与拾取

转自:http://blog.sina.com.cn/s/blog_4a9aa55c0100vu57.html 以下内容主要整理<OpenGL编程指南>第13章的内容.主要解决以下问题: (1)如何允许用户选择屏幕上的一块区域或者挑选屏幕上所绘制的一个物体? 一. 选择 1. OpenGL的选择机制如何实现 当我们打算使用OpenGL的选择机制时: (1)首先把整个场景绘制到帧缓冲区中: (2)然后进入选择模式,并且对场景进行重绘,此时,帧缓冲区的内容将不会被修改: (3)退出选择模式时,Op