How to draw axis coordinate in screen-space?

Daniele NieroDaniele Niero Posts: 233 ✭✭

Hi,

What would be the best approach to draw the axis coordinates on the bottom corner of the viewport, like in Maya.

Can it be done with InlineDrawing/InlineDebugShape?

Thanks,
Daniele

Comments

  • AhmidouAhmidou Posts: 179 ✭✭

    Hi Daniel,
    I would make a new shader based on the OGLFlatVertexColorShader one that would take a different set of MVP matrices than the current view one:

    • an othrogaphic one for the projection (I guess you need to trial and error for the good frustum).
    • the same view matrix with the translation back to the origin.
    • an identity model matrix.

    then you just need to call glViewport(0,0,50,50) to render in the left corner and glDisable(GL_DEPTH_TEST) to draw on top ot everything.

  • Daniele NieroDaniele Niero Posts: 233 ✭✭
    edited July 4

    Hi Ahmidou,

    This is what I was afraid of... I'm totally lost when it comes down to shader (or anything render-related for what it matters).
    I was hoping there was an "higher level" way to do it.

    But thanks for your suggestion, I'll pass it to someone here that can actually understand it :)

  • AhmidouAhmidou Posts: 179 ✭✭

    I gave it a try, here's the shader:

    require InlineDrawing;
    function OGLOrthoProjectionToFixedScreenLocation() {
      // Avoid calling the init method if this default constructor is being invoked
      // during the construction of a derived object.
      this.distance = 2.5;
        this.viewX = 0.0;
        this.viewY = 0.0;
        this.viewW = 50.0;
        this.viewH = 50.0;
      if(this.type() == OGLOrthoProjectionToFixedScreenLocation)
        this.init(String(this.type()));
    }
    
    /// default constructor taking a name
    function OGLOrthoProjectionToFixedScreenLocation(String name) {
      this.init(name);
    }
    
    /// initialize the OGLOrthoProjectionToFixedScreenLocation using name
    /// \internal
    function OGLOrthoProjectionToFixedScreenLocation.init!(String name) {
      this.name = name;
      this.setVertexCode("
          #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2
    
          uniform mat4 u_viewMatrix_;
          uniform mat4 u_projection_;
          uniform mat4 u_modelMatrix_;
    
          attribute vec4 positions;
          attribute vec4 vertexColors;
    
          varying vec4 v_vertexColor;
    
          void main(){
            gl_Position =  (u_projection_ * (u_viewMatrix_ * (u_modelMatrix_ * positions)));
            v_vertexColor = vertexColors;
          }
        ");
      this.setFragmentCode("
          #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2
    
          varying vec4 v_vertexColor;
    
          void main(){
            gl_FragColor = v_vertexColor;
          }
        ");
      this.defineUniform(InlineUniform("u_viewMatrix_", Mat44()));
      this.defineUniform(InlineUniform("u_projection_", Mat44()));
      this.defineUniform(InlineUniform("u_modelMatrix_", Mat44()));
      this.defineAttribute('positions', "Vec4");
      this.defineAttribute('vertexColors', "Vec4");
    }
    
    function Boolean OGLOrthoProjectionToFixedScreenLocation.draw!(io DrawContext context) {
        InlineViewport viewport = context.viewport;
    
        Scalar frustumH = this.distance;
        Scalar frustumW = this.distance;
        Mat44 projection = symmetricOrthographicFrustum(frustumW, frustumH, viewport.camera.nearDistance, viewport.camera.farDistance);
        this.setUniform(InlineUniform('u_projection_', projection));
        Mat44 viewMat = viewport.getViewMat();
        viewMat.setTranslation(Vec3(0, 0, -1));
        this.setUniform(InlineUniform('u_viewMatrix_', viewMat));
        Mat44 vm = Mat44();
        this.setUniform(InlineUniform('u_modelMatrix_', vm));
        glViewport(this.viewX, this.viewY, this.viewW, this.viewH);
        glDisable(GL_DEPTH_TEST);
        return this.parent.draw(context);
    }
    

    and on the canvas side

    function DrawingHandle.drawCornerAxesInstances!(String name, Float32 orthoDistance, Float32 viewX, Float32 viewY, Float32 viewH, Float32 viewW, Xfo transforms[], out Vec3 dummyResult, out InlineInstance instance)
    {
      String uidName = this.uid() + '_' + name;
    
      InlineDrawing draw = this.getDrawing();
      InlineShader shader = draw.registerShader(OGLOrthoProjectionToFixedScreenLocation);
      InlineDebugShape shape = draw.getShape(uidName);
      if(shape == null)
      {
        shape = draw.registerShape(InlineDebugShape(uidName));
        shape.drawAxes(Xfo(), false);
      }
    
      this.drawShapeInstances(uidName, shader, transforms, shape, instance);
      Ref<OGLOrthoProjectionToFixedScreenLocation> orthoShader = shader;
      orthoShader.distance = orthoDistance;
      orthoShader.viewX = viewX;
      orthoShader.viewY = viewY;
      orthoShader.viewH = viewH;
      orthoShader.viewW = viewW;
    }
    
    /// helper function to draw a single axes
    /// \dfgPresetCreate
    function DrawingHandle.drawCornerAxes!(String name, Float32 orthoDistance, Float32 viewX, Float32 viewY, Float32 viewH, Float32 viewW, Xfo transform, out Vec3 dummyResult, out InlineInstance instance)
    {
      Xfo transforms[];
      transforms.push(transform);
      this.drawCornerAxesInstances(name, orthoDistance, viewX, viewY, viewH, viewW, transforms, dummyResult, instance);
    }
    

    The next step would be to use the Python API when launching canvas to set it up automatically and without adding physical node to the graph

  • AhmidouAhmidou Posts: 179 ✭✭

    Ho and BTW I found out that we couldn't overwrite the MVP matrices from the draw function, I believe we should, but it's not a big deal.

  • Daniele NieroDaniele Niero Posts: 233 ✭✭

    Hi @Ahmidou

    Thank you so much for your help, I can confirm that it works!
    I just changed few small things because the axes drawn looked a little bit weird... so messing around this the matrices multiplications in the shader I've found out that you just need this: u_viewMatrix_ * position

    Anyway this is what I got after re-touching your code:

    require InlineDrawing;
    
    object OGLOrthoProjectionToFixedScreenLocation: OGLInlineShader {
        Scalar viewX; 
        Scalar viewY; 
        Scalar viewW; 
        Scalar viewH; 
    };
    
    function OGLOrthoProjectionToFixedScreenLocation() { 
        // Avoid calling the init method if this default constructor is being invoked 
        // during the construction of a derived object. 
    
        this.viewX = 0.0; 
        this.viewY = 0.0; 
        this.viewW = 50.0; 
        this.viewH = 50.0; 
        if(this.type() == OGLOrthoProjectionToFixedScreenLocation) 
            this.init(String(this.type())); 
    } 
    
    /// default constructor taking a name 
    function OGLOrthoProjectionToFixedScreenLocation(String name) { 
        this.init(name); 
    } 
    
    /// initialize the OGLOrthoProjectionToFixedScreenLocation using name 
    /// \internal 
    function OGLOrthoProjectionToFixedScreenLocation.init!(String name) { 
        this.name = name; 
    
        this.setVertexCode("
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            uniform mat4 u_viewMatrix_; 
    
            attribute vec4 positions; 
            attribute vec4 vertexColors; 
    
            varying vec4 v_vertexColor; 
    
            void main(){ 
                gl_Position = u_viewMatrix_ * positions; 
                v_vertexColor = vertexColors; 
            } "
        ); 
    
        this.setFragmentCode(" 
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            varying vec4 v_vertexColor; 
            void main(){ 
                gl_FragColor = v_vertexColor; 
            } "
        ); 
    
        this.defineUniform(InlineUniform("u_viewMatrix_", Mat44())); 
        this.defineAttribute('positions', "Vec4"); 
        this.defineAttribute('vertexColors', "Vec4"); 
    } 
    
    function Boolean OGLOrthoProjectionToFixedScreenLocation.draw!(io DrawContext context) { 
        InlineViewport viewport = context.viewport; 
    
        Mat44 viewMat = viewport.getViewMat(); 
        viewMat.setTranslation(Vec3(0, 0, 0)); 
        this.setUniform(InlineUniform('u_viewMatrix_', viewMat)); 
    
        glViewport(this.viewX, this.viewY, this.viewW, this.viewH); 
        glDisable(GL_DEPTH_TEST); 
    
        return this.parent.draw(context); 
    }
    
    
    /// helper function to draw a axes at the viewport's bottom corner 
    function DrawingHandle.drawViewportCoordinates!(String name, Float32 viewX, Float32 viewY, Float32 viewH, Float32 viewW, out InlineInstance instance)
    {
        String uidName = this.uid() + '_' + name;
    
        Xfo transforms[];
        transforms.push(Xfo());
    
        InlineDrawing draw = this.getDrawing();
        InlineShader shader = draw.registerShader(OGLOrthoProjectionToFixedScreenLocation);
        InlineDebugShape shape = draw.getShape(uidName);
        if(shape == null) {
            shape = draw.registerShape(InlineDebugShape(uidName));
            shape.drawAxes(Xfo(), false);
        }
    
        this.drawShapeInstances(uidName, shader, transforms, shape, instance);
        Ref<OGLOrthoProjectionToFixedScreenLocation> orthoShader = shader;
    
        orthoShader.viewX = viewX;
        orthoShader.viewY = viewY;
        orthoShader.viewH = viewH;
        orthoShader.viewW = viewW;
    }
    
    

    Thanks again!!!

  • Daniele NieroDaniele Niero Posts: 233 ✭✭

    Hi @Ahmidou

    Thank you so much for your help, I can confirm that it works!
    I just changed few small things because the axes drawn looked a little bit weird... so messing around this the matrices multiplications in the shader I've found out that you just need this: u_viewMatrix_ * position

    Anyway this is what I got after re-touching your code:

    require InlineDrawing;
    
    
    object OGLOrthoProjectionToFixedScreenLocation: OGLInlineShader {
        Scalar viewX; 
        Scalar viewY; 
        Scalar viewW; 
        Scalar viewH; 
    };
    
    function OGLOrthoProjectionToFixedScreenLocation() { 
        // Avoid calling the init method if this default constructor is being invoked 
        // during the construction of a derived object. 
    
        this.viewX = 0.0; 
        this.viewY = 0.0; 
        this.viewW = 50.0; 
        this.viewH = 50.0; 
        if(this.type() == OGLOrthoProjectionToFixedScreenLocation) 
            this.init(String(this.type())); 
    } 
    
    /// default constructor taking a name 
    function OGLOrthoProjectionToFixedScreenLocation(String name) { 
        this.init(name); 
    } 
    
    /// initialize the OGLOrthoProjectionToFixedScreenLocation using name 
    /// \internal 
    function OGLOrthoProjectionToFixedScreenLocation.init!(String name) { 
        this.name = name; 
    
        this.setVertexCode("
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            uniform mat4 u_viewMatrix_; 
    
            attribute vec4 positions; 
            attribute vec4 vertexColors; 
    
            varying vec4 v_vertexColor; 
    
            void main(){ 
                gl_Position = u_viewMatrix_ * positions; 
                v_vertexColor = vertexColors; 
            } "
        ); 
    
        this.setFragmentCode(" 
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            varying vec4 v_vertexColor; 
            void main(){ 
                gl_FragColor = v_vertexColor; 
            } "
        ); 
    
        this.defineUniform(InlineUniform("u_viewMatrix_", Mat44())); 
        this.defineAttribute('positions', "Vec4"); 
        this.defineAttribute('vertexColors', "Vec4"); 
    } 
    
    function Boolean OGLOrthoProjectionToFixedScreenLocation.draw!(io DrawContext context) { 
        InlineViewport viewport = context.viewport; 
    
        Mat44 viewMat = viewport.getViewMat(); 
        viewMat.setTranslation(Vec3(0, 0, 0)); 
        this.setUniform(InlineUniform('u_viewMatrix_', viewMat)); 
    
        glViewport(this.viewX, this.viewY, this.viewW, this.viewH); 
        glDisable(GL_DEPTH_TEST); 
    
        return this.parent.draw(context); 
    }
    
    
    
    /// helper function to draw a axes at the viewport's bottom corner 
    function DrawingHandle.drawViewportCoordinates!(String name, Float32 viewX, Float32 viewY, Float32 viewH, Float32 viewW, out InlineInstance instance)
    {
        String uidName = this.uid() + '_' + name;
    
        Xfo transforms[];
        transforms.push(Xfo());
    
        InlineDrawing draw = this.getDrawing();
        InlineShader shader = draw.registerShader(OGLOrthoProjectionToFixedScreenLocation);
        InlineDebugShape shape = draw.getShape(uidName);
        if(shape == null) {
            shape = draw.registerShape(InlineDebugShape(uidName));
            shape.drawAxes(Xfo(), false);
        }
    
        this.drawShapeInstances(uidName, shader, transforms, shape, instance);
        Ref<OGLOrthoProjectionToFixedScreenLocation> orthoShader = shader;
    
    
        orthoShader.viewX = viewX;
        orthoShader.viewY = viewY;
        orthoShader.viewH = viewH;
        orthoShader.viewW = viewW;
    }
    
    

    Thanks again!!!

  • Daniele NieroDaniele Niero Posts: 233 ✭✭

    Hi @Ahmidou

    Thank you so much for your help, I can confirm that it works!
    I just changed few small things because the axes drawn looked a little bit weird... so messing around this the matrices multiplications in the shader I've found out that you just need this: u_viewMatrix_ * position

    Anyway this is what I got after re-touching your code:

    require InlineDrawing;
    
    
    object OGLOrthoProjectionToFixedScreenLocation: OGLInlineShader {
        Scalar viewX; 
        Scalar viewY; 
        Scalar viewW; 
        Scalar viewH; 
    };
    
    function OGLOrthoProjectionToFixedScreenLocation() { 
        // Avoid calling the init method if this default constructor is being invoked 
        // during the construction of a derived object. 
    
        this.viewX = 0.0; 
        this.viewY = 0.0; 
        this.viewW = 50.0; 
        this.viewH = 50.0; 
        if(this.type() == OGLOrthoProjectionToFixedScreenLocation) 
            this.init(String(this.type())); 
    } 
    
    /// default constructor taking a name 
    function OGLOrthoProjectionToFixedScreenLocation(String name) { 
        this.init(name); 
    } 
    
    /// initialize the OGLOrthoProjectionToFixedScreenLocation using name 
    /// \internal 
    function OGLOrthoProjectionToFixedScreenLocation.init!(String name) { 
        this.name = name; 
    
        this.setVertexCode("
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            uniform mat4 u_viewMatrix_; 
    
            attribute vec4 positions; 
            attribute vec4 vertexColors; 
    
            varying vec4 v_vertexColor; 
    
            void main(){ 
                gl_Position = u_viewMatrix_ * positions; 
                v_vertexColor = vertexColors; 
            } "
        ); 
    
        this.setFragmentCode(" 
            #version 120 // We require OpenGL 2.1 for InlineDrawing, which supports GLSL 1.2 
    
            varying vec4 v_vertexColor; 
            void main(){ 
                gl_FragColor = v_vertexColor; 
            } "
        ); 
    
        this.defineUniform(InlineUniform("u_viewMatrix_", Mat44())); 
        this.defineAttribute('positions', "Vec4"); 
        this.defineAttribute('vertexColors', "Vec4"); 
    } 
    
    function Boolean OGLOrthoProjectionToFixedScreenLocation.draw!(io DrawContext context) { 
        InlineViewport viewport = context.viewport; 
    
        Mat44 viewMat = viewport.getViewMat(); 
        viewMat.setTranslation(Vec3(0, 0, 0)); 
        this.setUniform(InlineUniform('u_viewMatrix_', viewMat)); 
    
        glViewport(this.viewX, this.viewY, this.viewW, this.viewH); 
        glDisable(GL_DEPTH_TEST); 
    
        return this.parent.draw(context); 
    }
    
    
    
    /// helper function to draw a axes at the viewport's bottom corner 
    function DrawingHandle.drawViewportCoordinates!(String name, Float32 viewX, Float32 viewY, Float32 viewH, Float32 viewW, out InlineInstance instance)
    {
        String uidName = this.uid() + '_' + name;
    
        Xfo transforms[];
        transforms.push(Xfo());
    
        InlineDrawing draw = this.getDrawing();
        InlineShader shader = draw.registerShader(OGLOrthoProjectionToFixedScreenLocation);
        InlineDebugShape shape = draw.getShape(uidName);
        if(shape == null) {
            shape = draw.registerShape(InlineDebugShape(uidName));
            shape.drawAxes(Xfo(), false);
        }
    
        this.drawShapeInstances(uidName, shader, transforms, shape, instance);
        Ref<OGLOrthoProjectionToFixedScreenLocation> orthoShader = shader;
    
    
        orthoShader.viewX = viewX;
        orthoShader.viewY = viewY;
        orthoShader.viewH = viewH;
        orthoShader.viewW = viewW;
    }
    
    

    Thanks again!!!

  • AhmidouAhmidou Posts: 179 ✭✭
    edited July 7

    what do you mean by weird? I haven't tried in the standalone, but here it's matching the Maya one that is orthographic.
    I'll try this week end in the standalone.
    edit:
    Actually you're right the ortho projection is not needed at all.

    I'm glad it helped!

Sign In or Register to comment.