0

How can I add an arcball effects to drawn quads?

In this example, a Cube was created and the arcball effect was added which is working fine.

//  Create a sphere.
Cube cube = new Cube();
cube.AddEffect(arcBallEffect);

//  Add it.
sceneControl1.Scene.SceneContainer.AddChild(cube);

This is the complete code, what I want is to add an arcball effect to the quads drawn inside drawCube function.

public partial class SharpGLForm : Form
{
    private double max_dimension = 100;

    /// <summary>
    /// The current rotation.
    /// </summary>
    private float rotation = 0.0f;
    private ArcBallEffect arcBallEffect = new ArcBallEffect();
    /// <summary>
    /// Initializes a new instance of the <see cref="SharpGLForm"/> class.
    /// </summary>
    public SharpGLForm()
    {
        InitializeComponent();
        sceneControl1.MouseDown += new MouseEventHandler(FormSceneSample_MouseDown);
        sceneControl1.MouseMove += new MouseEventHandler(FormSceneSample_MouseMove);
        sceneControl1.MouseUp += new MouseEventHandler(openGLControl_MouseUp);

        //  Add some design-time primitives.
        sceneControl1.Scene.SceneContainer.AddChild(new
            SharpGL.SceneGraph.Primitives.Grid());
        sceneControl1.Scene.SceneContainer.AddChild(new
            SharpGL.SceneGraph.Primitives.Axies());

        //  Create a light.
        Light light = new Light()
        {
            On = true,
            Position = new Vertex(3, 10, 3),
            GLCode = OpenGL.GL_LIGHT0
        };

        //  Add the light.
        //sceneControl1.Scene.SceneContainer.AddChild(light);

        //  Create a sphere.
        Cube cube = new Cube();
        cube.AddEffect(arcBallEffect);

        //  Add it.
        sceneControl1.Scene.SceneContainer.AddChild(cube);

    }

