Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


BlackJoker

Member Since 28 Feb 2013
Offline Last Active Nov 26 2014 11:55 AM

Topics I've Started

Corrupting of the view if far from world center

13 November 2014 - 02:54 PM

Hello to all. 

I have a strange issue related (I think so) with view matrix of my camera class.

 

When camera is far from center of the world, it begins corrupting the view. 

Far - its starting from ~ 1.2*10^5-6.

 

I checked already my world matrix - it is correct, because if I put model back to the zero coordinates, it start looking correctly again.

Also view corrupting even if I don`t move model, but move camera.

Results on the screenshots attached to this post.

 

Here is my Camera class code. Maybe someone who wants help to solve this issue could find error, because I don`t see it (at least now).

enum CamType
    {
        Free = 0,
        FirstPerson = 1,
        ThirdPerson = 2,
        ThirdPersonAlt = 3
    }

    struct ViewMatrixDecomposeData
    {
        public Vector3 scale;
        public Quaternion rotation;
        public Vector3 translation;
    }

    class Camera
    {
        public Vector3 position;
        private Vector3 lookAt;
        private Vector3 center;
        private float radius;
        private Vector3 baseUp;
        private float fovX;
        private float fovY;
        private float aspectRatio;
        private float zNear;
        private float zFar;
        private Vector3 xAxis;
        private Vector3 yAxis;
        private Vector3 zAxis;
        private Quaternion qRotation;
        private CamType cameraType;
        private ViewMatrixDecomposeData viewMatrixDecomposeData;

        private Matrix viewMatrix;
        private Matrix projectionMatrix;

        public float ZNear
        {
            get { return zNear; }
            set { zNear = value; }
        }

        public float ZFar
        {
            get { return zFar; }
            set { zFar = value; }
        }

        public Matrix WorldMatrix { get; set; }

        public Matrix ViewMatrix
        {
            get { return viewMatrix; }
            set { viewMatrix = value; }
        }

        public Matrix ProjectionMatrix
        {
            get { return projectionMatrix; }
            set { projectionMatrix = value; }
        }

        public CamType CameraType
        {
            get
            {
                return cameraType;
            }

            set
            {
                if (cameraType != value)
                {
                    if (((cameraType == CamType.ThirdPerson) || (cameraType == CamType.ThirdPersonAlt)) && (value == CamType.Free))
                    {
                        // this is for the case of swithching from 3rd person to Free camera
                        GetViewMatrixRotation();

                        qRotation = viewMatrixDecomposeData.rotation;
                    }

                    cameraType = value;
                }
            }
        }

        public Camera(Vector3 _position, Vector3 _lookAt, Vector3 _up)
        {
            // free camera construstor
            SetFreeCamera(_position, _lookAt, _up);
        }

        public Camera(Vector3 _position, Quaternion _objectRotation, float _face_distance)
        {
            // 1st person camera construstor
            SetFirstPersonCamera(_position, _objectRotation, _face_distance);
        }

        public Camera(Vector3 _center, Quaternion _objectRotation, Vector3 _initialRelRotation, float _radius, Vector3 _lookAt, bool isAlternative)
        {
            // 3rd person camera constructor
            SetThirdPersonCamera(_center, _objectRotation, _initialRelRotation, _radius, _lookAt, isAlternative);
        }

        public void BuildPerspectiveForFovX(float _fovX, float _aspect, float _zNear, float _zFar)
        {
            fovX = _fovX;
            aspectRatio = _aspect;
            zNear = _zNear;
            zFar = _zFar;

            float e = 1.0f/(float) Math.Tan(MathUtil.DegreesToRadians(fovX/2.0f));
            float aspectInv = 1.0f/aspectRatio;
            fovY = 2.0f*(float) Math.Atan(aspectInv/e);
            float xScale = 1.0f/(float) Math.Tan(0.5f*fovY);
            float yScale = xScale/aspectInv;

            Matrix temp = ProjectionMatrix;

            temp.M11 = xScale;
            temp.M21 = 0.0f;
            temp.M31 = 0.0f;
            temp.M41 = 0.0f;

            temp.M12 = 0.0f;
            temp.M22 = yScale;
            temp.M32 = 0.0f;
            temp.M42 = 0.0f;

            temp.M13 = 0.0f;
            temp.M23 = 0.0f;
            temp.M33 = zFar/(zFar - zNear);
            temp.M43 = -zNear*zFar/(zFar - zNear);

            temp.M14 = 0.0f;
            temp.M24 = 0.0f;
            temp.M34 = 1.0f;
            temp.M44 = 0.0f;

            ProjectionMatrix = temp;
            //ProjectionMatrix = Matrix.PerspectiveFovLH(_fovX, _aspect, zNear, zFar);
        }

        public Matrix BuildPerspectiveForFovX2 (float _fovX, float _aspect, float _zNear, float _zFar)
        {
            fovX = _fovX;
            aspectRatio = _aspect;
            zNear = _zNear;
            zFar = _zFar;

            float e = 1.0f / (float)Math.Tan(MathUtil.DegreesToRadians(fovX / 2.0f));
            float aspectInv = 1.0f / aspectRatio;
            fovY = 2.0f * (float)Math.Atan(aspectInv / e);
            float xScale = 1.0f / (float)Math.Tan(0.5f * fovY);
            float yScale = xScale / aspectInv;

            Matrix temp = new Matrix();

            temp.M11 = xScale;
            temp.M21 = 0.0f;
            temp.M31 = 0.0f;
            temp.M41 = 0.0f;

            temp.M12 = 0.0f;
            temp.M22 = yScale;
            temp.M32 = 0.0f;
            temp.M42 = 0.0f;

            temp.M13 = 0.0f;
            temp.M23 = 0.0f;
            temp.M33 = zFar / (zFar - zNear);
            temp.M43 = -zNear * zFar / (zFar - zNear);

            temp.M14 = 0.0f;
            temp.M24 = 0.0f;
            temp.M34 = 1.0f;
            temp.M44 = 0.0f;

            return temp;
        }

        public void BuildPerspectiveForFovY(float _fovY, float _aspect, float _zNear, float _zFar)
        {
            ZNear = _zNear;
            ZFar = _zFar;
            ProjectionMatrix = Matrix.PerspectiveFovLH(_fovY, _aspect, zNear, zFar);
        }

        private void GetViewMatrixRotation()
        {
            ViewMatrix.Decompose(out viewMatrixDecomposeData.scale, out viewMatrixDecomposeData.rotation, out viewMatrixDecomposeData.translation);
            viewMatrixDecomposeData.rotation = Quaternion.Normalize(viewMatrixDecomposeData.rotation);
        }

        private void SetAxisFromViewMatrix()
        {
            xAxis = new Vector3(ViewMatrix.M11, ViewMatrix.M21, ViewMatrix.M31);
            yAxis = new Vector3(ViewMatrix.M12, ViewMatrix.M22, ViewMatrix.M32);
            zAxis = new Vector3(ViewMatrix.M13, ViewMatrix.M23, ViewMatrix.M33);
        }

        private void UpdateViewMatrix()
        {
            qRotation = Quaternion.Normalize(qRotation);

            if ((CameraType == CamType.ThirdPerson) || (CameraType == CamType.ThirdPersonAlt))
            {
                ViewMatrix = Matrix.Translation(Vector3.Negate(center))*Matrix.RotationQuaternion(qRotation);

                position = center - new Vector3(ViewMatrix.M13, ViewMatrix.M23, ViewMatrix.M33)*radius;

                ViewMatrix = Matrix.LookAtLH(position, lookAt,
                    new Vector3(ViewMatrix.M12, ViewMatrix.M22, ViewMatrix.M32));
            }
            else
            {
                ViewMatrix = Matrix.Translation(Vector3.Negate(position))*Matrix.RotationQuaternion(qRotation);

                if (CameraType == CamType.FirstPerson)
                {
                    ViewMatrix *= Matrix.Translation(new Vector3(0, 0, -radius));
                }
            }
        }

        public void RotateX(float _degree_angle)
        {
            if ((cameraType == CamType.ThirdPerson) || (cameraType == CamType.ThirdPersonAlt))
            {
                _degree_angle = -_degree_angle;
            }

            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitX, MathUtil.DegreesToRadians(_degree_angle)), qRotation);
            UpdateViewMatrix();
        }

        public void RotateY(float _degree_angle)
        {
            if ((cameraType == CamType.ThirdPerson) || (cameraType == CamType.ThirdPersonAlt))
            {
                _degree_angle = -_degree_angle;
            }

            if (cameraType == CamType.ThirdPersonAlt)
            {
                qRotation = Quaternion.Multiply(qRotation, Quaternion.RotationAxis(baseUp, MathUtil.DegreesToRadians(_degree_angle)));
            }
            else
            {
                qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitY, MathUtil.DegreesToRadians(_degree_angle)), qRotation);
            }
            UpdateViewMatrix();
        }

        public void RotateZ(float _degree_angle)
        {
            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitZ, MathUtil.DegreesToRadians(_degree_angle)), qRotation);
            UpdateViewMatrix();
        }

        public void MoveRelX(float _rel_x)
        {
            if (cameraType == CamType.Free)
            {
                SetAxisFromViewMatrix();

                position += xAxis * _rel_x;

                UpdateViewMatrix();
            }
        }

        public void MoveRelY(float _rel_y)
        {
            if (cameraType == CamType.Free)
            {
                SetAxisFromViewMatrix();

                position += yAxis * _rel_y;

                UpdateViewMatrix();
            }
        }

        public void MoveRelZ(float _rel_z)
        {
            if ((cameraType == CamType.ThirdPerson) || (cameraType == CamType.ThirdPersonAlt))
            {
                radius -= _rel_z;

                UpdateViewMatrix();
            }
            else
            {
                SetAxisFromViewMatrix();

                position += zAxis * _rel_z;

                UpdateViewMatrix();
            }
        }

        public void SetFreePosition(Vector3 _position)
        {
            position = _position;

            UpdateViewMatrix();
        }

        public void SetFreeLookAt(Vector3 _lookAt)
        {
            lookAt = _lookAt;

            Vector3 up = new Vector3(ViewMatrix.M12, ViewMatrix.M22, ViewMatrix.M32);

            ViewMatrix = Matrix.LookAtLH(position, lookAt, up);

            GetViewMatrixRotation();

            qRotation = viewMatrixDecomposeData.rotation;

            UpdateViewMatrix();
        }

        public void SetFreeCamera(Vector3 _position, Vector3 _lookAt, Vector3 _up)
        {
            cameraType = CamType.Free;    
            
            position = _position;
            lookAt = _lookAt;
            
            ViewMatrix = Matrix.LookAtLH(position, lookAt, _up);
            
            GetViewMatrixRotation();

            qRotation = viewMatrixDecomposeData.rotation;

            UpdateViewMatrix();
        }

        // SetRadius is both for 1st and 3rd person camera
        public void SetRadius(float _radius)
        {
            radius = _radius;

            UpdateViewMatrix();
        }

        public void SetFirstPersonPositionRotation(Vector3 _position, Quaternion _objectRotation)
        {
            position = _position;
            qRotation = _objectRotation;

            UpdateViewMatrix();
        }

        public void SetFirstPersonCamera(Vector3 _position , Quaternion _objectRotation, float _face_distance)
        {
            cameraType = CamType.FirstPerson;

            position = _position;
            radius = _face_distance;
            qRotation = _objectRotation;

            UpdateViewMatrix();
        }
        
        public void SetThirdPersonCenterLookAt(Vector3 _center, Vector3 _lookAt)
        {
            center = _center;
            lookAt = _lookAt;

            UpdateViewMatrix();
        }

        public void SetThirdPersonCamera(Vector3 _center, Quaternion _objectRotation, Vector3 _initialRelRotation, float _radius, Vector3 _lookAt, bool isAlternative)
        {
            if (isAlternative == true)
            {
                cameraType = CamType.ThirdPersonAlt;
            }
            else
            {
                cameraType = CamType.ThirdPerson;    
            }
            
            center = _center;
            radius = _radius;
            lookAt = _lookAt;

            qRotation = _objectRotation;

            baseUp = Matrix.RotationQuaternion(_objectRotation).Up;

            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitX, MathUtil.DegreesToRadians(_initialRelRotation.X)), qRotation);
            qRotation = Quaternion.Multiply(qRotation, Quaternion.RotationAxis(baseUp, MathUtil.DegreesToRadians(_initialRelRotation.Y)));
            qRotation = Quaternion.Multiply(Quaternion.RotationAxis(Vector3.UnitZ, MathUtil.DegreesToRadians(_initialRelRotation.Z)), qRotation);

            UpdateViewMatrix();
        }
    }

