Exemple #1
0
const Frustum& Camera::GetFrustum() const
{
    // Use projection_ instead of GetProjection() so that Y-flip has no effect. Update first if necessary
    if (projectionDirty_)
        UpdateProjection();

    if (frustumDirty_)
    {
        if (customProjection_)
            frustum_.Define(projection_ * GetView());
        else
        {
            // If not using a custom projection, prefer calculating frustum from projection parameters instead of matrix
            // for better accuracy
            if (!orthographic_)
                frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), GetFarClip(), GetEffectiveWorldTransform());
            else
                frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), GetFarClip(), GetEffectiveWorldTransform());
        }

        frustumDirty_ = false;
    }

    return frustum_;
}
Exemple #2
0
Frustum Camera::GetViewSpaceFrustum() const
{
    Frustum ret;

    if (!orthographic_)
        ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_);
    else
        ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_);

    return ret;
}
Exemple #3
0
const Frustum& Camera::GetFrustum() const
{
    if (frustumDirty_)
    {
        const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
        if (!orthographic_)
            frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
        else
            frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
        
        frustumDirty_ = false;
    }
    
    return frustum_;
}
Exemple #4
0
void Camera::GetFrustumSize(Vector3& near, Vector3& far) const
{
    near.z_ = GetNearClip();
    far.z_ = farClip_;

    if (!orthographic_)
    {
        float halfViewSize = tanf(fov_ * M_DEGTORAD * 0.5f) / zoom_;
        near.y_ = near.z_ * halfViewSize;
        near.x_ = near.y_ * aspectRatio_;
        far.y_ = far.z_ * halfViewSize;
        far.x_ = far.y_ * aspectRatio_;
    }
    else
    {
        float halfViewSize = orthoSize_ * 0.5f / zoom_;
        near.y_ = far.y_ = halfViewSize;
        near.x_ = far.x_ = near.y_ * aspectRatio_;
    }

    if (flipVertical_)
    {
        near.y_ = -near.y_;
        far.y_ = -far.y_;
    }
}
Exemple #5
0
const Frustum& Camera::GetFrustum() const
{
    if (frustumDirty_)
    {
        Matrix3x4 worldTransform = GetEffectiveWorldTransform();

        if (!orthographic_)
            frustum_.Define(fov_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);
        else
            frustum_.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), farClip_, worldTransform);

        frustumDirty_ = false;
    }

    return frustum_;
}
Exemple #6
0
Vector3 Camera::ScreenToWorldPoint(const Vector3& screenPos) const
{
    Ray ray = GetScreenRay(screenPos.x_, screenPos.y_);
    Vector3 viewSpaceDir = (GetView() * Vector4(ray.direction_, 0.0f));
    float rayDistance = (Max(screenPos.z_ - GetNearClip(), 0.0f) / viewSpaceDir.z_);
    return ray.origin_ + ray.direction_ * rayDistance;
}
Exemple #7
0
	bool Camera::ObjectFrustumCulling( const RenderObject& obj )
	{
		const AABB& aabb = obj.m_worldAABB;

		//物体坐标转换到相机空间进行裁减
		VEC4 pos(aabb.GetCenter(), 1.0f);
		Common::Transform_Vec4_By_Mat44(pos, pos, GetViewMatrix());

		float n = GetNearClip();
		float f = GetFarClip();
		float fov = GetFov();
		float half_w = n * std::tan(fov/2);
		float half_h = half_w / GetAspectRatio();

		//检测前后面
		if(-pos.z+aabb.m_boundingRadius <= n || -pos.z-aabb.m_boundingRadius >= f)
			return true;

		//检测左右面
		float planeX = half_w * pos.z / -n;
		if(pos.x - planeX >= aabb.m_boundingRadius ||
			pos.x + aabb.m_boundingRadius <= -planeX)
			return true;

		//检测上下面
		float planeY = half_h * pos.z / -n;
		if(pos.y - planeY >= aabb.m_boundingRadius ||
			pos.y + aabb.m_boundingRadius <= -planeY)
			return true;

		return false;
	}
