Ejemplo n.º 1
0
        public void Evaluating_the_rule_for_a_CSG_operation(
            CsgOperation op, CsgOperand hitShape, bool insideLeft, bool insideRight, bool expectedResult)
        {
            var result = Csg.IntersectionAllowed(op, hitShape, insideLeft, insideRight);

            result.Should().Be(expectedResult);
        }
Ejemplo n.º 2
0
        public void TestCsgFilteringIntersections()
        {
            var s1 = new Sphere();
            var s2 = new Cube();

            var i1 = new Intersection(1, s1);
            var i2 = new Intersection(2, s2);
            var i3 = new Intersection(3, s1);
            var i4 = new Intersection(4, s2);
            var xs = new Intersections(i1, i2, i3, i4);

            var op = new CsgOperation[] { CsgOperation.Union, CsgOperation.Intersection, CsgOperation.Difference };
            var x0 = new int[] { 0, 1, 0 };
            var x1 = new int[] { 3, 2, 1 };

            for (int i = 0; i < op.Length; i++)
            {
                var           c      = new CSG(op[i], s1, s2);
                Intersections result = c.FilterIntersections(xs);

                Assert.AreEqual(result.Count, 2, i.ToString());
                Assert.AreEqual(result[0], xs[x0[i]], i.ToString());
                Assert.AreEqual(result[1], xs[x1[i]], i.ToString());
            }
        }
Ejemplo n.º 3
0
        public Csg(CsgOperation operation, Shape left, Shape right)
        {
            Operation = operation;

            Left        = left;
            left.Parent = this;

            Right        = right;
            right.Parent = this;
        }
Ejemplo n.º 4
0
        public CSG(CsgOperation op, RTObject left, RTObject right)
        {
            Operation = op;
            Left      = left;
            Right     = right;

            Left.Parent  = this;
            Right.Parent = this;
            _bounds      = null;
        }
Ejemplo n.º 5
0
        //// ===========================================================================================================
        //// Constructors
        //// ===========================================================================================================

        public CsgShape(
            string name,
            CsgOperation operation,
            Shape left,
            Shape right,
            Matrix4x4?transform = null,
            Material?material   = null)
            : this(operation, left, right, name, transform, material)
        {
        }
Ejemplo n.º 6
0
        public void Filtering_a_list_of_intersections(CsgOperation operation, int index1, int index2)
        {
            var s1     = Sphere.UnitSphere();
            var s2     = new Cube();
            var csg    = new Csg(operation, s1, s2);
            var xs     = IntersectionCollection.Create((1, s1), (2, s2), (3, s1), (4, s2));
            var result = csg.FilterIntersections(xs);

            result.Intersections.Should().HaveCount(2);
            result[0].Should().Be(xs[index1]);
            result[1].Should().Be(xs[index2]);
        }