"Bind" Entities to Entity

16 October 2014 - 10:41 AM

Hi, I start writing my own engine not so long ago and now trying to write Entity framework.

 

If I understood it correctly, It contains several lists with IUpdatable and IDrawable components.

 

This is good if I have only 1 mesh in my entity, but I want to timplement a little bit different behaviour.

 

But what if I have, for ex., a space ship consists from a 1000 meshes?

How to manage such situation? Need I create something like a mesh class with meshes list inside?

 

I can iterate through the collection of meshes, Ok, but what if I want to attach another meshes to this ship? For ex, a crew? And I want that these meshes automatically update their positions when ship update its position?

How to "bind" them to the ship?

 

And another question is this correct approach to create mesh component with meshes and submeshes collections (submeshes for that cases if one mesh splitted by different materials)???

 

P.S. I am writing on C# in XNA-like framework and now study Elephant framework as an example to write my own Entity framework.

 

 


Planar Texture coordinates calculation algorithm

01 October 2014 - 01:36 AM

Hello.

I am trying to write correct algorithm for calculating planar texture coordinates, but It doesnt calculate coordinates correctly.

 

If I understand it well, I need to find normal for each triangle to find orientation of the face. Then, transform it so that if will lay along Z axis and then calculate coordinates without Y axis because Z will be like Y in transformed face.

 