Exemple #8
0
Frustum Camera::GetViewSpaceFrustum() const
{
    if (projectionDirty_)
        UpdateProjection();

    Frustum ret;

    if (customProjection_)
        ret.Define(projection_);
    else
    {
        if (!orthographic_)
            ret.Define(fov_, aspectRatio_, zoom_, GetNearClip(), GetFarClip());
        else
            ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, GetNearClip(), GetFarClip());
    }

    return ret;
}
Exemple #9
0
	void Camera::_BuildProjMatrix()
	{
		/*	这是第一个版本的透视投影矩阵,即"蛮干"求解法.
			它的缺陷在于为了变换出xy坐标都在[-1, 1]的CVV空间,
			必须满足以下条件:
			1.视距d=1.
			2.fov=90度.
			3.视口AspectRatio=1.
			否则变换不出CVV.

			MatProj = ( 1, 0,	0,	0
						0, 1,	0,	0
						0,  0,	1,	0
						0,  0, 1/d,  0 )

			投影变换加齐次除法后:
			x' = x * d / z, y' = y * d / z	*/

		//普适版投影矩阵.推导见: http://blog.csdn.net/popy007/article/details/1797121
		float r,l,t,b;
		r = m_nearClip*tanf(m_fov/2);
		l = -r;
		t = r/m_aspectRatio;
		b= -t;

		m_matProj.m00 = 2*m_nearClip/(r-l);
		m_matProj.m01 = 0;
		m_matProj.m02 = (r+l)/(r-l);
		m_matProj.m03 = 0;

		m_matProj.m10 = 0;
		m_matProj.m11 = 2*m_nearClip/(t-b);
		m_matProj.m12 = (t+b)/(t-b);
		m_matProj.m13 = 0;

		m_matProj.m20 = 0;
		m_matProj.m21 = 0;
		m_matProj.m22 = -(m_farClip+m_nearClip)/(m_farClip-m_nearClip);
		m_matProj.m23 = -2*m_farClip*m_nearClip/(m_farClip-m_nearClip);

		m_matProj.m30 = 0;
		m_matProj.m31 = 0;
		m_matProj.m32 = -1;
		m_matProj.m33 = 0;

		m_matInvProj = m_matProj.Inverse();

		m_imagePlane_r = GetNearClip() * tanf(GetFov() / 2);
		m_imagePlane_t = m_imagePlane_r / GetAspectRatio();
	}
