Selaa lähdekoodia

Moved polygon clipping back into DecalSet & PolyHedron, as the common function interface was not pleasant.

Lasse Öörni 13 vuotta sitten
vanhempi
sitoutus
803b7cf53a

+ 57 - 6
Engine/Graphics/DecalSet.cpp

@@ -28,7 +28,6 @@
 #include "Context.h"
 #include "Context.h"
 #include "DecalSet.h"
 #include "DecalSet.h"
 #include "Geometry.h"
 #include "Geometry.h"
-#include "GeometryUtils.h"
 #include "Graphics.h"
 #include "Graphics.h"
 #include "Log.h"
 #include "Log.h"
 #include "Node.h"
 #include "Node.h"
@@ -46,6 +45,62 @@ static const unsigned STATIC_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_T
 static const unsigned SKINNED_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT | MASK_BLENDWEIGHTS |
 static const unsigned SKINNED_ELEMENT_MASK = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT | MASK_BLENDWEIGHTS |
     MASK_BLENDINDICES;
     MASK_BLENDINDICES;
 
 
+static DecalVertex ClipEdge(const DecalVertex& v0, const DecalVertex& v1, float d0, float d1, bool skinned)
+{
+    DecalVertex ret;
+    float t = d0 / (d0 - d1);
+    
+    ret.position_ = v0.position_ + t * (v1.position_ - v0.position_);
+    ret.normal_ = v0.normal_ + t * (v1.normal_ - v0.normal_);
+    if (skinned)
+    {
+        // Blend weights / indices can not be easily interpolated, choose the one that is nearer to the split plane
+        const DecalVertex& src = Abs(d0) < Abs(d1) ? v0 : v1;
+        for (unsigned i = 0; i < 4; ++i)
+        {
+            ret.blendWeights_[i] = src.blendWeights_[i];
+            ret.blendIndices_[i] = src.blendIndices_[i];
+        }
+    }
+    
+    return ret;
+}
+
+static void ClipPolygon(PODVector<DecalVertex>& dest, const PODVector<DecalVertex>& src, const Plane& plane, bool skinned)
+{
+    unsigned last;
+    float lastDistance = 0.0f;
+    dest.Clear();
+    
+    if (src.Empty())
+        return;
+    
+    for (unsigned i = 0; i < src.Size(); ++i)
+    {
+        float distance = plane.Distance(src[i].position_);
+        if (distance >= 0.0f)
+        {
+            if (lastDistance < 0.0f)
+                dest.Push(ClipEdge(src[last], src[i], lastDistance, distance, skinned));
+            
+            dest.Push(src[i]);
+        }
+        else
+        {
+            if (lastDistance >= 0.0f && i != 0)
+                dest.Push(ClipEdge(src[last], src[i], lastDistance, distance, skinned));
+        }
+        
+        last = i;
+        lastDistance = distance;
+    }
+    
+    // Recheck the distances of the last and first vertices and add the final clipped vertex if applicable
+    float distance = plane.Distance(src[0].position_);
+    if ((lastDistance < 0.0f && distance >= 0.0f) || (lastDistance >= 0.0f && distance < 0.0f))
+        dest.Push(ClipEdge(src[last], src[0], lastDistance, distance, skinned));
+}
+
 void Decal::CalculateBoundingBox()
 void Decal::CalculateBoundingBox()
 {
 {
     boundingBox_.Clear();
     boundingBox_.Clear();
@@ -256,11 +311,7 @@ bool DecalSet::AddDecal(Drawable* target, const Vector3& worldPosition, const Qu
             if (face.Empty())
             if (face.Empty())
                 continue;
                 continue;
             
             
-            tempFace.Resize(face.Size() + 2);
-            unsigned outVertices = ClipPolygon((float*)&face[0], (float*)&tempFace[0], face.Size(), sizeof(DecalVertex),
-                decalFrustum.planes_[i], skinned_ ? (sizeof(DecalVertex) - 4 * sizeof(float) - 4 * sizeof(unsigned char)) : 0);
-            tempFace.Resize(outVertices);
-            
+            ClipPolygon(tempFace, face, decalFrustum.planes_[i], skinned_);
             face = tempFace;
             face = tempFace;
         }
         }
     }
     }

+ 0 - 139
Engine/Math/GeometryUtils.cpp

