<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>