FreeCAD

Форк
0
/
CoinRiftWidget.cpp 
507 строк · 20.2 Кб
1
/**************************************************************************
2
* Copyright (c) 2014 Bastiaan Veelo <Bastiaan a_t Veelo d_o_t net>        *
3
* Copyright (c) 2014 Jürgen Riegel <FreeCAD@juergen-riegel.net>           *
4
*                                                                         *
5
* All rights reserved. Contact me if the below is too restrictive for you.*
6
*                                                                         *
7
* Redistribution and use in source and binary forms, with or without      *
8
* modification, are permitted provided that the following conditions are  *
9
* met:                                                                    *
10
*                                                                         *
11
* Redistributions of source code must retain the above copyright notice,  *
12
* this list of conditions and the following disclaimer.                   *
13
*                                                                         *
14
* Redistributions in binary form must reproduce the above copyright       *
15
* notice, this list of conditions and the following disclaimer in the     *
16
* documentation and/or other materials provided with the distribution.    *
17
*                                                                         *
18
* Neither the name of the copyright holder nor the names of its           *
19
* contributors may be used to endorse or promote products derived from    *
20
* this software without specific prior written permission.                *
21
*                                                                         *
22
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS     *
23
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT       *
24
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR   *
25
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT    *
26
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  *
27
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT        *
28
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   *
29
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY   *
30
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT     *
31
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE   *
32
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.    *
33
\**************************************************************************/
34

35
#include "PreCompiled.h"
36
#include "CoinRiftWidget.h"
37

38
#include <Base/Console.h>
39

40
#if BUILD_VR
41

42

43

44
#undef max
45

46

47

48

49
CoinRiftWidget::CoinRiftWidget() : QGLWidget()
50
{
51
    for (int eye = 0; eye < 2; eye++) {
52
        reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye])->TexId = 0;
53
#ifdef USE_FRAMEBUFFER
54
        frameBufferID[eye] = 0;
55
        depthBufferID[eye] = 0;
56
#endif
57
    }
58

59
    // OVR will do the swapping.
60
    setAutoBufferSwap(false);
61

62
    hmd = ovrHmd_Create(0);
63
    if (!hmd) {
64
        qDebug() << "Could not find Rift device.";
65
        throw;
66
    }
67

68
    if (!ovrHmd_ConfigureTracking (hmd, ovrTrackingCap_Orientation |
69
                                        ovrTrackingCap_MagYawCorrection |
70
                                        ovrTrackingCap_Position,
71
                                        ovrTrackingCap_Orientation |
72
                                        ovrTrackingCap_MagYawCorrection |
73
                                        ovrTrackingCap_Position
74
                                        )) { // Capabilities we require.
75
        qDebug() << "Could not start Rift motion sensor.";
76
        throw;
77
    }
78

79
    resize(hmd->Resolution.w, hmd->Resolution.h);
80

81
    // Configure stereo settings.
82
    ovrSizei recommenedTex0Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left,
83
                                                           hmd->DefaultEyeFov[0], 1.0f);
84
    ovrSizei recommenedTex1Size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right,
85
                                                           hmd->DefaultEyeFov[1], 1.0f);
86

87
#ifdef USE_SO_OFFSCREEN_RENDERER
88
    renderer = new SoOffscreenRenderer(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w),
89
                                                        std::max(recommenedTex1Size.h, recommenedTex1Size.h)));
90
    renderer->setComponents(SoOffscreenRenderer::RGB_TRANSPARENCY);
91
    BackgroundColor = SbColor(.0f, .0f, .8f);
92
    renderer->setBackgroundColor(BackgroundColor);
93
#endif
94
#ifdef USE_FRAMEBUFFER
95
    m_sceneManager = new SoSceneManager();
96
    m_sceneManager->setViewportRegion(SbViewportRegion(std::max(recommenedTex0Size.w, recommenedTex0Size.w),
97
                                                       std::max(recommenedTex1Size.h, recommenedTex1Size.h)));