Ejemplo n.º 7
0
 internal static bool IsIntersectionAllowed(
     CsgOperation operation,
     bool isLeftHit,
     bool isWithinLeft,
     bool isWithinRight)
 {
     return(operation switch
     {
         CsgOperation.Union => (isLeftHit && !isWithinRight) || (!isLeftHit && !isWithinLeft),
         CsgOperation.Intersection => (isLeftHit && isWithinRight) || (!isLeftHit && isWithinLeft),
         CsgOperation.Difference => (isLeftHit && !isWithinRight) || (!isLeftHit && isWithinLeft),
         _ => throw new ArgumentOutOfRangeException(nameof(operation), operation, null)
     });
Ejemplo n.º 8
0
        Given_a_set_of_intersections_produce_a_subset_of_only_those_intersections_that_conform_to_the_operation_of_the_current_CSG_object(
            CsgOperation operation,
            int intersectionIndex1,
            int intersectionIndex2)
        {
            var left          = new Sphere();
            var right         = new Cube();
            var csg           = new CsgShape(operation, left, right);
            var intersections = new IntersectionList((1, left), (2, right), (3, left), (4, right));
            var filtered      = csg.FilterIntersections(intersections);

            filtered.Should()
            .HaveCount(2)
            .And.ContainInOrder(intersections[intersectionIndex1], intersections[intersectionIndex2]);
        }
Ejemplo n.º 9
0
 internal static bool IntersectionAllowed(CsgOperation op, CsgOperand hitShape, bool insideLeft, bool insideRight)
 {
     return(op switch
     {
         CsgOperation.Union =>
         (hitShape == CsgOperand.Left && !insideRight) ||
         (hitShape == CsgOperand.Right && !insideLeft),
         CsgOperation.Intersection =>
         (hitShape == CsgOperand.Left && insideRight) ||
         (hitShape == CsgOperand.Right && insideLeft),
         CsgOperation.Difference =>
         (hitShape == CsgOperand.Left && !insideRight) ||
         (hitShape == CsgOperand.Right && insideLeft),
         _ => false
     });
Ejemplo n.º 10
0
	public void ProcessSlave( CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info )
	{
		switch( inSide )
		{
		case CsgOperation.EPolySide.PolySide_Outside:
		case CsgOperation.EPolySide.PolySide_Planar_Outside:
			// add to deferred faces
			inOperation.AddDeferredFace( inFace );
			break;
		case CsgOperation.EPolySide.PolySide_Inside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
		case CsgOperation.EPolySide.PolySide_Planar_Inside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
			break;
		}
	}
Ejemplo n.º 11
0
        public static bool IntersectionAllowed(CsgOperation op, bool lhit, bool inl, bool inr)
        {
            if (op == CsgOperation.Union)
            {
                return((lhit && !inr) || (!lhit && !inl));
            }
            else if (op == CsgOperation.Intersection)
            {
                return((lhit && inr) || (!lhit && inl));
            }
            else if (op == CsgOperation.Difference)
            {
                return((lhit && !inr) || (!lhit && inl));
            }

            return(false);
        }
Ejemplo n.º 12
0
    // TODO

    public void ProcessMaster(CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info)
    {
        switch (inSide)
        {
        case CsgOperation.EPolySide.PolySide_Outside:
        case CsgOperation.EPolySide.PolySide_Planar_Outside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
            break;

        case CsgOperation.EPolySide.PolySide_Inside:
        case CsgOperation.EPolySide.PolySide_Planar_Inside:
            // add to deferred faces
            inOperation.AddDeferredFace(inFace);
            break;
        }
    }
Ejemplo n.º 13
0
        public CsgShape(
            CsgOperation operation,
            Shape left,
            Shape right,
            string?name         = null,
            Matrix4x4?transform = null,
            Material?material   = null)
            : base(name, transform, material)
        {
            Operation = operation;
            Left      = left;
            Right     = right;

            Left.Parent  = this;
            Right.Parent = this;

            BoundingBox = new BoundingBox(Point.Zero, Point.Zero);
        }
Ejemplo n.º 14
0
	public void ProcessMaster( CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info )
	{
		switch( inSide )
		{
		case CsgOperation.EPolySide.PolySide_Outside:
		case CsgOperation.EPolySide.PolySide_Planar_Outside:
			// add cutted polygons
			if( (inFace.flags & Face.FaceFlags_WasCutted) != 0 )
				inOperation.AddPlanarFace( inFace );
			break;
		case CsgOperation.EPolySide.PolySide_Inside:
		case CsgOperation.EPolySide.PolySide_Planar_Inside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
			// discard original node
			inOperation.MarkNodeAsDestroyed();
			break;
		}
	}
Ejemplo n.º 15
0
	// TODO
	
	public void ProcessMaster( CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info )
	{
		switch( inSide )
		{
		case CsgOperation.EPolySide.PolySide_Outside:
		case CsgOperation.EPolySide.PolySide_Planar_Outside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
			break;
		case CsgOperation.EPolySide.PolySide_Inside:
		case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
		case CsgOperation.EPolySide.PolySide_Planar_Inside:
			// clone face
			Face newFace = (Face)inFace.Clone();
			newFace.Reverse();
			// add to deferred faces
			inOperation.AddDeferredFace( newFace );
			break;
		}
	}
Ejemplo n.º 16
0
    public void ProcessSlave(CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info)
    {
        switch (inSide)
        {
        case CsgOperation.EPolySide.PolySide_Outside:
        case CsgOperation.EPolySide.PolySide_Planar_Outside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
            break;

        case CsgOperation.EPolySide.PolySide_Inside:
        case CsgOperation.EPolySide.PolySide_Planar_Inside:
            // clone face
            Face newFace = (Face)inFace.Clone();
            newFace.Reverse();
            // add to deferred faces
            inOperation.AddDeferredFace(newFace);
            break;
        }
    }
Ejemplo n.º 17
0
    public void ProcessMaster(CsgOperation inOperation, Face inFace, CsgOperation.EPolySide inSide, CsgOperation.OperationInfo info)
    {
        switch (inSide)
        {
        case CsgOperation.EPolySide.PolySide_Outside:
        case CsgOperation.EPolySide.PolySide_Planar_Outside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Inside:
            // add cutted polygons
            if ((inFace.flags & Face.FaceFlags_WasCutted) != 0)
            {
                inOperation.AddPlanarFace(inFace);
            }
            break;

        case CsgOperation.EPolySide.PolySide_Inside:
        case CsgOperation.EPolySide.PolySide_Planar_Inside:
        case CsgOperation.EPolySide.PolySide_CoPlanar_Outside:
            // discard node
            inOperation.MarkNodeAsDestroyed();
            break;
        }
    }
Ejemplo n.º 18
0
        public void TestCsgRules()
        {
            var op = new CsgOperation[]
            {
                CsgOperation.Union, CsgOperation.Union, CsgOperation.Union, CsgOperation.Union, CsgOperation.Union, CsgOperation.Union, CsgOperation.Union, CsgOperation.Union,
                CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection, CsgOperation.Intersection,
                CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference, CsgOperation.Difference
            };
            var lhit = new bool[]
            {
                true, true, true, true, false, false, false, false,
                true, true, true, true, false, false, false, false,
                true, true, true, true, false, false, false, false
            };
            var inl = new bool[]
            {
                true, true, false, false, true, true, false, false,
                true, true, false, false, true, true, false, false,
                true, true, false, false, true, true, false, false
            };
            var inr = new bool[]
            {
                true, false, true, false, true, false, true, false,
                true, false, true, false, true, false, true, false,
                true, false, true, false, true, false, true, false
            };
            var result = new bool[]
            {
                false, true, false, true, false, false, true, true,
                true, false, true, false, true, true, false, false,
                false, true, false, true, true, true, false, false
            };

            for (int i = 0; i < op.Length; i++)
            {
                Assert.AreEqual(result[i], CSG.IntersectionAllowed(op[i], lhit[i], inl[i], inr[i]));
            }
        }
Ejemplo n.º 19
0
    /// <summary>
    /// Performs CSG Operation on this Object (Master) with given Slaves.
    /// </summary>
    /// <param name='inOper'>
    /// In oper.
    /// </param>
    /// <param name='inSlaves'>
    /// In slaves.
    /// </param>
    public void PerformCSG(CsgOperation.ECsgOperation inOper, GameObject[] inSlaves)
    {
        //
        CreateFromMesh();

        // create bsp generator
        BspGen gen = new BspGen(GlobalSettings.BspOptimization);

        rootNode = gen.GenerateBspTree(faces);

        List <CSGFace> savedFaces = new List <CSGFace>();

        //
        foreach (GameObject g in inSlaves)
        {
            CSGObject slave = g.GetComponent <CSGObject>();

            // if we have a csg object and we are not our self
            // and intersecting
            if (slave && g != gameObject && intersect(slave))
            {
                Debug.Log(g.name);

                //
                slave.CreateFromMesh();

                // ....
                BspGen genSlave = new BspGen(GlobalSettings.BspOptimization);
                slave.rootNode = genSlave.GenerateBspTree(slave.faces);

                CsgVisitor visitor = null;

                switch (inOper)
                {
                case CsgOperation.ECsgOperation.CsgOper_Additive:
                    visitor = new UnionVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_Subtractive:
                    visitor = new SubtractiveVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_Intersect:
                    visitor = new IntersectVisitor();
                    break;

                case CsgOperation.ECsgOperation.CsgOper_DeIntersect:
                    visitor = new DeIntersectVisitor();
                    break;

                default:
                    visitor = null;
                    break;
                }


                CsgOperation oper = new CsgOperation(visitor);

                oper.Perform(inOper, this, slave);

                // save faces
                savedFaces.AddRange(faces);
            }
        }


        // If we want to merge Coplanars after every Operation
        if (GlobalSettings.MergeCoplanars)
        {
            MergeFaces();
        }

        // for additive or subtracte operation, built faces list from bsp tree
        // for others, use faces directly
        if (inOper == CsgOperation.ECsgOperation.CsgOper_Additive || inOper == CsgOperation.ECsgOperation.CsgOper_Subtractive)
        {
            // create new face list
            List <CSGFace> newFaces = new List <CSGFace>();
            // create faces from bsp nodes
            BspHelper.FacesFromNodes(rootNode, newFaces);
            // copy to face list
            faces = newFaces;
        }
        else
        {
            // copy saved faces
            faces = savedFaces;
        }


        //	Face.MergeCoplanars( faces );

        // copy to unity structure
        TransferFacesToMesh();


        // dumb tree
//		BspHelper.DumpTree( rootNode );
    }
Ejemplo n.º 20
0
	/// <summary>
	/// Performs CSG Operation on this Object (Master) with given Slaves.
	/// </summary>
	/// <param name='inOper'>
	/// In oper.
	/// </param>
	/// <param name='inSlaves'>
	/// In slaves.
	/// </param>
	public void PerformCSG( CsgOperation.ECsgOperation inOper, GameObject[] inSlaves )
	{
		// 
		CreateFromMesh();
		
		// create bsp generator
		BspGen gen = new BspGen( GlobalSettings.BspOptimization );
				
		rootNode = gen.GenerateBspTree( faces );
		
		List<Face> savedFaces = new List<Face>();
		
		// 
  		foreach ( GameObject g in inSlaves )
  		{
			CSGObject slave = g.GetComponent<CSGObject>();
			
			// if we have a csg object and we are not our self
			// and intersecting
			if( slave && g != gameObject && intersect(slave) )
			{	
       			Debug.Log(g.name);
				
				// 
				slave.CreateFromMesh();
				
				// ....
				BspGen genSlave = new BspGen( GlobalSettings.BspOptimization );
				slave.rootNode = genSlave.GenerateBspTree( slave.faces );
				
				CsgVisitor visitor = null;
				
				switch( inOper )
				{
				case CsgOperation.ECsgOperation.CsgOper_Additive:
					visitor = new UnionVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_Subtractive:
					visitor = new SubtractiveVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_Intersect:
					visitor = new IntersectVisitor();
					break;
				case CsgOperation.ECsgOperation.CsgOper_DeIntersect:
					visitor = new DeIntersectVisitor();
					break;
				default:
					visitor = null;
					break;
				}
				
				
				CsgOperation oper = new CsgOperation( visitor );
				
				oper.Perform( inOper, this, slave );
				
				// save faces
				savedFaces.AddRange( faces );
			}
  		}
		
		
		// If we want to merge Coplanars after every Operation
		if( GlobalSettings.MergeCoplanars )
		{
			MergeFaces();	
		}
  		
		// for additive or subtracte operation, built faces list from bsp tree
		// for others, use faces directly
		if( inOper == CsgOperation.ECsgOperation.CsgOper_Additive || inOper == CsgOperation.ECsgOperation.CsgOper_Subtractive )
		{
		
			// create new face list
			List<Face> newFaces = new List<Face>();
			// create faces from bsp nodes
			BspHelper.FacesFromNodes( rootNode, newFaces );
			// copy to face list
			faces = newFaces;	
			
		}
		else
		{
			// copy saved faces
			faces = savedFaces;	
		}
		
		
	//	Face.MergeCoplanars( faces );
		
		// copy to unity structure
		TransferFacesToMesh();
		
		
		// dumb tree
//		BspHelper.DumpTree( rootNode );
		
	}