[XUI] 3D, rotations and pivots

Discussion in 'Chit Chat' started by Star-Dust, May 17, 2018.

  1. Star-Dust

    Star-Dust Expert Licensed User

    So far I've used the native Android commands to rotate the views according to the X, Y, and Z axes. The native commands let you change the X and Y coordinates of the Pivot point and get this.

    [​IMG]

    But to get a rotating cube it is not enough to be able to rotate on three axes but you have to be able to move the pivot according to the x, y and z axis.

    I thought that the only solution was having to recover a source that I used 15 years ago in turbo pascal and in Vb4 to make the rotations. But unfortunately I did not find it.
    There is the LibGDX library that allows you to do this without having to study too much, but it is my challenge with myself
    So I went to memory and I made great strides ...
    1.gif
    Obviously I developed with the XUI library
    In the meantime I'm creating a class to handle everything.
    As soon as I can rotate an image I will show it to you
     
    Last edited: May 17, 2018
  2. Star-Dust

    Star-Dust Expert Licensed User

    Update:
    2.gif

    The next step is to create a sphere with the help of C-Spline curves.
    The C-SPline algorithm I posted here, fixing 5 points, creates a circle with many contiguous lines.
    Thus it is possible to create a sphere with lines.

    But now it's time to sleep :p
     
  3. Filippo

    Filippo Expert Licensed User

  4. Star-Dust

    Star-Dust Expert Licensed User

    E non hai visto ancora la mia foto o_O :p
     
    JordiCP, Cableguy and Filippo like this.
  5. LucaMs

    LucaMs Expert Licensed User

    ... put images on the faces of the cube.
     
  6. LucaMs

    LucaMs Expert Licensed User

    or, better, to allow the user-developer to put a B4XView (so not necessarily an ImageView) on any face of the cube.

    I'm thinking to an AMAZING "cube of settings", where each face is used to set a category of properties :)

    Dim pnlColors As B4XView
    ...
    pnlColors.LoadLayout(...)
    PropCube.Face(0) = pnlColors
     
    JordiCP likes this.
  7. JordiCP

    JordiCP Well-Known Member Licensed User

    Some months ago I spent some time with something that was for a different purpose, but based on a similar concept.
    Plan to be into it again soon, I think it is a really interesting challenge :)
     
    Star-Dust and LucaMs like this.
  8. Star-Dust

    Star-Dust Expert Licensed User

    A few explanations:

    Each point in space has three coordinates (X, Y, Z) that are considered the distance (positive or negative) with respect to each axis.
    H1.png

    But the position can also be indicated by the length of the line (or radius) that passes from the center of the axes to the point and the inclination in degrees or radians of the angle that forms this line with respect to the axes.

    To understand each other better I describe the thing on a 2-dimensional plane
    The Point (50,50) can also be indicated as follows: Radius = 70.7 Angle = 45 °
    H2.png

    This allows to recalculate the position:
    X = Cos(Angle) * Radius - Cos(45°) * 70.7 = 50
    Y = Sin (Angle) * Radius - Sin (45°) * 70.7 = 50


    When you need to rotate a point, just change the angle value.
    X = Cos(Angle + Value) * Radius
    Y = Sin (Angle + Value) * Radius


    This method helps a lot, but redoing these calculations for each rotation would weigh heavily on the processor. Then calculate the angle and radius when inserting the coordinates of the point:
    Code:
    public Sub AddPoint(X As Int, Y As Int)
        
    Dim NewPoint As T_Point
        NewPoint.Initialize
        NewPoint.X=X
        NewPoint.y=Y
        NewPoint.Angle=
    ATan2D(Y,X)
        NewPoint.Radius=
    Sqrt(Power(Y,2)+Power(X,2))
    End Sub
    This is just a simplistic example, because on a three-dimensional plane it gets complicated
     
    Sagenut likes this.
  9. Star-Dust

    Star-Dust Expert Licensed User

    I completed the calculation and the perspectives:
    3.gif 5.gif

    This is the code that generates these rotations.
    Code:
    Sub Activity_Create(FirstTime As Boolean)
        
    Activity.LoadLayout("Layout1")
        
    Panel = xui.CreatePanel("")
        
    Activity.Addview(Panel,40dip,40dip,100%x-40dip,100%y-80dip)
        
        Lines.Initialize
        
    ' CUBE
        Lines.AddRec(-50,-50,50,50,50,50,MyColor2)'
        Lines.AddRec(-50,-50,-50,50,50,-50,MyColor2)
       
        Lines.AddLine(-
    50,-50,50,-50,-50,-50,MyColor3)
        Lines.AddLine(
    50,-50,50,50,-50,-50,MyColor3)
        Lines.AddLine(
    50,50,50,50,50,-50,MyColor3)
        Lines.AddLine(-
    50,50,50,-50,50,-50,MyColor3)

       
    ' SPHERA
        Lines.AddCircleZ(0,0,0,80,MyColor)
        Lines.AddCircley(
    0,0,0,80,MyColor2)
        Lines.AddCirclex(
    0,0,0,80,MyColor3)

        
    ' DRaw
        Lines.RenderImage(Panel,2dip)
    End Sub

    Sub SeekBar_ValueChanged (Value As Int, UserChanged As Boolean)
        
    ' Rotate
        Lines.RotateY(SeekBarY.Value).RotateZ(SeekBarZ.Value).RotateX(SeekBarX.Value).RenderImage(Panel,2dip)
        LabelC.Text=
    $"X:${SeekBarX.Value} Y:${SeekBarY.Value} Z:${SeekBarZ.Value}"$
    End Sub
    Next step rotate full geometric figures
     
    Last edited: May 19, 2018 at 6:02 AM
    Beja, Sagenut and Johan Hormaza like this.
  10. Star-Dust

    Star-Dust Expert Licensed User

    Thank you, surely I would appreciate your comments to improve this work, I saw some of your works you posted and are truly exceptional.
    Unfortunately, now, as soon as I finish an algorithm and it works, I think it's better.
    I rewrote the algorithm 3 times by totally changing it and improving it.
    But now I have thought of a new algorithm that makes it easy for me to render full images and polygons of every shape.
    But rewriting everything at once will require much more time and I never get to render the images, but I already have in mind how to do it in XUI (if I do not forget it in the meantime)
     
    JordiCP, Beja and Sagenut like this.
  11. Star-Dust

    Star-Dust Expert Licensed User

    Update
    6.gif 7.gif

    Cube
    Code:
    Lines.Initialize
        Lines.AddPolygon(
    1,-50,-50,50,C).AddPolygon(1,50,-50,50,C).AddPolygon(1,50,50,50,C).AddPolygon(1,-50,50,50,C)
        Lines.AddPolygon(
    2,-50,-50,50,C).AddPolygon(2,-50,50,50,C).AddPolygon(2,-50,50,-50,C).AddPolygon(2,-50,-50,-50,C)
        Lines.AddPolygon(
    3,-50,-50,-50,C).AddPolygon(3,50,-50,-50,C).AddPolygon(3,50,50,-50,C).AddPolygon(3,-50,50,-50,C)
        Lines.AddPolygon(
    4,50,-50,50,C).AddPolygon(4,50,50,50,C).AddPolygon(4,50,50,-50,C).AddPolygon(4,50,-50,-50,C)
        Lines.RenderToView(
    Panel,2dip)
    Pentagon
    Code:
    Lines.AddPolygon(1,-60,-30,50,xui.Color_White).AddPolygon(1,0,-60,50,xui.Color_White).AddPolygon(1,60,-30,50,xui.Color_White).AddPolygon(1,40,50,50,xui.Color_White).AddPolygon(1,-40,50,50,xui.Color_White)
    Now last step, rendering Image
     
    Last edited: May 21, 2018 at 6:47 AM
  12. Star-Dust

    Star-Dust Expert Licensed User

    Without using native methods, but all created in B4X and XUI
    It is still in a rudimentary phase, it must be speeded up and improved ... but it is already something

    8.gif

    PS. Maybe I will distribute the source code of this class, except for the image rendering, if someone is interested
     
    Beja, inakigarm and Erel like this.
  13. Star-Dust

    Star-Dust Expert Licensed User

    Wait B4A 8.30 which has been announced that it will be faster, so the movement will appear more natural.

    In addition, I am examining same algorithms for image deformation, what I now use does not satisfy
     
  14. Star-Dust

    Star-Dust Expert Licensed User

    For Java aficionados this is a way to adapt an image to a trapezoid frame, like the one used to give the idea of a perspective or rotational image

    Code:
    private Bitmap drawTrapezoid(Bitmap bmp, PointF topLeft, PointF topRight, PointF bottomLeft, PointF bottomRight)
            {
                //Get new width 
    and height
                float left = (float)Math.Min(Math.Min(topLeft.X, topRight.X), Math.Min(bottomLeft.X, bottomRight.X));
                float right = (float)Math.Max(Math.Max(topLeft.X, topRight.X), Math.Max(bottomLeft.X, bottomRight.X));
                float top = (float)Math.Min(Math.Min(topLeft.Y, topRight.Y), Math.Min(bottomLeft.Y, bottomRight.Y));
                float bottom = (float)Math.Max(Math.Max(topLeft.Y, topRight.Y), Math.Max(bottomLeft.Y, bottomRight.Y));

                //Translate points 
    to (00)
                PointF origin = new PointF(left, top);
                topLeft.X -= origin.X;
                topLeft.Y -= origin.Y;
                topRight.X -= origin.X;
                topRight.Y -= origin.Y;
                bottomLeft.X -= origin.X;
                bottomLeft.Y -= origin.Y;
                bottomRight.X -= origin.X;
                bottomRight.Y -= origin.Y;

                //Use Graphics class 
    to resize the image
                int newWidth = (int)Math.Round(right - left);
                int newHeight = (int)Math.Round(bottom - top);
                
    Bitmap inputBmp = new Bitmap(newWidth, newHeight);
                Graphics gg = Graphics.FromImage(inputBmp);
                gg.DrawImage(bmp, new Rectangle(
    00, newWidth, newHeight), new Rectangle(00, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
                gg.Dispose();


                
    Bitmap trap = new Bitmap(inputBmp.Width, inputBmp.Height);

                PointF xyA = new PointF(
    0.0f, 0.0f);
                PointF xyB = new PointF(inputBmp.Width, inputBmp.Height);

                double xFraction, yFraction;
                float xStart, xWidth;
                float yStart, yWidth;


                //Depending on the points, we have 
    to either top to bottom or right to left
                
    if (topLeft.Y == topRight.Y)
                {
                    
    for (float y = topLeft.Y; y < bottomLeft.Y; y++)
                    {
                        yFraction = (y - topLeft.Y) / (bottomLeft.Y - topLeft.Y);
                        xStart = (int)Math.Round((decimal)(topLeft.X + (y - topLeft.Y) * (bottomLeft.X - topLeft.X) / (bottomLeft.Y - topLeft.Y)));
                        xWidth = (int)Math.Round((decimal)((topRight.X - topLeft.X) + (y - topLeft.Y) * ((bottomRight.X - bottomLeft.X) - (topRight.X - topLeft.X)) / (bottomLeft.Y - topLeft.Y)));
                        
    For (float x = xStart; x < xStart + xWidth; x++)
                        {
                            xFraction = (x - xStart) / (xWidth);
                            float sm = (float)Math.Round(xFraction * (xyB.X - xyA.X));
                            trap.SetPixel((int)x, (int)y, inputBmp.GetPixel((int)sm, (int)y));
                        
    }
                    }
                }
                Else
                {
                    For (float x = topLeft.X; x < topRight.X; x++)
                    {
                        xFraction = (x - topLeft.X) / (topRight.X - topLeft.X);

                        yStart = (int)Math.Round((decimal)(topLeft.Y + (x - topLeft.X) * (topRight.Y - topLeft.Y) / (topRight.X - topLeft.X)));
                        yWidth = (int)Math.Round((decimal)((bottomLeft.Y - topLeft.Y) + (x - topLeft.X) * ((bottomRight.Y - topRight.Y) - (bottomLeft.Y - topLeft.Y)) / (topRight.X - topLeft.X)));
                        For (float y = yStart; y < yStart + yWidth; y++)
                        {
                            yFraction = (y - yStart) / (yWidth);
                            float sm = (float)Math.Round(yFraction * (xyB.Y - xyA.Y));
                            trap.SetPixel((int)x, (int)y, inputBmp.GetPixel((int)x, (int)sm));
                        }
                    }
                }         

                inputBmp.Dispose();

                Return trap;
            }
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice