/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the OpenSim Project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ using System; using System.Collections.Generic; using System.Text; using OpenSim.Framework.Console; namespace OpenSim.Region.Physics.Meshing { // A simple hull is a set of vertices building up to simplices that border a region // The word simple referes to the fact, that this class assumes, that all simplices // do not intersect // Simple hulls can be added and subtracted. // Vertices can be checked to lie inside a hull // Also note, that the sequence of the vertices is important and defines if the region that // is defined by the hull lies inside or outside the simplex chain public class SimpleHull { List vertices = new List(); List holeVertices = new List(); // Only used, when the hull is hollow // Adds a vertex to the end of the list public void AddVertex(Vertex v) { vertices.Add(v); } override public String ToString() { String result=""; foreach (Vertex v in vertices) { result += "b:" + v.ToString() + "\n"; } return result; } public List getVertices() { List newVertices = new List(); newVertices.AddRange(vertices); newVertices.Add(null); newVertices.AddRange(holeVertices); return newVertices; } public SimpleHull Clone() { SimpleHull result = new SimpleHull(); foreach (Vertex v in vertices) { result.AddVertex(v.Clone()); } foreach (Vertex v in this.holeVertices) { result.holeVertices.Add(v.Clone()); } return result; } public bool IsPointIn(Vertex v1) { int iCounter=0; List simplices=buildSimplexList(); foreach (Simplex s in simplices) { // Send a ray along the positive X-Direction // Note, that this direction must correlate with the "below" interpretation // of handling for the special cases below Manager.PhysicsVector intersection = s.RayIntersect(v1, new Manager.PhysicsVector(1.0f, 0.0f, 0.0f), true); if (intersection == null) continue; // No intersection. Done. More tests to follow otherwise // Did we hit the end of a simplex? // Then this can be one of two special cases: // 1. we go through a border exactly at a joint // 2. we have just marginally touched a corner // 3. we can slide along a border // Solution: If the other vertex is "below" the ray, we don't count it // Thus corners pointing down are counted twice, corners pointing up are not counted // borders are counted once if (intersection.IsIdentical(s.v1, 0.001f)) { if (s.v2.Y < v1.Y) continue; } // Do this for the other vertex two if (intersection.IsIdentical(s.v2, 0.001f)) { if (s.v1.Y buildSimplexList() { List result = new List(); // Not asserted but assumed: at least three vertices for (int i=0; i simple = buildSimplexList(); foreach (Simplex sTest in simple) { Manager.PhysicsVector vvTemp = Simplex.Intersect(sTest, s, -.001f, -.001f, 0.999f, .999f); Vertex vTemp=null; if (vvTemp != null) vTemp = new Vertex(vvTemp); if (vTemp!=null) { Manager.PhysicsVector diff=(s.v1-vTemp); float distTemp=diff.length(); if (bestIntersection==null || distTemp