So, I made the following:

public void CalculatePlanarTextureCoordinates(GeometryData geometryData)
        {
            List<Vector2> texCoordinates = new List<Vector2>();
            OrientedBoundingBox boundingBox;
            List<PositionData> positions = TransformPoints(geometryData, out boundingBox);
            foreach (var positionData in positions)
            {
                texCoordinates.Add(new Vector2(
                    GetPlanarCoordinates(boundingBox.Extents.X, positionData.Position.X,
                        geometryData.OrientedBoundingBox.Size.X),
                    GetPlanarCoordinates(boundingBox.Extents.Z, positionData.Position.Z,
                        geometryData.OrientedBoundingBox.Size.Z)));
            }

           geometryData.TextureCoordinates = texCoordinates;
        }

private float GetPlanarCoordinates(float start, float end, float width)
        {
            return (end - start)/width;
        }

private List<PositionData> TransformPoints(GeometryData geometryData, out OrientedBoundingBox boundingBox)
        {
            PositionData[] transformedPositionData = new PositionData[geometryData.Positions.Count];
            Matrix transformationMatrix = Matrix.Identity;
            for (int i = 0; i < geometryData.IndexBuffer.Count; i += 3)
            {
                Vector3 v0 = geometryData.Positions[geometryData.IndexBuffer[i + 1]].Position -
                             geometryData.Positions[geometryData.IndexBuffer[i]].Position;
                Vector3 v1 = geometryData.Positions[geometryData.IndexBuffer[i + 2]].Position -
                             geometryData.Positions[geometryData.IndexBuffer[i]].Position;

                Vector3 direction = Vector3.Cross(v0, v1);
                direction = Vector3.Normalize(direction);
                Vector3 vertex1 = geometryData.Positions[geometryData.IndexBuffer[i]].Position;
                Vector3 vertex2 = geometryData.Positions[geometryData.IndexBuffer[i + 1]].Position;
                Vector3 vertex3 = geometryData.Positions[geometryData.IndexBuffer[i + 2]].Position;

                if (direction == Vector3.UnitY)
                {
                    transformedPositionData[geometryData.IndexBuffer[i]].Position = vertex1;
                    transformedPositionData[geometryData.IndexBuffer[i + 1]].Position = vertex2;
                    transformedPositionData[geometryData.IndexBuffer[i + 2]].Position = vertex3;
                }

                Vector3 rotationAxis = Vector3.Cross(direction, Vector3.UnitY);
                float rotationAngle = Vector3.Dot(direction, Vector3.UnitY);
                Quaternion qRot;

                if (rotationAxis.X != 0.0f || rotationAxis.Y != 0.0f || rotationAxis.Z != 0.0f)
                {
                    qRot = new Quaternion(rotationAxis, rotationAngle);
                }
                else
                {
                    qRot = new Quaternion(Vector3.UnitX, rotationAngle);
                }


                transformationMatrix = Matrix.Translation(-geometryData.OrientedBoundingBox.Center) *
                                       Matrix.RotationQuaternion(qRot);

                    transformedPositionData[geometryData.IndexBuffer[i]].Position = Vector3.Transform(vertex1,
                        Quaternion.RotationMatrix(transformationMatrix));
                    transformedPositionData[geometryData.IndexBuffer[i + 1]].Position = Vector3.Transform(vertex2,
                        Quaternion.RotationMatrix(transformationMatrix));
                    transformedPositionData[geometryData.IndexBuffer[i + 2]].Position = Vector3.Transform(vertex3,
                        Quaternion.RotationMatrix(transformationMatrix));
            }
            BoundingBox basicBoundingBox =
                BoundingBox.FromPoints(transformedPositionData.Select(x => x.Position).ToArray());
            boundingBox = new OrientedBoundingBox(basicBoundingBox);
            boundingBox.Transform(transformationMatrix);
            return transformedPositionData.ToList();
        }