98
    m_sceneManager->setBackgroundColor(SbColor(.0f, .0f, .8f));
99
#endif
100
    basePosition = SbVec3f(0.0f, 0.0f, -2.0f);
101

102
    // light handling
103
     SoDirectionalLight *light = new SoDirectionalLight();
104
    light->direction.setValue(1,-1,-1);
105

106
    SoDirectionalLight *light2 = new SoDirectionalLight();
107
    light2->direction.setValue(-1,-1,-1);
108
    light2->intensity.setValue(0.6);
109
    light2->color.setValue(0.8,0.8,1);
110

111

112
    scene = new SoSeparator(0); // Placeholder.
113
    for (int eye = 0; eye < 2; eye++) {
114
        rootScene[eye] = new SoSeparator();
115
        rootScene[eye]->ref();
116
        camera[eye] = new SoFrustumCamera();
117
        camera[eye]->position.setValue(basePosition);
118
        camera[eye]->focalDistance.setValue(5.0f);
119
        camera[eye]->viewportMapping.setValue(SoCamera::LEAVE_ALONE);
120
        rootScene[eye]->addChild(camera[eye]);
121
        rootScene[eye]->addChild(light);
122
        rootScene[eye]->addChild(light2);
123
        rootScene[eye]->addChild(scene);
124
    }
125

126
    // Populate ovrEyeDesc[2].
127
    eyeRenderDesc[0].Eye = ovrEye_Left;
128
    eyeRenderDesc[1].Eye = ovrEye_Right;
129
    eyeRenderDesc[0].Fov = hmd->DefaultEyeFov[0];
130
    eyeRenderDesc[1].Fov = hmd->DefaultEyeFov[1];
131
#ifdef USE_SO_OFFSCREEN_RENDERER
132
    eyeTexture[0].Header.TextureSize.w = renderer->getViewportRegion().getViewportSizePixels().getValue()[0];
133
    eyeTexture[0].Header.TextureSize.h = renderer->getViewportRegion().getViewportSizePixels().getValue()[1];
134
    eyeTexture[1].Header.TextureSize = eyeTexture[0].Header.TextureSize;
135
#endif
136
#ifdef USE_FRAMEBUFFER
137
    eyeTexture[0].Header.TextureSize = recommenedTex0Size;
138
    eyeTexture[1].Header.TextureSize = recommenedTex1Size;
139
#endif
140
    eyeTexture[0].Header.RenderViewport.Pos.x = 0;
141
    eyeTexture[0].Header.RenderViewport.Pos.y = 0;
142
    eyeTexture[0].Header.RenderViewport.Size = eyeTexture[0].Header.TextureSize;
143
    eyeTexture[1].Header.RenderViewport.Pos = eyeTexture[0].Header.RenderViewport.Pos;
144
    eyeTexture[1].Header.RenderViewport.Size = eyeTexture[1].Header.TextureSize;
145

146
    const int backBufferMultisample = 0; // TODO This is a guess?
147
    ovrGLConfig cfg;
148
    cfg.OGL.Header.API = ovrRenderAPI_OpenGL;
149
    cfg.OGL.Header.RTSize = hmd->Resolution;
150
    cfg.OGL.Header.Multisample = backBufferMultisample;
151
    cfg.OGL.Window = reinterpret_cast<HWND>(winId());
152
    makeCurrent();
153
    //cfg.OGL.WglContext = wglGetCurrentContext(); // http://stackoverflow.com/questions/17532033/qglwidget-get-gl-contextes-for-windows
154
    cfg.OGL.DC = wglGetCurrentDC();
155
    qDebug() << "Window:" << cfg.OGL.Window;
156
    //qDebug() << "Context:" << cfg.OGL.WglContext;
157
    qDebug() << "DC:" << cfg.OGL.DC;
158

159
    int DistortionCaps = 0;
160
    DistortionCaps |= ovrDistortionCap_Chromatic;
161
// DistortionCaps |= ovrDistortionCap_TimeWarp; // Produces black screen...
162
    DistortionCaps |= ovrDistortionCap_Vignette;