Exemple #10
0
Frustum Camera::GetViewSpaceSplitFrustum(float nearClip, float farClip) const
{
    Frustum ret;

    nearClip = Max(nearClip, GetNearClip());
    farClip = Min(farClip, farClip_);
    if (farClip < nearClip)
        farClip = nearClip;

    if (!orthographic_)
        ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip);
    else
        ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip);

    return ret;
}
Exemple #11
0
Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
{
    Frustum ret;

    Matrix3x4 worldTransform = GetEffectiveWorldTransform();
    nearClip = Max(nearClip, GetNearClip());
    farClip = Min(farClip, farClip_);
    if (farClip < nearClip)
        farClip = nearClip;

    if (!orthographic_)
        ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
    else
        ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);

    return ret;
}
Exemple #12
0
Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
{
    Frustum ret;
    
    const Matrix3x4& worldTransform = node_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
    nearClip = Max(nearClip, GetNearClip());
    farClip = Min(farClip, farClip_);
    if (farClip < nearClip)
        farClip = nearClip;
    
    if (!orthographic_)
        ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
    else
        ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, worldTransform);
    
    return ret;
}
Exemple #13
0
bool Camera::IsProjectionValid() const
{
    return farClip_ > GetNearClip();
}
Exemple #14
0
Matrix4 Camera::GetProjection(bool apiSpecific) const
{
    Matrix4 ret(Matrix4::ZERO);

    // Whether to construct matrix using OpenGL or Direct3D clip space convention
    #ifdef URHO3D_OPENGL
    bool openGLFormat = apiSpecific;
    #else
    bool openGLFormat = false;
    #endif

    if (!orthographic_)
    {
        float nearClip = GetNearClip();
        float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
        float w = h / aspectRatio_;
        float q, r;

        if (openGLFormat)
        {
            q = (farClip_ + nearClip) / (farClip_ - nearClip);
            r = -2.0f * farClip_ * nearClip / (farClip_ - nearClip);
        }
        else
        {
            q = farClip_ / (farClip_ - nearClip);
            r = -q * nearClip;
        }

        ret.m00_ = w;
        ret.m02_ = projectionOffset_.x_ * 2.0f;
        ret.m11_ = h;
        ret.m12_ = projectionOffset_.y_ * 2.0f;
        ret.m22_ = q;
        ret.m23_ = r;
        ret.m32_ = 1.0f;
    }
    else
    {
        // Disregard near clip, because it does not affect depth precision as with perspective projection
        float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
        float w = h / aspectRatio_;
        float q, r;

        if (openGLFormat)
        {
            q = 2.0f / farClip_;
            r = -1.0f;
        }
        else
        {
            q = 1.0f / farClip_;
            r = 0.0f;
        }

        ret.m00_ = w;
        ret.m03_ = projectionOffset_.x_ * 2.0f;
        ret.m11_ = h;
        ret.m13_ = projectionOffset_.y_ * 2.0f;
        ret.m22_ = q;
        ret.m23_ = r;
        ret.m33_ = 1.0f;
    }

    if (flipVertical_)
        ret = flipMatrix * ret;

    return ret;
}
Exemple #15
0
Matrix4 Camera::GetProjection(bool apiSpecific) const
{
    Matrix4 ret(Matrix4::ZERO);
    
    if (!orthographic_)
    {
        float nearClip = GetNearClip();
        float h = (1.0f / tanf(fov_ * M_DEGTORAD * 0.5f)) * zoom_;
        float w = h / aspectRatio_;
        float q, r;
        
        if (apiSpecific)
        {
            #ifdef USE_OPENGL
            q = (farClip_ + nearClip) / (farClip_ - nearClip);
            r = -2.0f * farClip_ * nearClip / (farClip_ - nearClip);
            #else
            q = farClip_ / (farClip_ - nearClip);
            r = -q * nearClip;
            #endif
        }
        else
        {
            q = farClip_ / (farClip_ - nearClip);
            r = -q * nearClip;
        }
        
        ret.m00_ = w;
        ret.m02_ = projectionOffset_.x_ * 2.0f;
        ret.m11_ = h;
        ret.m12_ = projectionOffset_.y_ * 2.0f;
        ret.m22_ = q;
        ret.m23_ = r;
        ret.m32_ = 1.0f;
    }
    else
    {
        // Disregard near clip, because it does not affect depth precision as with perspective projection
        float h = (1.0f / (orthoSize_ * 0.5f)) * zoom_;
        float w = h / aspectRatio_;
        float q, r;
        
        if (apiSpecific)
        {
            #ifdef USE_OPENGL
            q = 2.0f / farClip_;
            r = -1.0f;
            #else
            q = 1.0f / farClip_;
            r = 0.0f;
            #endif
        }
        else
        {
            q = 1.0f / farClip_;
            r = 0.0f;
        }
        
        ret.m00_ = w;
        ret.m03_ = projectionOffset_.x_ * 2.0f;
        ret.m11_ = h;
        ret.m13_ = projectionOffset_.y_ * 2.0f;
        ret.m22_ = q;
        ret.m23_ = r;
        ret.m33_ = 1.0f;
    }
    
    if (flipVertical_)
        ret = flipMatrix * ret;
    
    return ret;
}