@@ -1,139 +0,0 @@
-//
-// Urho3D Engine
-// Copyright (c) 2008-2012 Lasse Öörni
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#include "Precompiled.h"
-#include "GeometryUtils.h"
-#include "Plane.h"
-
-inline void ClipEdge(float* output, float* v0, float* v1, float d0, float d1, unsigned components, unsigned blendWeightsComp)
-{
-    float t = d0 / (d0 - d1);
-    
-    if (!blendWeightsComp)
-    {
-       for (unsigned i = 0; i < components; ++i)
-            output[i] = v0[i] + t * (v1[i] - v0[i]);
-    }
-    else
-    {
-        for (unsigned i = 0; i < blendWeightsComp; ++i)
-            output[i] = v0[i] + t * (v1[i] - v0[i]);
-        
-        // Blend weights / indices can not be easily interpolated, choose the one that is nearer to the split plane
-        if (Abs(d0) < Abs(d1))
-        {
-            for (unsigned i = blendWeightsComp; i < components; ++i)
-                output[i] = v0[i];
-        }
-        else
-        {
-            for (unsigned i = blendWeightsComp; i < components; ++i)
-                output[i] = v1[i];
-        }
-    }
-}
-
-inline void CopyVertex(float* output, float* input, unsigned components)
-{
-    for (unsigned i = 0; i < components; ++i)
-        output[i] = input[i];
-}
-
-unsigned ClipPolygon(float* input, float* output, unsigned vertexCount, unsigned vertexSize, const Plane& plane,
-    unsigned blendWeightsOffset, float* clip, unsigned* clipVertexCount)
-{
-    unsigned components = vertexSize / sizeof(float);
-    unsigned blendWeightsComp = blendWeightsOffset / sizeof(float);
-    unsigned outVertexCount = 0;
-    float* lastVertex = input;
-    float lastDistance = 0.0f;
-    
-    if (clipVertexCount)
-        *clipVertexCount = 0;
-    
-    for (unsigned i = 0; i < vertexCount; ++i)
-    {
-        float* vertex = input + i * components;
-        const Vector3& position = *((Vector3*)vertex);
-        float distance = plane.Distance(position);
-        if (distance >= 0.0f)
-        {
-            if (lastDistance < 0.0f)
-            {
-                ClipEdge(output, lastVertex, vertex, lastDistance, distance, components, blendWeightsComp);
-                if (clip && clipVertexCount)
-                {
-                    CopyVertex(clip, output, components);
-                    clip += components;
-                    ++(*clipVertexCount);
-                }
-                output += components;
-                ++outVertexCount;
-            }
-            
-            for (unsigned j = 0; j < components; ++j)
-                output[j] = vertex[j];
-            output += components;
-            ++outVertexCount;
-        }
-        else
-        {
-            if (lastDistance >= 0.0f && i != 0)
-            {
-                ClipEdge(output, lastVertex, vertex, lastDistance, distance, components, blendWeightsComp);
-                if (clip && clipVertexCount)
-                {
-                    CopyVertex(clip, output, components);
-                    clip += components;
-                    ++(*clipVertexCount);
-                }
-                output += components;
-                ++outVertexCount;
-            }
-        }
-        
-        lastVertex = vertex;
-        lastDistance = distance;
-    }
-    
-    // Recheck the distances of the last and first vertices and add the final clipped vertex if applicable
-    {
-        float* vertex = input;
-        const Vector3& position = *((Vector3*)vertex);
-        float distance = plane.Distance(position);
-        if ((lastDistance < 0.0f && distance >= 0.0f) || (lastDistance >= 0.0f && distance < 0.0f))
-        {
-            ClipEdge(output, lastVertex, vertex, lastDistance, distance, components, blendWeightsComp);
-            if (clip && clipVertexCount)
-            {
-                CopyVertex(clip, output, components);
-                clip += components;
-                ++(*clipVertexCount);
-            }
-            output += components;
-            ++outVertexCount;
-        }
-    }
-    
-    return outVertexCount;
-}

+ 0 - 30
Engine/Math/GeometryUtils.h