163
    DistortionCaps |= ovrDistortionCap_HqDistortion;
164

165
    bool VSyncEnabled(false); // TODO This is a guess.
166
    if (!ovrHmd_ConfigureRendering( hmd,
167
                                    &cfg.Config,
168
                                    /*(VSyncEnabled ? 0 : ovrHmdCap_NoVSync),*/
169
                                    DistortionCaps,
170
                                    hmd->DefaultEyeFov,//eyes,
171
                                    eyeRenderDesc)) {
172
        qDebug() << "Could not configure OVR rendering.";
173
        throw;
174
    }
175
    static const float nearPlane = 0.01;
176

177
    for (int eye = 0; eye < 2; eye++) {
178
        camera[eye]->aspectRatio.setValue((eyeRenderDesc[eye].Fov.LeftTan + eyeRenderDesc[eye].Fov.RightTan) /
179
                (eyeRenderDesc[eye].Fov.UpTan + eyeRenderDesc[eye].Fov.DownTan));
180
        camera[eye]->nearDistance.setValue(nearPlane);
181
        camera[eye]->farDistance.setValue(10000.0f);
182
        camera[eye]->left.setValue(-eyeRenderDesc[eye].Fov.LeftTan * nearPlane);
183
        camera[eye]->right.setValue(eyeRenderDesc[eye].Fov.RightTan * nearPlane);
184
        camera[eye]->top.setValue(eyeRenderDesc[eye].Fov.UpTan * nearPlane);
185
        camera[eye]->bottom.setValue(-eyeRenderDesc[eye].Fov.DownTan * nearPlane);
186
    }
187
}
188

189

190
CoinRiftWidget::~CoinRiftWidget()
191
{
192
#ifdef USE_SO_OFFSCREEN_RENDERER
193
    delete renderer;
194
#endif
195
    for (int eye = 0; eye < 2; eye++) {
196
        rootScene[eye]->unref();
197
        ovrGLTextureData *texData = reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye]);
198
        if (texData->TexId) {
199
            glDeleteTextures(1, &texData->TexId);
200
            texData->TexId = 0;
201
        }
202
#ifdef USE_FRAMEBUFFER
203
        if (frameBufferID[eye] != 0) {
204
// OVR::CAPI::GL::glDeleteFramebuffersExt(1, &frameBufferID[eye]); // TODO
205
            frameBufferID[eye] = 0;
206
        }
207
        if (depthBufferID[eye] != 0) {
208
// OVR::CAPI::GL::glDeleteRenderbuffersExt(1, &depthBufferID[eye]); // TODO
209
            depthBufferID[eye] = 0;
210
        }
211
#endif
212
    }
213
    scene = 0;
214
    //ovrHmd_StopSensor(hmd);
215
    ovrHmd_Destroy(hmd);
216
}
217

218

219
void CoinRiftWidget::setBackgroundColor(const SbColor &Col)
220
{
221
    BackgroundColor = Col;
222
    renderer->setBackgroundColor(BackgroundColor);
223
}
224

225

226
void CoinRiftWidget::setSceneGraph(SoNode *sceneGraph)
227
{
228
    rootScene[0]->replaceChild(scene, sceneGraph);
229
    rootScene[1]->replaceChild(scene, sceneGraph);
230
    scene = sceneGraph;
231
}
232

233

234
void CoinRiftWidget::resizeGL(int width, int height) {
235
    int side = qMin(width, height);
236
    glViewport((width - side) / 2, (height - side) / 2, side, side);
237

238
    glMatrixMode(GL_PROJECTION);
239
    glLoadIdentity();
240
    glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1000.0);
241
    glMatrixMode(GL_MODELVIEW);
242
}
243

