示例#1
0
文件: Camera.cpp 项目: xamarin/Urho3D
Frustum Camera::GetSplitFrustum(float nearClip, float farClip) const
{
    if (projectionDirty_)
        UpdateProjection();

    nearClip = Max(nearClip, projNearClip_);
    farClip = Min(farClip, projFarClip_);
    if (farClip < nearClip)
        farClip = nearClip;

    Frustum ret;

    if (customProjection_)
    {
        // DefineSplit() needs to project the near & far distances, so can not use a combined view-projection matrix.
        // Transform to world space afterward instead
        ret.DefineSplit(projection_, nearClip, farClip);
        ret.Transform(GetEffectiveWorldTransform());
    }
    else
    {
        if (!orthographic_)
            ret.Define(fov_, aspectRatio_, zoom_, nearClip, farClip, GetEffectiveWorldTransform());
        else
            ret.DefineOrtho(orthoSize_, aspectRatio_, zoom_, nearClip, farClip, GetEffectiveWorldTransform());
    }

    return ret;
}
示例#2
0
文件: Camera.cpp 项目: Boshin/Urho3D
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;
}
示例#3
0
文件: Camera.cpp 项目: Boshin/Urho3D
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;
}
示例#4
0
文件: Camera.cpp 项目: Boshin/Urho3D
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;
}
示例#5
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;
}
示例#6
0
文件: Camera.cpp 项目: xamarin/Urho3D
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;
}
示例#7
0
文件: Camera.cpp 项目: xamarin/Urho3D
Frustum Camera::GetViewSpaceSplitFrustum(float nearClip, float farClip) const
{
    if (projectionDirty_)
        UpdateProjection();

    nearClip = Max(nearClip, projNearClip_);
    farClip = Min(farClip, projFarClip_);
    if (farClip < nearClip)
        farClip = nearClip;

    Frustum ret;

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

    return ret;
}
示例#8
0
bool DecalSet::AddDecal(Drawable* target, const Vector3& worldPosition, const Quaternion& worldRotation, float size,
    float aspectRatio, float depth, const Vector2& topLeftUV, const Vector2& bottomRightUV, float timeToLive, float normalCutoff,
    unsigned subGeometry)
{
    URHO3D_PROFILE(AddDecal);

    // Do not add decals in headless mode
    if (!node_ || !GetSubsystem<Graphics>())
        return false;

    if (!target || !target->GetNode())
    {
        URHO3D_LOGERROR("Null target drawable for decal");
        return false;
    }

    // Check for animated target and switch into skinned/static mode if necessary
    AnimatedModel* animatedModel = dynamic_cast<AnimatedModel*>(target);
    if ((animatedModel && !skinned_) || (!animatedModel && skinned_))
    {
        RemoveAllDecals();
        skinned_ = animatedModel != 0;
        bufferDirty_ = true;
    }

    // Center the decal frustum on the world position
    Vector3 adjustedWorldPosition = worldPosition - 0.5f * depth * (worldRotation * Vector3::FORWARD);
    /// \todo target transform is not right if adding a decal to StaticModelGroup
    Matrix3x4 targetTransform = target->GetNode()->GetWorldTransform().Inverse();

    // For an animated model, adjust the decal position back to the bind pose
    // To do this, need to find the bone the decal is colliding with
    if (animatedModel)
    {
        Skeleton& skeleton = animatedModel->GetSkeleton();
        unsigned numBones = skeleton.GetNumBones();
        Bone* bestBone = 0;
        float bestSize = 0.0f;

        for (unsigned i = 0; i < numBones; ++i)
        {
            Bone* bone = skeleton.GetBone(i);
            if (!bone->node_ || !bone->collisionMask_)
                continue;

            // Represent the decal as a sphere, try to find the biggest colliding bone
            Sphere decalSphere
                (bone->node_->GetWorldTransform().Inverse() * worldPosition, 0.5f * size / bone->node_->GetWorldScale().Length());

            if (bone->collisionMask_ & BONECOLLISION_BOX)
            {
                float size = bone->boundingBox_.HalfSize().Length();
                if (bone->boundingBox_.IsInside(decalSphere) && size > bestSize)
                {
                    bestBone = bone;
                    bestSize = size;
                }
            }
            else if (bone->collisionMask_ & BONECOLLISION_SPHERE)
            {
                Sphere boneSphere(Vector3::ZERO, bone->radius_);
                float size = bone->radius_;
                if (boneSphere.IsInside(decalSphere) && size > bestSize)
                {
                    bestBone = bone;
                    bestSize = size;
                }
            }
        }

        if (bestBone)
            targetTransform = (bestBone->node_->GetWorldTransform() * bestBone->offsetMatrix_).Inverse();
    }

    // Build the decal frustum
    Frustum decalFrustum;
    Matrix3x4 frustumTransform = targetTransform * Matrix3x4(adjustedWorldPosition, worldRotation, 1.0f);
    decalFrustum.DefineOrtho(size, aspectRatio, 1.0, 0.0f, depth, frustumTransform);

    Vector3 decalNormal = (targetTransform * Vector4(worldRotation * Vector3::BACK, 0.0f)).Normalized();

    decals_.Resize(decals_.Size() + 1);
    Decal& newDecal = decals_.Back();
    newDecal.timeToLive_ = timeToLive;

    Vector<PODVector<DecalVertex> > faces;
    PODVector<DecalVertex> tempFace;

    unsigned numBatches = target->GetBatches().Size();

    // Use either a specified subgeometry in the target, or all
    if (subGeometry < numBatches)
        GetFaces(faces, target, subGeometry, decalFrustum, decalNormal, normalCutoff);
    else
    {
        for (unsigned i = 0; i < numBatches; ++i)
            GetFaces(faces, target, i, decalFrustum, decalNormal, normalCutoff);
    }

    // Clip the acquired faces against all frustum planes
    for (unsigned i = 0; i < NUM_FRUSTUM_PLANES; ++i)
    {
        for (unsigned j = 0; j < faces.Size(); ++j)
        {
            PODVector<DecalVertex>& face = faces[j];
            if (face.Empty())
                continue;

            ClipPolygon(tempFace, face, decalFrustum.planes_[i], skinned_);
            face = tempFace;
        }
    }

    // Now triangulate the resulting faces into decal vertices
    for (unsigned i = 0; i < faces.Size(); ++i)
    {
        PODVector<DecalVertex>& face = faces[i];
        if (face.Size() < 3)
            continue;

        for (unsigned j = 2; j < face.Size(); ++j)
        {
            newDecal.AddVertex(face[0]);
            newDecal.AddVertex(face[j - 1]);
            newDecal.AddVertex(face[j]);
        }
    }

    // Check if resulted in no triangles
    if (newDecal.vertices_.Empty())
    {
        decals_.Pop();
        return true;
    }

    if (newDecal.vertices_.Size() > maxVertices_)
    {
        URHO3D_LOGWARNING("Can not add decal, vertex count " + String(newDecal.vertices_.Size()) + " exceeds maximum " +
                   String(maxVertices_));
        decals_.Pop();
        return false;
    }
    if (newDecal.indices_.Size() > maxIndices_)
    {
        URHO3D_LOGWARNING("Can not add decal, index count " + String(newDecal.indices_.Size()) + " exceeds maximum " +
                   String(maxIndices_));
        decals_.Pop();
        return false;
    }

    // Calculate UVs
    Matrix4 projection(Matrix4::ZERO);
    projection.m11_ = (1.0f / (size * 0.5f));
    projection.m00_ = projection.m11_ / aspectRatio;
    projection.m22_ = 1.0f / depth;
    projection.m33_ = 1.0f;

    CalculateUVs(newDecal, frustumTransform.Inverse(), projection, topLeftUV, bottomRightUV);

    // Transform vertices to this node's local space and generate tangents
    Matrix3x4 decalTransform = node_->GetWorldTransform().Inverse() * target->GetNode()->GetWorldTransform();
    TransformVertices(newDecal, skinned_ ? Matrix3x4::IDENTITY : decalTransform);
    GenerateTangents(&newDecal.vertices_[0], sizeof(DecalVertex), &newDecal.indices_[0], sizeof(unsigned short), 0,
        newDecal.indices_.Size(), offsetof(DecalVertex, normal_), offsetof(DecalVertex, texCoord_), offsetof(DecalVertex,
        tangent_));

    newDecal.CalculateBoundingBox();
    numVertices_ += newDecal.vertices_.Size();
    numIndices_ += newDecal.indices_.Size();

    // Remove oldest decals if total vertices exceeded
    while (decals_.Size() && (numVertices_ > maxVertices_ || numIndices_ > maxIndices_))
        RemoveDecals(1);

    URHO3D_LOGDEBUG("Added decal with " + String(newDecal.vertices_.Size()) + " vertices");

    // If new decal is time limited, subscribe to scene post-update
    if (newDecal.timeToLive_ > 0.0f && !subscribed_)
        UpdateEventSubscription(false);

    MarkDecalsDirty();
    return true;
}