    void FormSceneSample_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            arcBallEffect.ArcBall.MouseMove(e.X, e.Y);
        }
    }

    void FormSceneSample_MouseDown(object sender, MouseEventArgs e)
    {
        arcBallEffect.ArcBall.SetBounds(sceneControl1.Width, sceneControl1.Height);
        arcBallEffect.ArcBall.MouseDown(e.X, e.Y);
    }

    /// <summary>
    /// Handles the OpenGLDraw event of the openGLControl control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="RenderEventArgs"/> instance containing the event data.</param>
    private void openGLControl_OpenGLDraw(object sender, RenderEventArgs e)
    {
        //  Get the OpenGL object.
        OpenGL gl = sceneControl1.OpenGL;

        //  Clear the color and depth buffer.
        gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

        //  Load the identity matrix.
        gl.LoadIdentity();

        //  Rotate around the Y axis.
        //gl.Rotate(rotation, 0.5f, 0.5f, 0.5f);
        gl.Scale(5f, 5f, 5f); 
        gl.Disable(OpenGL.GL_BLEND);

        //30 100 100
        //0 0 0 50 90 20
        //50 0 0 30 30 10
        //80 0 0 20 20 10
        //50 0 10 10 10 10

        drawCube(100, 100, 30, 0, 0, 0, true); // Draw big box
        drawCube(50, 90, 20, 0, 0, 0, false);
        drawCube(30, 30, 10, 50, 0, 0, true);
        drawCube(20, 20, 10, 80, 0, 0, false);
        drawCube(10, 10, 10, 50, 0, 10, true);

        //drawCube(100, 100,30, 0, 0, 0, true); // Draw big box
        //drawCube(20, 40, 20, 0, 0, 0, false);
        //drawCube(30, 30, 10, 20, 0, 0, true);
        //drawCube(20, 20, 10, 50, 0, 0, false);
        //drawCube(10, 10, 10, 70, 0, 0, true);

        //  Nudge the rotation.
        //rotation += 3.0f;
    }

    private void drawCube(double length, double height, double width, double posX, double posY, double posZ, bool isWireframe)
    {
        OpenGL gl = openGLControl.OpenGL;
        Random r = new Random();
        int range = 255;
        double scaledLength = length / max_dimension;
        double scaledWidth = width / max_dimension;
        double scaledHeight = height / max_dimension;
        double scaledPosX = posZ / max_dimension;
        double scaledPosY = posY / max_dimension;
        double scaledPosZ = posX / max_dimension;

        if (isWireframe)
        {
            gl.Color(1.0f, 0.0f, 0.0f);
            gl.PolygonMode(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_LINE);
        }
        else
        {
            gl.PolygonMode(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_FILL);
            gl.Color(r.NextDouble() * range, r.NextDouble() * range, r.NextDouble() * range);
        }
        gl.Begin(OpenGL.GL_QUADS);

        // Front face
        gl.Vertex(0.0f + scaledPosX, 0.0f + scaledPosY, 0.0f + scaledPosZ);
        gl.Vertex(0.0f + scaledPosX, scaledHeight + scaledPosY, 0.0f + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, 0.0f + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, 0.0f + scaledPosY, 0.0f + scaledPosZ);

        gl.Vertex(0f + scaledPosX, 0.0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, 0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(0f + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);

        //top face
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(0f + scaledPosX, scaledHeight + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(0f + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);

        //bottom face
        gl.Vertex(scaledWidth + scaledPosX, 0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(0f + scaledPosX, 0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(0f + scaledPosX, 0f + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, 0f + scaledPosY, 0f + scaledPosZ);

        //left face
        gl.Vertex(scaledWidth + scaledPosX, 0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, 0f + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(scaledWidth + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);

        //right face
        gl.Vertex(0f + scaledPosX, 0f + scaledPosY, 0f + scaledPosZ);
        gl.Vertex(0f + scaledPosX, 0f + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(0f + scaledPosX, scaledHeight + scaledPosY, scaledLength + scaledPosZ);
        gl.Vertex(0f + scaledPosX, scaledHeight + scaledPosY, 0f + scaledPosZ);

        gl.End();
    }

    /// <summary>
    /// Handles the OpenGLInitialized event of the openGLControl control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void openGLControl_OpenGLInitialized(object sender, EventArgs e)
    {
        //  TODO: Initialise OpenGL here.

        //  Get the OpenGL object.
        OpenGL gl = openGLControl.OpenGL;

        //  Set the clear color.
        gl.ClearColor(0, 0, 0, 0);
    }

    /// <summary>
    /// Handles the Resized event of the openGLControl control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
    private void openGLControl_Resized(object sender, EventArgs e)
    {
        //  TODO: Set the projection matrix here.

        //  Get the OpenGL object.
        OpenGL gl = openGLControl.OpenGL;

        //  Set the projection matrix.
        gl.MatrixMode(OpenGL.GL_PROJECTION);

        //  Load the identity.
        gl.LoadIdentity();

        //  Create a perspective transformation.
        gl.Perspective(20.0f, (double)Width / (double)Height, 0.01, 100.0);

        //  Use the 'look at' helper function to position and aim the camera.
        gl.LookAt(-35, 0, 0, 0, 0, 0, 0, 1, 0);

        //  Set the modelview matrix.
        gl.MatrixMode(OpenGL.GL_MODELVIEW);
    }

    private void openGLControl_MouseUp(object sender, MouseEventArgs e)
    {
        arcBallEffect.ArcBall.MouseUp(e.X, e.Y);
    }
}

}

This is the output of this program, the right one can be rotated and I want to apply same effect to the left side enter image description here

Anonymous Duck
  • 2,942
  • 1
  • 12
  • 35

1 Answers1

0

To make this work, i add listener for mousemove and change x-rotation and y-rotation respectively

        void FormSceneSample_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                double deltaDirection_X = currentPositionX - e.X;
                double deltaDirection_Y = currentPositionY - e.Y;
                var direction_X = deltaDirection_X > 0 ? 1 : -1;
                var direction_Y = deltaDirection_Y > 0 ? 1 : -1;

                if (direction_X == 1)
                    xRotation -= 1.0f;
                else
                    xRotation += 1.0f;

                if (direction_Y == 1)
                    yRotation -= 1.0f;
                else
                    yRotation += 1.0f;

                currentPositionX = e.X;
                currentPositionY = e.Y;
            }
        }

After I calculated the movement if it's right or left, top or bottom the new calculated value is now feed to the rotate API

gl.Rotate(xRotation, 0f, xRotation, yRotation);

The output is not the smooth though, I'm currently trying an arcball effect

Anonymous Duck
  • 2,942
  • 1
  • 12
  • 35