@@ -1,30 +0,0 @@
-//
-// Urho3D Engine
-// Copyright (c) 2008-2012 Lasse Öörni
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-
-#pragma once
-
-class Plane;
-
-/// Clip a polygon with a plane. Output may have up to 2x vertices of input. Vertices can have additional float values which will be interpolated, and/or blend weights which will just be copied from the nearer vertex. Optionally put clipped vertices into a separate output array. Return number of output vertices.
-unsigned ClipPolygon(float* input, float* output, unsigned vertexCount, unsigned vertexSize, const Plane& plane, unsigned blendWeightsOffset = 0, float* clip = 0, unsigned* clipVertexCount = 0);
-

+ 48 - 18
Engine/Math/Polyhedron.cpp

@@ -23,7 +23,6 @@
 
 
 #include "Precompiled.h"
 #include "Precompiled.h"
 #include "Frustum.h"
 #include "Frustum.h"
-#include "GeometryUtils.h"
 #include "Polyhedron.h"
 #include "Polyhedron.h"
 
 
 Polyhedron::~Polyhedron()
 Polyhedron::~Polyhedron()
@@ -92,32 +91,63 @@ void Polyhedron::AddFace(const PODVector<Vector3>& face)
 
 
 void Polyhedron::Clip(const Plane& plane)
 void Polyhedron::Clip(const Plane& plane)
 {
 {
-    unsigned totalVertices = 0;
-    unsigned totalClippedVertices = 0;
-    for (unsigned i = 0; i < faces_.Size(); ++i)
-        totalVertices += faces_[i].Size();
-    
-    // Clipping may produce max. 1 vertex more for each face
-    clippedVertices_.Resize(totalVertices + faces_.Size());
+    clippedVertices_.Clear();
     
     
     for (unsigned i = 0; i < faces_.Size(); ++i)
     for (unsigned i = 0; i < faces_.Size(); ++i)
     {
     {
         PODVector<Vector3>& face = faces_[i];
         PODVector<Vector3>& face = faces_[i];
-        if (face.Empty())
-            continue;
+        Vector3 lastVertex;
+        float lastDistance = 0.0f;
+        
+        outFace_.Clear();
+        
+        for (unsigned j = 0; j < face.Size(); ++j)
+        {
+            float distance = plane.Distance(face[j]);
+            if (distance >= 0.0f)
+            {
+                if (lastDistance < 0.0f)
+                {
+                    float t = lastDistance / (lastDistance - distance);
+                    Vector3 clippedVertex = lastVertex + t * (face[j] - lastVertex);
+                    outFace_.Push(clippedVertex);
+                    clippedVertices_.Push(clippedVertex);
+                }
+                
+                outFace_.Push(face[j]);
+            }
+            else
+            {
+                if (lastDistance >= 0.0f && j != 0)
+                {
+                    float t = lastDistance / (lastDistance - distance);
+                    Vector3 clippedVertex = lastVertex + t * (face[j] - lastVertex);
+                    outFace_.Push(clippedVertex);
+                    clippedVertices_.Push(clippedVertex);
+                }
+            }
+            
+            lastVertex = face[j];
+            lastDistance = distance;
+        }
         
         
-        outFace_.Resize(face.Size() * 2);
+        // Recheck the distances of the last and first vertices and add the final clipped vertex if applicable
+        float distance = plane.Distance(face[0]);
+        if ((lastDistance < 0.0f && distance >= 0.0f) || (lastDistance >= 0.0f && distance < 0.0f))
+        {
+            float t = lastDistance / (lastDistance - distance);
+            Vector3 clippedVertex = lastVertex + t * (face[0] - lastVertex);
+            outFace_.Push(clippedVertex);
+            clippedVertices_.Push(clippedVertex);
+        }
         
         
-        unsigned outClippedVertices = 0;
-        unsigned outVertices = ClipPolygon((float*)&face[0], (float*)&outFace_[0], face.Size(), sizeof(Vector3), plane,
-            0, (float*)&clippedVertices_[totalClippedVertices], &outClippedVertices);
-        totalClippedVertices += outClippedVertices;
+        // Do not keep faces which are less than triangles
+        if (outFace_.Size() < 3)
+            outFace_.Clear();
         
         
-        outFace_.Resize(outVertices);
+        face = outFace_;
     }
     }
     
     
-    clippedVertices_.Resize(totalClippedVertices);
-    
     // Remove empty faces
     // Remove empty faces
     for (unsigned i = faces_.Size() - 1; i < faces_.Size(); --i)
     for (unsigned i = faces_.Size() - 1; i < faces_.Size(); --i)
     {
     {