244
void CoinRiftWidget::initializeGL()
245
{
246
    makeCurrent();
247
    // Infer hardware capabilities.
248
#ifdef USE_FRAMEBUFFER
249
    OVR::CAPI::GL::InitGLExtensions();
250
    if (OVR::CAPI::GL::glBindFramebuffer == NULL) {
251
        qDebug() << "No GL extensions found.";
252
        exit(4);
253
    }
254

255
    // Store old framebuffer.
256
    GLint oldfb;
257
    glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
258
#endif
259

260
    // Create rendering target textures.
261
    glEnable(GL_TEXTURE_2D);
262
    for (int eye = 0; eye < 2; eye++) {
263
#ifdef USE_FRAMEBUFFER
264
        OVR::CAPI::GL::glGenFramebuffers(1, &frameBufferID[eye]);
265
        OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]);
266
        // Create the render buffer.
267
        // TODO: need to check for OpenGl 3 or higher and load the functions JR 2014
268
        /*OVR::CAPI::GL::*/glGenRenderbuffers(1, &depthBufferID[eye]);
269
        /*OVR::CAPI::GL::*/glBindRenderbuffer(GL_RENDERBUFFER_EXT, depthBufferID[eye]);
270
        /*OVR::CAPI::GL::*/glRenderbufferStorage(GL_RENDERBUFFER_EXT,
271
                                                GL_DEPTH_COMPONENT16,
272
                                                eyeTexture[eye].Header.TextureSize.w,
273
                                                eyeTexture[eye].Header.TextureSize.h);
274
        // Attach renderbuffer to framebuffer.
275
        OVR::CAPI::GL::glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT,
276
                                                    GL_DEPTH_ATTACHMENT_EXT,
277
                                                    GL_RENDERBUFFER_EXT,
278
                                                    depthBufferID[eye]);
279
#endif
280
        ovrGLTextureData *texData = reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye]);
281
        texData->Header.API = ovrRenderAPI_OpenGL;
282
        texData->Header.TextureSize = eyeTexture[eye].Header.TextureSize;
283
        texData->Header.RenderViewport = eyeTexture[eye].Header.RenderViewport;
284
        glGenTextures(1, &texData->TexId);
285
        glBindTexture(GL_TEXTURE_2D, texData->TexId);
286
        Q_ASSERT(!glGetError());
287
        // Allocate storage for the texture.
288
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, eyeTexture[eye].Header.TextureSize.w, eyeTexture[eye].Header.TextureSize.h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
289
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
290
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
291
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
292
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
293
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
294
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
295
        Q_ASSERT(!glGetError());
296
#ifdef USE_FRAMEBUFFER
297
        // Attach texture to framebuffer color object.
298
        OVR::CAPI::GL::glFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
299
                                                 GL_COLOR_ATTACHMENT0_EXT,
300
                                                 GL_TEXTURE_2D, texData->TexId, 0);
301
        if (OVR::CAPI::GL::glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
302
                GL_FRAMEBUFFER_COMPLETE)
303
            qDebug() << "ERROR: FrameBuffer is not operational!";
304
#endif
305
    }
306
    glBindTexture(GL_TEXTURE_2D, 0);
307
    glDisable(GL_TEXTURE_2D);
308

309
#ifdef USE_FRAMEBUFFER
310
    // Continue rendering to the original frame buffer (likely 0, the onscreen buffer).
311
    OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb);
312
#endif
313
    doneCurrent();
314
}
315

316

