public static float CamDistance(Vector3 v, GLCamera cam, float radius = _orbRadius)
 {
     if (!cam.Orthographic)
     {
         return(v.TrueDistance(cam.GetPoint()) / radius * (cam.VerticalFieldOfView / 45.0f) * 0.1f);
     }
     else
     {
         return(cam._scale._x * 80.0f);
     }
 }
Example #2
0
        public void ApplyBillboard(GLCamera camera)
        {
            if (BillboardSetting == BillboardFlags.Off)
            {
                return;
            }

            Vector3 camPoint = camera.GetPoint();
            Vector3 camRot   = camera._rotation;

            FrameState worldState = _frameMatrix.Derive();

            Matrix m = Matrix.Identity, mInv = Matrix.Identity;

            Vector3 rot = ((int)BillboardSetting & 1) == 0 ?                              //If perspective
                          worldState.Translate.LookatAngles(camPoint) * Maths._rad2degf : //Point at camera position
                          camRot;                                                         //Set parallel to the camera

            switch (BillboardSetting)
            {
            case BillboardFlags.Standard:
            case BillboardFlags.StandardPerspective:

                //Is affected by parent rotation
                m    = Matrix.RotationMatrix(worldState.Rotate);
                mInv = Matrix.ReverseRotationMatrix(worldState.Rotate);

                //No restrictions to apply
                break;

            case BillboardFlags.Rotation:
            case BillboardFlags.RotationPerspective:

                //Is not affected by parent rotation
                m    = Matrix.RotationMatrix(_frameState.Rotate);
                mInv = Matrix.ReverseRotationMatrix(_frameState.Rotate);

                //TODO: apply restrictions?
                break;

            case BillboardFlags.Y:
            case BillboardFlags.YPerspective:

                //Is affected by parent rotation
                m    = Matrix.RotationMatrix(worldState.Rotate);
                mInv = Matrix.ReverseRotationMatrix(worldState.Rotate);

                //Only Y is allowed to rotate automatically
                rot._x = 0;
                rot._z = 0;

                break;

            default:     //Not a valid billboard type
                return;
            }

            worldState.Rotate = rot;

            _frameMatrix        = worldState._transform * m;
            _inverseFrameMatrix = worldState._iTransform * mInv;
        }
 public static Vector3 CamLoc(GLCamera cam)
 {
     return(cam == null ? new Vector3() : cam.GetPoint());
 }
        public void Render(GLCamera cam, bool renderBG)
        {
            cam.LoadProjection();

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.Color4(Color.White);
            GL.Enable(EnableCap.Texture2D);

            float
                halfW = (float)Width / 2.0f,
                halfH = (float)Height / 2.0f;

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            GL.MatrixMode(MatrixMode.Texture);
            GL.LoadIdentity();

            if (renderBG)
            {
                GL.PushAttrib(AttribMask.TextureBit);

                GLTexture bgTex = TKContext.FindOrCreate <GLTexture>("TexBG", GLTexturePanel.CreateBG);
                bgTex.Bind();

                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
                GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);

                float
                    s = (float)Width / (float)bgTex.Width,
                    t = (float)Height / (float)bgTex.Height;

                GL.Begin(BeginMode.Quads);

                GL.TexCoord2(0.0f, 0.0f);
                GL.Vertex2(-halfW, -halfH);
                GL.TexCoord2(s, 0.0f);
                GL.Vertex2(halfW, -halfH);
                GL.TexCoord2(s, t);
                GL.Vertex2(halfW, halfH);
                GL.TexCoord2(0.0f, t);
                GL.Vertex2(-halfW, halfH);

                GL.End();

                GL.PopAttrib();
            }

            if (Tex0 == null)
            {
                return;
            }
            Tex0.Prepare(_targetMatRef, -1);
            GLTexture texture = GLTex;

            if (texture == null || texture._texId <= 0)
            {
                return;
            }

            MDL0TextureNode.ApplyGLTextureParameters(_targetMatRef);

            //These are used to match up the UV overlay to the texture underneath
            Vector2 topLeft     = new Vector2();
            Vector2 bottomRight = new Vector2();

            float texWidth  = texture.Width;
            float texHeight = texture.Height;

            float tAspect = (float)texWidth / texHeight;
            float wAspect = (float)Width / Height;

            float[] texCoord = new float[8];

            //These are used to compensate for padding added on an axis
            float xCorrect = 1.0f, yCorrect = 1.0f;

            if (tAspect > wAspect)
            {
                //Texture is wider, use horizontal fit
                //X touches the edges of the window, Y has top and bottom padding

                //X
                texCoord[0] = texCoord[6] = 0.0f;
                texCoord[2] = texCoord[4] = 1.0f;

                //Y
                texCoord[1] = texCoord[3] = (yCorrect = tAspect / wAspect) / 2.0f + 0.5f;
                texCoord[5] = texCoord[7] = 1.0f - texCoord[1];

                bottomRight = new Vector2(halfW, (((float)Height - ((float)Width / texWidth * texHeight)) / (float)Height / 2.0f - 0.5f) * (float)Height);
                topLeft     = new Vector2(-halfW, -bottomRight._y);
            }
            else
            {
                //Window is wider, use vertical fit
                //Y touches the edges of the window, X has left and right padding

                //Y
                texCoord[1] = texCoord[3] = 1.0f;
                texCoord[5] = texCoord[7] = 0.0f;

                //X
                texCoord[2] = texCoord[4] = (xCorrect = wAspect / tAspect) / 2.0f + 0.5f;
                texCoord[0] = texCoord[6] = 1.0f - texCoord[2];

                bottomRight = new Vector2(1.0f - (((float)Width - ((float)Height / texHeight * texWidth)) / Width / 2.0f - 0.5f) * (float)Width, -halfH);
                topLeft     = new Vector2(-bottomRight._x, halfH);
            }

            //Apply the texcoord bind transform first
            TextureFrameState state = _targetMatRef._bindState;

            GL.MultMatrix((float *)&state._transform);

            //Translate the texture coordinates to match where the user dragged the camera
            //Divide by width and height to convert window units (0 to w, 0 to h) to texcoord units (0 to 1)
            //Then multiply by the correction value if the window is bigger than the texture on an axis
            Vector3 point = cam.GetPoint();

            GL.Translate(point._x / Width * xCorrect, -point._y / Height * yCorrect, 0);

            //Now to scale the texture after translating.
            //The scale origin is the top left of the texture on the window (not of the window itself),
            //so we need to translate the center of the texture to that origin,
            //scale it up or down, then translate it back to where it was.
            OpenTK.Vector3 trans = new OpenTK.Vector3(-topLeft._x / Width * xCorrect, topLeft._y / Height * yCorrect, 0.0f);
            GL.Translate(trans);
            GL.Scale((OpenTK.Vector3)cam._scale);
            GL.Translate(-trans);

            //Bind the material ref's texture
            GL.BindTexture(TextureTarget.Texture2D, texture._texId);

            //Draw a quad across the screen and render the texture with the calculated texcoords
            GL.Begin(BeginMode.Quads);

            GL.TexCoord2(texCoord[0], texCoord[1]);
            GL.Vertex2(-halfW, -halfH);
            GL.TexCoord2(texCoord[2], texCoord[3]);
            GL.Vertex2(halfW, -halfH);
            GL.TexCoord2(texCoord[4], texCoord[5]);
            GL.Vertex2(halfW, halfH);
            GL.TexCoord2(texCoord[6], texCoord[7]);
            GL.Vertex2(-halfW, halfH);

            GL.End();
            GL.Disable(EnableCap.Texture2D);

            //Now load the camera transform and draw the UV overlay over the texture
            cam.LoadModelView();

            //Color the lines limegreen, a bright color that probably won't be in a texture
            GL.Color4(Color.LimeGreen);

            Vector2 mdlScale = new Vector2(bottomRight._x - topLeft._x, bottomRight._y - topLeft._y);

            GL.Translate(topLeft._x, topLeft._y, 0.0f);
            GL.Scale(mdlScale._x, mdlScale._y, 1.0f);

            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            GL.LineWidth(1);

            //Render texture coordinates as vertex points
            foreach (RenderInfo info in _renderInfo)
            {
                info.PrepareStream();
            }
        }