<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:#0563C1;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:#954F72;
        text-decoration:underline;}
span.EmailStyle17
        {mso-style-type:personal-compose;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="#0563C1" vlink="#954F72">
<div class="WordSection1">
<p class="MsoNormal">We are trying to build a Unity plugin using Native C++ which will allow us to incorporate VTK rendering. We have a plugin which demonstrates the basics of this based and draws a rotating cube. Our problem is that the cube doesn't move with
 the rest of the world - the vtkExternalOpenGLCamera doesn't appear to be using the View or Projection matrices given to it.
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Platform is Windows 10 64bit application.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">A few ways we have investigated this:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">* The cube can be moved within the view by setting its position
<o:p></o:p></p>
<p class="MsoNormal">    * Setting X or Y to +/-1 moves it to the edges of the view - indicating that it's position is in screen space, where the limits are +/_ 1
<o:p></o:p></p>
<p class="MsoNormal">    * Changing Z doesn't change the view of the cube - indicating that the view is orthographic<o:p></o:p></p>
<p class="MsoNormal">* Looking at the transforms/matrices in the camera using the debugger they are identity matrices - which is consostent with the above<o:p></o:p></p>
<p class="MsoNormal">* To Unity we have added a cebug script which allows the user to move the camera around<o:p></o:p></p>
<p class="MsoNormal">    * The elements of the scene rendered by Unity move as expected<o:p></o:p></p>
<p class="MsoNormal">    * The elements in the of the scene rendered by VTK do not move - they stay in the same place relative to the camera<o:p></o:p></p>
<p class="MsoNormal">        * This indicates that the View matrix is not being used by the vtkExternalOpenGLCamera<o:p></o:p></p>
<p class="MsoNormal">* Getting the camera View and Projection matrices from Unity and passing them to VTK<o:p></o:p></p>
<p class="MsoNormal">    * This post suggests that we should not need to do this (http://vtk.1045678.n5.nabble.com/Using-vtkExternalOpenGLCamera-td5744015.html) - the camera position should be automatically be updated by the vtk code - "The external renderer
 is responsible for updating the VTK camera matrices based on the OpenGL state." <o:p>
</o:p></p>
<p class="MsoNormal">    * However, we added functions to the plugin to pass the View and projection matrix values and then set them in the vtkExternalOpenGLCamera<o:p></o:p></p>
<p class="MsoNormal">        * No change is observed in the rendering <o:p></o:p></p>
<p class="MsoNormal">        * Running through the code in the debugger the matrices do appear to be set in the camera
<o:p></o:p></p>
<p class="MsoNormal">        <o:p></o:p></p>
<p class="MsoNormal">During the first run the first run these matrices appear to be successfully set...<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">* UserProvidedViewTransform - false -> true<o:p></o:p></p>
<p class="MsoNormal">* ViewTransform - Concatenation - PreMatrix - Identity -> Matches transpose of supplied view matrix<o:p></o:p></p>
<p class="MsoNormal">* ModelViewTransform - Concatenation - PreMatrix - Identity -> Matches transpose of supplied view matrix<o:p></o:p></p>
<p class="MsoNormal">* UseExplicitProjectionTransformMatrix - false -> true<o:p></o:p></p>
<p class="MsoNormal">* ExplicitProjectionTransformMatrix - undefined -> defined as the transpose of the supplied projection matrix
<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I've also tried setting these to hard coded values, but with no effect.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">So at this point we are a bit stuck as to why it isn't working, and so how to make it work.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">* Any suggestions to fix this are welcomed<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Core code for the plugin (which includes all of the VTK code follows) NB, this was based on an example native C++ Unity Plugin from here (but a lot of the code has been stripped out for clarity): https://bitbucket.org/Unity-Technologies/graphicsdemos/src/43011994ae74/NativeRenderingPlugin/?at=default<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include "RenderAPI.h"<o:p></o:p></p>
<p class="MsoNormal">#include "PlatformBase.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// OpenGL Core profile (desktop) or OpenGL ES (mobile) implementation of RenderAPI.<o:p></o:p></p>
<p class="MsoNormal">// Supports several flavors: Core, ES2, ES3<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">//vtk headers<o:p></o:p></p>
<p class="MsoNormal">#include "vtkAutoInit.h" <o:p></o:p></p>
<p class="MsoNormal">VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2<o:p></o:p></p>
<p class="MsoNormal">#include <ExternalVTKWidget.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkActor.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkProperty.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkCallbackCommand.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkCamera.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkCubeSource.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkExternalOpenGLRenderWindow.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkExternalOpenGLCamera.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkLight.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkNew.h><o:p></o:p></p>
<p class="MsoNormal">#include <vtkPolyDataMapper.h><o:p></o:p></p>
<p class="MsoNormal">#include "vtkWindows.h" // Needed to include OpenGL header on Windows.<o:p></o:p></p>
<p class="MsoNormal">#include <vtk_glew.h><o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#if SUPPORT_OPENGL_UNIFIED<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include "GLEW/glew.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">class RenderAPI_OpenGLCoreES : public RenderAPI<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">public:<o:p></o:p></p>
<p class="MsoNormal">    RenderAPI_OpenGLCoreES(UnityGfxRenderer apiType);<o:p></o:p></p>
<p class="MsoNormal">    virtual ~RenderAPI_OpenGLCoreES() { }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    virtual void ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    virtual bool GetUsesReverseZ() { return false; }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    virtual void UpdateVtk(const double viewMatrix[16], const double projectionMatrix[16]); // std::string &debugStr);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">private:<o:p></o:p></p>
<p class="MsoNormal">    void CreateResources();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">private:<o:p></o:p></p>
<p class="MsoNormal">    // vtk<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<ExternalVTKWidget> m_ExternalVTKWidget;<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<vtkExternalOpenGLRenderer> m_renderer;<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<vtkActor> m_CubeActor;<o:p></o:p></p>
<p class="MsoNormal">    vtkSmartPointer<vtkExternalOpenGLCamera> m_externalVtkCamera;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    UnityGfxRenderer m_APIType;<o:p></o:p></p>
<p class="MsoNormal">    GLuint m_VertexShader;<o:p></o:p></p>
<p class="MsoNormal">    GLuint m_Program;<o:p></o:p></p>
<p class="MsoNormal">    GLuint m_VertexBuffer;<o:p></o:p></p>
<p class="MsoNormal">};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">RenderAPI* CreateRenderAPI_OpenGLCoreES(UnityGfxRenderer apiType)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    return new RenderAPI_OpenGLCoreES(apiType);<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">enum VertexInputs<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    kVertexInputPosition = 0,<o:p></o:p></p>
<p class="MsoNormal">    kVertexInputColor = 1<o:p></o:p></p>
<p class="MsoNormal">};<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">// Simple vertex shader source<o:p></o:p></p>
<p class="MsoNormal">#define VERTEX_SHADER_SRC(ver, attr, varying)                       \<o:p></o:p></p>
<p class="MsoNormal">    ver                                                             \<o:p></o:p></p>
<p class="MsoNormal">    attr " highp vec3 pos;\n"                                       \<o:p></o:p></p>
<p class="MsoNormal">    attr " lowp vec4 color;\n"                                      \<o:p></o:p></p>
<p class="MsoNormal">    "\n"                                                            \<o:p></o:p></p>
<p class="MsoNormal">    varying " lowp vec4 ocolor;\n"                                  \<o:p></o:p></p>
<p class="MsoNormal">    "\n"                                                            \<o:p></o:p></p>
<p class="MsoNormal">    "uniform highp mat4 worldMatrix;\n"                             \<o:p></o:p></p>
<p class="MsoNormal">    "uniform highp mat4 viewMatrix;\n"                              \<o:p></o:p></p>
<p class="MsoNormal">    "uniform highp mat4 projMatrix;\n"                              \<o:p></o:p></p>
<p class="MsoNormal">    "\n"                                                            \<o:p></o:p></p>
<p class="MsoNormal">    "void main()\n"                                                 \<o:p></o:p></p>
<p class="MsoNormal">    "{\n"                                                           \<o:p></o:p></p>
<p class="MsoNormal">    "   gl_Position = (projMatrix * viewMatrix * worldMatrix) * vec4(pos,1);\n" \<o:p></o:p></p>
<p class="MsoNormal">    "   ocolor = color;\n"                                          \<o:p></o:p></p>
<p class="MsoNormal">    "}\n"                                                           \<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">static const char* kGlesVProgTextGLES2 = VERTEX_SHADER_SRC("\n", "attribute", "varying");<o:p></o:p></p>
<p class="MsoNormal">static const char* kGlesVProgTextGLES3 = VERTEX_SHADER_SRC("#version 300 es\n", "in", "out");<o:p></o:p></p>
<p class="MsoNormal">#if SUPPORT_OPENGL_CORE<o:p></o:p></p>
<p class="MsoNormal">static const char* kGlesVProgTextGLCore = VERTEX_SHADER_SRC("#version 150\n", "in", "out");<o:p></o:p></p>
<p class="MsoNormal">#endif<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#undef VERTEX_SHADER_SRC<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">static GLuint CreateShader(GLenum type, const char* sourceText)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    GLuint ret = glCreateShader(type);<o:p></o:p></p>
<p class="MsoNormal">    glShaderSource(ret, 1, &sourceText, NULL);<o:p></o:p></p>
<p class="MsoNormal">    glCompileShader(ret);<o:p></o:p></p>
<p class="MsoNormal">    return ret;<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void RenderAPI_OpenGLCoreES::CreateResources()<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    // Create shaders<o:p></o:p></p>
<p class="MsoNormal">    glewExperimental = GL_TRUE;<o:p></o:p></p>
<p class="MsoNormal">    glewInit();<o:p></o:p></p>
<p class="MsoNormal">    glGetError(); // Clean up error generated by glewInit<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    m_VertexShader = CreateShader(GL_VERTEX_SHADER, kGlesVProgTextGLCore);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // Link shaders into a program and find uniform locations<o:p></o:p></p>
<p class="MsoNormal">    m_Program = glCreateProgram();<o:p></o:p></p>
<p class="MsoNormal">    glBindAttribLocation(m_Program, kVertexInputPosition, "pos");<o:p></o:p></p>
<p class="MsoNormal">    glBindAttribLocation(m_Program, kVertexInputColor, "color");<o:p></o:p></p>
<p class="MsoNormal">    glAttachShader(m_Program, m_VertexShader);<o:p></o:p></p>
<p class="MsoNormal">    //glAttachShader(m_Program, m_FragmentShader);<o:p></o:p></p>
<p class="MsoNormal">#   if SUPPORT_OPENGL_CORE<o:p></o:p></p>
<p class="MsoNormal">    if (m_APIType == kUnityGfxRendererOpenGLCore)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        glBindFragDataLocation(m_Program, 0, "fragColor");<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">#   endif // if SUPPORT_OPENGL_CORE<o:p></o:p></p>
<p class="MsoNormal">    glLinkProgram(m_Program);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    GLint status = 0;<o:p></o:p></p>
<p class="MsoNormal">    glGetProgramiv(m_Program, GL_LINK_STATUS, &status);<o:p></o:p></p>
<p class="MsoNormal">    assert(status == GL_TRUE);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // Create vertex buffer<o:p></o:p></p>
<p class="MsoNormal">    glGenBuffers(1, &m_VertexBuffer);<o:p></o:p></p>
<p class="MsoNormal">    glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);<o:p></o:p></p>
<p class="MsoNormal">    glBufferData(GL_ARRAY_BUFFER, 1024, NULL, GL_STREAM_DRAW);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    assert(glGetError() == GL_NO_ERROR);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    //InitialiseWorldTriangleTest();<o:p></o:p></p>
<p class="MsoNormal">    // Rotating cube ---------------------------------------------------------------<o:p></o:p></p>
<p class="MsoNormal">    // initiate vtk content <o:p></o:p></p>
<p class="MsoNormal">    // create the VTK scene<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<vtkCubeSource> cs;<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<vtkPolyDataMapper> mapper;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    mapper->SetInputConnection(cs->GetOutputPort());<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    m_CubeActor->SetMapper(mapper.GetPointer());<o:p></o:p></p>
<p class="MsoNormal">    m_CubeActor->GetProperty()->SetColor(1, 1, 0.2);<o:p></o:p></p>
<p class="MsoNormal">    m_CubeActor->GetProperty()->SetOpacity(0.5);<o:p></o:p></p>
<p class="MsoNormal">    m_CubeActor->SetPosition(0.5, 0, 0);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // create the VTK external renderer<o:p></o:p></p>
<p class="MsoNormal">    vtkNew<vtkExternalOpenGLRenderWindow> renWin;<o:p></o:p></p>
<p class="MsoNormal">    m_ExternalVTKWidget->SetRenderWindow(renWin.GetPointer());<o:p></o:p></p>
<p class="MsoNormal">    m_ExternalVTKWidget->GetRenderWindow()->AddRenderer(m_renderer.GetPointer());<o:p></o:p></p>
<p class="MsoNormal">    m_renderer->AddActor(m_CubeActor.GetPointer());<o:p></o:p></p>
<p class="MsoNormal">    m_renderer->ResetCamera();<o:p></o:p></p>
<p class="MsoNormal">    m_externalVtkCamera = vtkSmartPointer<vtkExternalOpenGLCamera>(<o:p></o:p></p>
<p class="MsoNormal">        dynamic_cast<vtkExternalOpenGLCamera*>(m_renderer->GetActiveCamera()));<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">RenderAPI_OpenGLCoreES::RenderAPI_OpenGLCoreES(UnityGfxRenderer apiType)<o:p></o:p></p>
<p class="MsoNormal">    : m_APIType(apiType)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void RenderAPI_OpenGLCoreES::ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    if (type == kUnityGfxDeviceEventInitialize)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        CreateResources();<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">    else if (type == kUnityGfxDeviceEventShutdown)<o:p></o:p></p>
<p class="MsoNormal">    {<o:p></o:p></p>
<p class="MsoNormal">        //@TODO: release resources<o:p></o:p></p>
<p class="MsoNormal">    }<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void RenderAPI_OpenGLCoreES::UpdateVtk(const double viewMatrix[16], const double projectionMatrix[16]) //std::string &debugStr)<o:p></o:p></p>
<p class="MsoNormal">{<o:p></o:p></p>
<p class="MsoNormal">    m_externalVtkCamera->SetViewTransformMatrix(viewMatrix);<o:p></o:p></p>
<p class="MsoNormal">    m_externalVtkCamera->SetProjectionTransformMatrix(projectionMatrix);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">    // draw vtk content<o:p></o:p></p>
<p class="MsoNormal">    m_CubeActor->RotateX(1.0f);<o:p></o:p></p>
<p class="MsoNormal">    m_CubeActor->RotateY(1.0f);<o:p></o:p></p>
<p class="MsoNormal">    m_ExternalVTKWidget->GetRenderWindow()->Render();<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#endif // #if SUPPORT_OPENGL_UNIFIED<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>