1 /*
2 OpenVR for PyMOL Copyright Notice
3 =====================================
4
5 The OpenVR for PyMOL source code is copyrighted, but you can freely use and
6 copy it as long as you don't change or remove any of the Copyright notices.
7 OpenVR for PyMOL is made available under the following open-source license
8 terms:
9
10 ------------------------------------------------------------------------------
11 Copyright (c) 2018 EPAM Systems, Inc.
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30 ------------------------------------------------------------------------------
31
32 */
33
34 // this header
35 #include "OpenVRControllerModel.h"
36
37 // system headers
38 #include <vector>
39 #include "os_std.h"
40 #include "os_gl.h"
41
42 // pymol headers
43 #include "Feedback.h"
44 #include "Matrix.h"
45
46 // local headers
47 #include "OpenVRController.h"
48
49 static std::vector<OpenVRControllerModel *> s_vecRenderModels;
50
51 //-----------------------------------------------------------------------------
52 // Purpose: Create/destroy GL Render Models
53 //-----------------------------------------------------------------------------
OpenVRControllerModel(const std::string & sRenderModelName)54 OpenVRControllerModel::OpenVRControllerModel(const std::string & sRenderModelName) : m_sModelName( sRenderModelName ) {
55 m_glIndexBuffer = 0;
56 m_glVertArray = 0;
57 m_glVertBuffer = 0;
58 m_glTexture = 0;
59 m_pShader = NULL;
60 }
61
~OpenVRControllerModel()62 OpenVRControllerModel::~OpenVRControllerModel() {
63 Free();
64 }
65
66 //-----------------------------------------------------------------------------
67 // Purpose: Allocates and populates the GL resources for a render model
68 //-----------------------------------------------------------------------------
Init(PyMOLGlobals * G,const vr::RenderModel_t & vrModel,const vr::RenderModel_TextureMap_t & vrDiffuseTexture)69 bool OpenVRControllerModel::Init(PyMOLGlobals *G, const vr::RenderModel_t &vrModel, const vr::RenderModel_TextureMap_t &vrDiffuseTexture) {
70 InitGeometry(vrModel);
71 InitTexture(vrDiffuseTexture);
72 InitShaders(G);
73 return true;
74 }
75
76 //-----------------------------------------------------------------------------
77 // Purpose: Frees the GL resources for a render model
78 //-----------------------------------------------------------------------------
Free()79 void OpenVRControllerModel::Free() {
80 FreeShaders();
81 FreeTexture();
82 FreeGeometry();
83 }
84
InitGeometry(const vr::RenderModel_t & vrModel)85 void OpenVRControllerModel::InitGeometry(const vr::RenderModel_t &vrModel) {
86 // create and bind a VAO to hold state for this model
87 glGenVertexArrays( 1, &m_glVertArray );
88 glBindVertexArray( m_glVertArray );
89
90 // Populate a vertex buffer
91 glGenBuffers( 1, &m_glVertBuffer );
92 glBindBuffer( GL_ARRAY_BUFFER, m_glVertBuffer );
93 glBufferData( GL_ARRAY_BUFFER, sizeof(vr::RenderModel_Vertex_t) *vrModel.unVertexCount, vrModel.rVertexData, GL_STATIC_DRAW);
94
95 // Identify the components in the vertex buffer
96 glEnableVertexAttribArray(0);
97 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof( vr::RenderModel_Vertex_t ), (void *)offsetof( vr::RenderModel_Vertex_t, vPosition));
98 glEnableVertexAttribArray(1);
99 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof( vr::RenderModel_Vertex_t ), (void *)offsetof(vr::RenderModel_Vertex_t, rfTextureCoord));
100
101 // Create and populate the index buffer
102 glGenBuffers( 1, &m_glIndexBuffer );
103 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_glIndexBuffer );
104 glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( uint16_t ) * vrModel.unTriangleCount * 3, vrModel.rIndexData, GL_STATIC_DRAW );
105
106 glBindVertexArray( 0 );
107
108 m_unVertexCount = vrModel.unTriangleCount * 3;
109 }
110
FreeGeometry()111 void OpenVRControllerModel::FreeGeometry() {
112 if( m_glVertBuffer ) {
113 glDeleteBuffers(1, &m_glIndexBuffer);
114 glDeleteVertexArrays( 1, &m_glVertArray );
115 glDeleteBuffers(1, &m_glVertBuffer);
116 m_glIndexBuffer = 0;
117 m_glVertArray = 0;
118 m_glVertBuffer = 0;
119 }
120 }
121
InitTexture(const vr::RenderModel_TextureMap_t & vrDiffuseTexture)122 void OpenVRControllerModel::InitTexture(const vr::RenderModel_TextureMap_t &vrDiffuseTexture) {
123 // create and populate the texture
124 glGenTextures(1, &m_glTexture );
125 glBindTexture( GL_TEXTURE_2D, m_glTexture );
126
127 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, vrDiffuseTexture.unWidth, vrDiffuseTexture.unHeight,
128 0, GL_RGBA, GL_UNSIGNED_BYTE, vrDiffuseTexture.rubTextureMapData );
129
130 // If this renders black ask McJohn what's wrong.
131 glGenerateMipmap(GL_TEXTURE_2D);
132
133 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
134 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
135 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
136 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
137
138 GLfloat fLargest;
139 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest );
140 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest );
141
142 glBindTexture( GL_TEXTURE_2D, 0 );
143 }
144
FreeTexture()145 void OpenVRControllerModel::FreeTexture() {
146 if (m_glTexture) {
147 glDeleteTextures(1, &m_glTexture);
148 m_glTexture = 0;
149 }
150 }
151
InitShaders(PyMOLGlobals * G)152 bool OpenVRControllerModel::InitShaders(PyMOLGlobals * G) {
153 m_pShader = new CShaderPrg(G, "CRenderModel", "vrcontroller.vs", "vrcontroller.fs");
154 if (m_pShader) {
155 m_pShader->reload();
156 glBindAttribLocation(m_pShader->id, 0, "position");
157 glBindAttribLocation(m_pShader->id, 1, "texcoords_in");
158 glLinkProgram(m_pShader->id);
159 }
160 return m_pShader != NULL;
161 }
162
FreeShaders()163 void OpenVRControllerModel::FreeShaders() {
164 if (m_pShader) {
165 delete m_pShader;
166 m_pShader = NULL;
167 }
168 }
169
170 //-----------------------------------------------------------------------------
171 // Purpose: Draws the render model
172 //-----------------------------------------------------------------------------
Draw()173 void OpenVRControllerModel::Draw() {
174 GL_DEBUG_FUN();
175 m_pShader->Enable();
176 glBindVertexArray( m_glVertArray );
177
178 glActiveTexture( GL_TEXTURE0 );
179 glBindTexture( GL_TEXTURE_2D, m_glTexture );
180
181 glDrawElements( GL_TRIANGLES, m_unVertexCount, GL_UNSIGNED_SHORT, 0 );
182
183 glBindVertexArray( 0 );
184 m_pShader->Disable();
185 }
186
187 // Purpose:
188 //-----------------------------------------------------------------------------
189 static
ThreadSleep(unsigned long nMilliseconds)190 void ThreadSleep( unsigned long nMilliseconds )
191 {
192 #if defined(_WIN32)
193 ::Sleep( nMilliseconds );
194 #elif defined(POSIX)
195 usleep( nMilliseconds * 1000 );
196 #endif
197 }
198
199 // Purpose: Finds a render model we've already loaded or loads a new one
200 //-----------------------------------------------------------------------------
FindOrLoadRenderModel(PyMOLGlobals * G,const char * pchRenderModelName)201 OpenVRControllerModel *FindOrLoadRenderModel(PyMOLGlobals * G, const char *pchRenderModelName)
202 {
203 OpenVRControllerModel *pRenderModel = NULL;
204 for(std::vector<OpenVRControllerModel *>::iterator i = s_vecRenderModels.begin(); i != s_vecRenderModels.end(); i++) {
205 if(!
206 #ifdef _WIN32
207 stricmp
208 #else
209 strcasecmp
210 #endif
211 ((*i)->GetName().c_str(), pchRenderModelName)){
212 pRenderModel = *i;
213 break;
214 }
215 }
216
217 // load the model if we didn't find one
218 if(!pRenderModel) {
219 vr::RenderModel_t *pModel;
220 vr::EVRRenderModelError error;
221 while (true) {
222 error = vr::VRRenderModels()->LoadRenderModel_Async(pchRenderModelName, &pModel);
223 if (error != vr::VRRenderModelError_Loading)
224 break;
225
226 ThreadSleep( 1 );
227 }
228
229 if (error != vr::VRRenderModelError_None) {
230 PRINTF
231 " Unable to load render model %s - %s\n",
232 pchRenderModelName,
233 vr::VRRenderModels()->GetRenderModelErrorNameFromEnum(error)
234 ENDF(G);
235 return NULL; // move on to the next tracked device
236 }
237
238 vr::RenderModel_TextureMap_t *pTexture;
239 while (true) {
240 error = vr::VRRenderModels()->LoadTexture_Async(pModel->diffuseTextureId, &pTexture);
241 if (error != vr::VRRenderModelError_Loading)
242 break;
243 ThreadSleep( 1 );
244 }
245
246 if (error != vr::VRRenderModelError_None) {
247 PRINTF
248 " Unable to load render texture id:%d for render model %s\n",
249 pModel->diffuseTextureId,
250 pchRenderModelName
251 ENDF(G);
252 vr::VRRenderModels()->FreeRenderModel(pModel);
253 return NULL; // move on to the next tracked device
254 }
255
256 pRenderModel = new OpenVRControllerModel(pchRenderModelName);
257 if (!pRenderModel->Init(G, *pModel, *pTexture)) {
258 PRINTF
259 " Unable to create GL model from render model %s\n",
260 pchRenderModelName
261 ENDF(G);
262 delete pRenderModel;
263 pRenderModel = NULL;
264 } else {
265 s_vecRenderModels.push_back(pRenderModel);
266 }
267 vr::VRRenderModels()->FreeRenderModel(pModel);
268 vr::VRRenderModels()->FreeTexture(pTexture);
269 }
270 return pRenderModel;
271 }
272
ShutdownRenderModels()273 void ShutdownRenderModels() {
274 for(std::vector<OpenVRControllerModel *>::iterator i = s_vecRenderModels.begin(); i != s_vecRenderModels.end(); i++) {
275 (*i)->Free();
276 delete (*i);
277 }
278 s_vecRenderModels.clear();
279 }
280