But in result I receive completely wrong coordinates with wrong side and even more that range [0..1].

 

Could someone tell me what is wrong here? Maybe I translate vertices incorrectly or something else?

I would appreciate for any help.


Calculating smooth normales

28 September 2014 - 01:32 PM

Hello. I want to calculate smooth normals for any mesh and for this I do the following calculations:

Vector3[] normals = new Vector3[geometryData.Positions.Count];

            for (int i = 0; i < geometryData.IndexBuffer.Count; i+=3)
            {
                Vector3 v0 = geometryData.Positions[geometryData.IndexBuffer[i + 1]].Position - geometryData.Positions[geometryData.IndexBuffer[i]].Position;
                Vector3 v1 = geometryData.Positions[geometryData.IndexBuffer[i]].Position - geometryData.Positions[geometryData.IndexBuffer[i + 2]].Position;
                
                Vector3 normal = Vector3.Normalize(Vector3.Cross(v0, v1));
                
                normals[geometryData.IndexBuffer[i]] += normal;
                normals[geometryData.IndexBuffer[i + 1]] += normal;
                normals[geometryData.IndexBuffer[i + 2]] += normal;
                
            }

            for (int i = 0; i < normals.Length; i++)
            {
                normals[i].Normalize();
            }

Then I compare calculated normals to pre-calculated by 3ds max and found that some of my normals has opposite sign on some axis, also sometimes values are not the same.

 

Does someone could say me what the prblem here? I think I should set correct sign somehow, but I dont know whow exactly.


Auto-level feature for quaternion based camera

22 September 2014 - 12:30 PM

I have 6DOF camera based on quaternions and I have accumulated roll. I wanted to get rid of it, but cant find the solution.

I know this was discussed much times, but I didnt find any working code for doing this.

For now i have the following code to get rid from unwanted roll rotation:

qRotation *= Quaternion.RotationAxis(Vector3.ForwardLH,
                Vector3.Dot(Vector3.Transform(Vector3.Right, qRotation), Vector3.Up) * 0.04f);
            qRotation = Quaternion.Normalize(qRotation);

But this code leads to unexpected results. First, Camera rotate to 180 degrees on z axis and I cannot rotate it back. 

Second - during rotation along X axis, camera start rotating and I change its orientation.

 

Does someone know how to fix that and do correct auto-leveling?


PARTNERS