Esempio n. 1
0
        public static void AlignWithTexture(this Texture tex, Plane currentPlane, Plane alignToPlane, Texture alignToTexture)
        {
            // Get reference values for the axes
            var refU = alignToTexture.UAxis;
            var refV = alignToTexture.VAxis;
            // Reference points in the texture plane to use for shifting later on
            var refX = alignToTexture.UAxis * alignToTexture.XShift * alignToTexture.XScale;
            var refY = alignToTexture.VAxis * alignToTexture.YShift * alignToTexture.YScale;

            // Two non-parallel planes intersect at an edge. We want the textures on this face
            // to line up with the textures on the provided face. To do this, we rotate the texture
            // normal on the provided face around the intersection edge to get the new texture axes.
            // Then we rotate the texture reference point around this edge as well to get the new shift values.
            // The scale values on both faces will always end up being the same value.

            // Find the intersection edge vector
            var intersectionEdge = alignToPlane.Normal.Cross(currentPlane.Normal);

            // If the planes are parallel, the texture doesn't need any rotation - just different shift values.
            if (Math.Abs(intersectionEdge.Length()) > 0.01f)
            {
                // Create a plane using the intersection edge as the normal
                var intersectionPlane = new Plane(intersectionEdge, 0);

                var intersect = Plane.Intersect(alignToPlane, currentPlane, intersectionPlane);
                if (intersect != null)
                {
                    // Since the intersection plane is perpendicular to both face planes, we can find the angle
                    // between the two planes (the align plane and the plane of this face) by projecting
                    // the normals of the planes onto the perpendicular plane and taking the cross product.

                    // Project the two normals onto the perpendicular plane
                    var apNormal = intersectionPlane.Project(alignToPlane.Normal).Normalise();
                    var cpNormal = intersectionPlane.Project(currentPlane.Normal).Normalise();

                    // Get the angle between the projected normals
                    var dot   = Math.Round(apNormal.Dot(cpNormal), 4);
                    var angle = (float)Math.Acos(dot);  // A.B = cos(angle)

                    // Rotate the texture axis by the angle around the intersection edge
                    var transform = Matrix4x4.CreateFromAxisAngle(intersectionEdge.Normalise(), angle);
                    refU = transform.Transform(refU);
                    refV = transform.Transform(refV);

                    // Rotate the texture reference points as well, but around the intersection line, not the origin
                    refX = transform.Transform(refX + intersect.Value) - intersect.Value;
                    refY = transform.Transform(refY + intersect.Value) - intersect.Value;
                }
            }

            // Convert the reference points back to get the final values
            tex.Rotation = 0;
            tex.UAxis    = refU;
            tex.VAxis    = refV;
            tex.XShift   = refU.Dot(refX) / alignToTexture.XScale;
            tex.YShift   = refV.Dot(refY) / alignToTexture.YScale;
            tex.XScale   = alignToTexture.XScale;
            tex.YScale   = alignToTexture.YScale;
        }
Esempio n. 2
0
File: Face.cs Progetto: silky/sledge
        public void AlignTextureWithFace(Face face)
        {
            // Get reference values for the axes
            var refU = face.Texture.UAxis;
            var refV = face.Texture.VAxis;
            // Reference points in the texture plane to use for shifting later on
            var refX = face.Texture.UAxis * face.Texture.XShift * face.Texture.XScale;
            var refY = face.Texture.VAxis * face.Texture.YShift * face.Texture.YScale;

            // Two non-parallel planes intersect at an edge. We want the textures on this face
            // to line up with the textures on the provided face. To do this, we rotate the texture
            // normal on the provided face around the intersection edge to get the new texture axes.
            // Then we rotate the texture reference point around this edge as well to get the new shift values.
            // The scale values on both faces will always end up being the same value.

            // Find the intersection edge vector
            var intersectionEdge = face.Plane.Normal.Cross(Plane.Normal);
            // Create a plane using the intersection edge as the normal
            var intersectionPlane = new Plane(intersectionEdge, 0);

            // If the planes are parallel, the texture doesn't need any rotation - just different shift values.
            var intersect = Plane.Intersect(face.Plane, Plane, intersectionPlane);
            if (intersect != null)
            {
                var texNormal = face.Texture.GetNormal();

                // Since the intersection plane is perpendicular to both face planes, we can find the angle
                // between the two planes (the original texture plane and the plane of this face) by projecting
                // the normals of the planes onto the perpendicular plane and taking the cross product.

                // Project the two normals onto the perpendicular plane
                var ptNormal = intersectionPlane.Project(texNormal).Normalise();
                var ppNormal = intersectionPlane.Project(Plane.Normal).Normalise();

                // Get the angle between the projected normals
                var dot = Math.Round(ptNormal.Dot(ppNormal), 4);
                var angle = DMath.Acos(dot); // A.B = cos(angle)

                // Rotate the texture axis by the angle around the intersection edge
                var transform = new UnitRotate(angle, new Line(Coordinate.Zero, intersectionEdge));
                refU = transform.Transform(refU);
                refV = transform.Transform(refV);

                // Rotate the texture reference points as well, but around the intersection line, not the origin
                refX = transform.Transform(refX + intersect) - intersect;
                refY = transform.Transform(refY + intersect) - intersect;
            }

            // Convert the reference points back to get the final values
            Texture.Rotation = 0;
            Texture.UAxis = refU;
            Texture.VAxis = refV;
            Texture.XShift = refU.Dot(refX) / face.Texture.XScale;
            Texture.YShift = refV.Dot(refY) / face.Texture.YScale;
            Texture.XScale = face.Texture.XScale;
            Texture.YScale = face.Texture.YScale;

            CalculateTextureCoordinates(true);
        }