317
void CoinRiftWidget::paintGL()
318
{
319
    const int ms(1000 / 75 /*fps*/);
320
    QTimer::singleShot(ms, this, &CoinRiftWidget::updateGL);
321

322
    // handling the safety warning
323
    handlingSafetyWarning();
324

325
    makeCurrent();
326

327
    ovrPosef eyePose[2];
328

329
    glEnable(GL_TEXTURE_2D);
330

331
    ovrFrameTiming hmdFrameTiming = ovrHmd_BeginFrame(hmd, 0);
332
    for (int eyeIndex = 0; eyeIndex < ovrEye_Count; eyeIndex++) {
333
        ovrEyeType eye = hmd->EyeRenderOrder[eyeIndex];
334
        eyePose[eye] = ovrHmd_GetEyePose(hmd, eye);
335

336

337
        SbRotation    riftOrientation(  eyePose[eye].Orientation.x,
338
                                        eyePose[eye].Orientation.y,
339
                                        eyePose[eye].Orientation.z,
340
                                        eyePose[eye].Orientation.w);
341

342
        camera[eye]->orientation.setValue(riftOrientation);
343

344
        SbVec3f riftPosition =   SbVec3f(eyePose[eye].Position.x,
345
                                         eyePose[eye].Position.y,
346
                                         eyePose[eye].Position.z);
347

348

349
        //SbVec3f originalPosition(camera[eye]->position.getValue());
350
        SbVec3f viewAdjust(eyeRenderDesc[eye].ViewAdjust.x,
351
                                                              eyeRenderDesc[eye].ViewAdjust.y,
352
                                                              eyeRenderDesc[eye].ViewAdjust.z);
353

354
        riftOrientation.multVec(viewAdjust,viewAdjust);
355

356
        camera[eye]->position.setValue(basePosition - viewAdjust + riftPosition);
357

358
        //Base::Console().Log("Eye(%d) Pos: %f, %f, %f  ViewAdjust:  %f, %f, %f \n",eye, eyePose[eye].Position.x,
359
        //                                                eyePose[eye].Position.y,
360
        //                                 eyePose[eye].Position.z,
361
        //                                 eyeRenderDesc[eye].ViewAdjust.x,
362
        //                                                      eyeRenderDesc[eye].ViewAdjust.y,
363
        //                                                      eyeRenderDesc[eye].ViewAdjust.z);
364

365
#ifdef USE_SO_OFFSCREEN_RENDERER
366
        ovrGLTextureData *texData = reinterpret_cast<ovrGLTextureData*>(&eyeTexture[eye]);
367
        glBindTexture(GL_TEXTURE_2D, texData->TexId);
368
        renderer->render(rootScene[eye]);
369
        Q_ASSERT(!glGetError());
370
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
371
                     eyeTexture[eye].Header.TextureSize.w,
372
                     eyeTexture[eye].Header.TextureSize.h,
373
                     0, GL_RGBA /*GL_BGRA*/, GL_UNSIGNED_BYTE, renderer->getBuffer());
374
        Q_ASSERT(!glGetError());
375
        glBindTexture(GL_TEXTURE_2D, 0);
376
#endif
377
#ifdef USE_FRAMEBUFFER
378
        // Clear state pollution from OVR SDK.
379
        glBindTexture(GL_TEXTURE_2D, 0); // You need this, at least if (hmdDesc.DistortionCaps & ovrDistortion_Chromatic).
380
        OVR::CAPI::GL::glUseProgram(0); // You need this even more.
381

382
        GLint oldfb;
383
        glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
384
        // Set up framebuffer for rendering.
385
        OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, frameBufferID[eye]);
386

387
        m_sceneManager->setSceneGraph(rootScene[eye]);
388
// m_sceneManager->setCamera(camera[eye]); // SoSceneManager does this implicitly.
389
        m_sceneManager->render();
390

391
        // Continue rendering to the original frame buffer (likely 0, the onscreen buffer).
392
        OVR::CAPI::GL::glBindFramebuffer(GL_FRAMEBUFFER_EXT, oldfb);
393
        Q_ASSERT(!glGetError());
394
#endif
395

396
        //camera[eye]->position.setValue(originalPosition);
397

398
    }
399

400
    // Submit the texture for distortion.
401
    ovrHmd_EndFrame(hmd, eyePose, eyeTexture);
402

403
    // Swap buffers.
404
    glDisable(GL_CULL_FACE);
405
    glDisable(GL_DEPTH_TEST);
406
    //ovrHmd_EndFrame(hmd);
407
    glEnable(GL_CULL_FACE);
408
    glEnable(GL_DEPTH_TEST);
409
    glClearDepth(1.0);
410

411
    doneCurrent();
412
}
413

414
void CoinRiftWidget::handlingSafetyWarning(void)
415
{
416
    // Health and Safety Warning display state.
417
    ovrHSWDisplayState hswDisplayState;
418
    ovrHmd_GetHSWDisplayState(hmd, &hswDisplayState);
419
    if (hswDisplayState.Displayed)
420
    {
421
        // Dismiss the warning if the user pressed the appropriate key or if the user
422
        // is tapping the side of the HMD.
423
        // If the user has requested to dismiss the warning via keyboard or controller input...
424
        //if (Util_GetAndResetHSWDismissedState())
425
            ovrHmd_DismissHSWDisplay(hmd);
426
        //else
427
        //{
428
        //    // Detect a moderate tap on the side of the HMD.
429
        //    ovrTrackingState ts = ovrHmd_GetTrackingState(hmd, ovr_GetTimeInSeconds());
430
        //    if (ts.StatusFlags & ovrStatus_OrientationTracked)
431
        //    {
432
        //        const OVR::Vector3f v(ts.RawSensorData.Accelerometer.x,
433
        //                              ts.RawSensorData.Accelerometer.y,
434
        //                              ts.RawSensorData.Accelerometer.z);
435
        //        // Arbitrary value and representing moderate tap on the side of the DK2 Rift.
436
        //        if (v.LengthSq() > 250.f)
437
        //            ovrHmd_DismissHSWDisplay(hmd);
438
        //    }
439
        //}
440
    }
441

442
}
443

444

445
#ifdef BUILD_RIFT_TEST_MAIN
446

447
int main(int argc, char *argv[])
448
{
449
    SoDB::init();
450

451
    QApplication app(argc, argv);
452
    qAddPostRoutine(cleanup);
453

454
    // Moved here because of https://developer.oculusvr.com/forums/viewtopic.php?f=17&t=7915&p=108503#p108503
455
    // Init libovr.
456
    if (!ovr_Initialize()) {
457
        qDebug() << "Could not initialize Oculus SDK.";
458
        exit(1);
459
    }
460

461
    CoinRiftWidget window;
462
    window.show();
463

464
    // An example scene.
465
    static const char * inlineSceneGraph[] = {
466
        "#Inventor V2.1 ascii\n",
467
        "\n",
468
        "Separator {\n",
469
        "  Rotation { rotation 1 0 0  0.3 }\n",
470
        "  Cone { }\n",
471
        "  BaseColor { rgb 1 0 0 }\n",
472
        "  Scale { scaleFactor .7 .7 .7 }\n",
473
        "  Cube { }\n",
474
        "\n",
475
        "  DrawStyle { style LINES }\n",
476
        "  ShapeHints { vertexOrdering COUNTERCLOCKWISE }\n",
477
        "  Coordinate3 {\n",
478
        "    point [\n",
479
        "       -2 -2 1.1,  -2 -1 1.1,  -2  1 1.1,  -2  2 1.1,\n",
480
        "       -1 -2 1.1,  -1 -1 1.1,  -1  1 1.1,  -1  2 1.1\n",
481
        "        1 -2 1.1,   1 -1 1.1,   1  1 1.1,   1  2 1.1\n",
482
        "        2 -2 1.1,   2 -1 1.1,   2  1 1.1,   2  2 1.1\n",
483
        "      ]\n",
484
        "  }\n",
485
        "\n",
486
        "  Complexity { value 0.7 }\n",
487
        "  NurbsSurface {\n",
488
        "     numUControlPoints 4\n",
489
        "     numVControlPoints 4\n",
490
        "     uKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n",
491
        "     vKnotVector [ 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 ]\n",
492
        "  }\n",
493
        "}\n",
494
        NULL
495
    };
496

497
    SoInput in;
498
    in.setStringArray(inlineSceneGraph);
499

500
    window.setSceneGraph(SoDB::readAll(&in));
501

502
    return app.exec();
503
}
504

505
#endif //BUILD_RIFT_TEST_MAIN
506

507
#endif //BUILD_VR
508

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.