2013-01-29 23:54:18 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2013-01-29 23:54:18 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
|
|
// with the following modification; you may not use this file except in
|
|
|
|
// compliance with the Apache License and the following modification to it:
|
|
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
2013-01-29 23:54:18 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
|
|
// the License and to reproduce the content of the NOTICE file.
|
2013-01-29 23:54:18 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2013-01-29 23:54:18 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the Apache License with the above modification is
|
|
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
|
|
// language governing permissions and limitations under the Apache License.
|
2013-01-29 23:54:18 +00:00
|
|
|
//
|
|
|
|
|
2015-05-30 05:33:51 +00:00
|
|
|
#include "../common/glUtils.h"
|
2013-01-31 23:34:35 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
#include <GLFW/glfw3.h>
|
|
|
|
GLFWwindow* g_window=0;
|
|
|
|
GLFWmonitor* g_primary=0;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-12-04 01:19:07 +00:00
|
|
|
#include <far/error.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/cpuEvaluator.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
#include <osd/cpuGLVertexBuffer.h>
|
|
|
|
|
|
|
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/ompEvaluator.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
|
2013-08-16 17:51:51 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_TBB
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/tbbEvaluator.h>
|
2013-02-02 20:53:33 +00:00
|
|
|
#endif
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_OPENCL
|
|
|
|
#include <osd/clGLVertexBuffer.h>
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/clEvaluator.h>
|
2015-04-28 22:46:37 +00:00
|
|
|
#include "../common/clDeviceContext.h"
|
2015-04-27 18:27:05 +00:00
|
|
|
|
2015-04-28 22:46:37 +00:00
|
|
|
CLDeviceContext g_clDeviceContext;
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef OPENSUBDIV_HAS_CUDA
|
|
|
|
#include <osd/cudaGLVertexBuffer.h>
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/cudaEvaluator.h>
|
2015-04-28 22:46:37 +00:00
|
|
|
#include "../common/cudaDeviceContext.h"
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-04-28 22:46:37 +00:00
|
|
|
CudaDeviceContext g_cudaDeviceContext;
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/glXFBEvaluator.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
#include <osd/glVertexBuffer.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
2015-05-09 00:31:26 +00:00
|
|
|
#include <osd/glComputeEvaluator.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
#include <osd/glVertexBuffer.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <osd/glMesh.h>
|
2015-05-20 21:36:57 +00:00
|
|
|
#include <osd/glLegacyGregoryPatchTable.h>
|
|
|
|
OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL;
|
|
|
|
OpenSubdiv::Osd::GLLegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-31 05:10:07 +00:00
|
|
|
#include "../../regression/common/far_utils.h"
|
2015-05-19 01:04:38 +00:00
|
|
|
#include "../common/glHud.h"
|
2015-05-31 22:08:37 +00:00
|
|
|
#include "../common/glUtils.h"
|
|
|
|
#include "../common/glControlMeshDisplay.h"
|
|
|
|
#include "../common/glShaderCache.h"
|
2014-09-05 22:07:46 +00:00
|
|
|
#include "../common/objAnim.h"
|
2015-05-31 22:08:37 +00:00
|
|
|
#include "../common/simple_math.h"
|
|
|
|
#include "../common/stopwatch.h"
|
2015-05-14 00:35:46 +00:00
|
|
|
#include <osd/glslPatchShaderSource.h>
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-04-12 20:35:18 +00:00
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
|
2015-04-12 20:35:18 +00:00
|
|
|
/* Function to get the correct shader file based on the opengl version.
|
|
|
|
The implentation varies depending if glew is available or not. In case
|
|
|
|
is available the capabilities are queried during execution and the correct
|
|
|
|
source is returned. If glew in not available during compile time the version
|
|
|
|
is determined*/
|
|
|
|
static const char *shaderSource(){
|
2016-02-19 20:57:56 +00:00
|
|
|
#if ! defined(OSD_USES_GLEW)
|
2015-05-22 01:47:36 +00:00
|
|
|
|
|
|
|
static const char *res =
|
2013-01-29 23:54:18 +00:00
|
|
|
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
|
2015-04-12 20:35:18 +00:00
|
|
|
#include "shader.gen.h"
|
2013-01-29 23:54:18 +00:00
|
|
|
#else
|
2015-04-12 20:35:18 +00:00
|
|
|
#include "shader_gl3.gen.h"
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
2015-05-27 00:48:14 +00:00
|
|
|
;
|
2015-04-12 20:35:18 +00:00
|
|
|
#else
|
2015-05-29 22:56:36 +00:00
|
|
|
static const char *res = NULL;
|
|
|
|
if (!res){
|
|
|
|
static const char *gen =
|
2015-04-12 20:35:18 +00:00
|
|
|
#include "shader.gen.h"
|
2015-05-29 22:56:36 +00:00
|
|
|
;
|
|
|
|
static const char *gen3 =
|
2015-04-12 20:35:18 +00:00
|
|
|
#include "shader_gl3.gen.h"
|
2015-05-29 22:56:36 +00:00
|
|
|
;
|
|
|
|
//Determine the shader file to use. Since some opengl implementations
|
|
|
|
//define that an extension is available but not an implementation
|
|
|
|
//for it you cannnot trust in the glew header definitions to know that is
|
|
|
|
//available, but you need to query it during runtime.
|
|
|
|
if (GLUtils::SupportsAdaptiveTessellation())
|
|
|
|
res = gen;
|
|
|
|
else
|
|
|
|
res = gen3;
|
|
|
|
}
|
2015-05-22 01:47:36 +00:00
|
|
|
#endif
|
2015-05-29 22:56:36 +00:00
|
|
|
return res;
|
2015-04-12 20:35:18 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
#include <cfloat>
|
|
|
|
#include <vector>
|
2014-09-05 22:07:46 +00:00
|
|
|
#include <iostream>
|
2013-01-29 23:54:18 +00:00
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
enum KernelType { kCPU = 0,
|
|
|
|
kOPENMP = 1,
|
2013-08-16 17:51:51 +00:00
|
|
|
kTBB = 2,
|
2014-09-05 22:07:46 +00:00
|
|
|
kCUDA = 3,
|
|
|
|
kCL = 4,
|
|
|
|
kGLSL = 5,
|
|
|
|
kGLSLCompute = 6 };
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
enum DisplayStyle { kDisplayStyleWire,
|
|
|
|
kDisplayStyleShaded,
|
|
|
|
kDisplayStyleWireOnShaded };
|
|
|
|
|
|
|
|
enum ShadingMode { kShadingMaterial,
|
|
|
|
kShadingVaryingColor,
|
|
|
|
kShadingInterleavedVaryingColor,
|
|
|
|
kShadingFaceVaryingColor,
|
|
|
|
kShadingPatchType,
|
|
|
|
kShadingPatchCoord,
|
2015-06-04 00:40:36 +00:00
|
|
|
kShadingNormal };
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2015-04-18 00:36:55 +00:00
|
|
|
enum EndCap { kEndCapNone = 0,
|
2015-04-23 23:58:45 +00:00
|
|
|
kEndCapBSplineBasis,
|
2015-04-18 00:36:55 +00:00
|
|
|
kEndCapGregoryBasis,
|
|
|
|
kEndCapLegacyGregory };
|
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
enum HudCheckBox { kHUD_CB_DISPLAY_CONTROL_MESH_EDGES,
|
|
|
|
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS,
|
2013-06-27 19:57:21 +00:00
|
|
|
kHUD_CB_ANIMATE_VERTICES,
|
|
|
|
kHUD_CB_DISPLAY_PATCH_COLOR,
|
|
|
|
kHUD_CB_VIEW_LOD,
|
2013-06-27 20:34:25 +00:00
|
|
|
kHUD_CB_FRACTIONAL_SPACING,
|
2013-06-27 19:57:21 +00:00
|
|
|
kHUD_CB_PATCH_CULL,
|
2014-10-13 15:52:09 +00:00
|
|
|
kHUD_CB_FREEZE,
|
2015-04-18 00:36:55 +00:00
|
|
|
kHUD_CB_DISPLAY_PATCH_COUNTS,
|
|
|
|
kHUD_CB_ADAPTIVE,
|
2016-09-30 18:00:31 +00:00
|
|
|
kHUD_CB_SINGLE_CREASE_PATCH,
|
|
|
|
kHUD_CB_INF_SHARP_PATCH };
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2014-10-13 18:27:43 +00:00
|
|
|
int g_currentShape = 0;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ObjAnim const * g_objAnim = 0;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
bool g_axis=true;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
int g_frame = 0,
|
|
|
|
g_repeatCount = 0;
|
2014-09-05 22:07:46 +00:00
|
|
|
float g_animTime = 0;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// GUI variables
|
|
|
|
int g_fullscreen = 0,
|
|
|
|
g_freeze = 0,
|
2015-06-01 18:13:54 +00:00
|
|
|
g_shadingMode = kShadingPatchType,
|
|
|
|
g_displayStyle = kDisplayStyleWireOnShaded,
|
2014-10-13 15:52:09 +00:00
|
|
|
g_adaptive = 1,
|
2015-04-23 23:58:45 +00:00
|
|
|
g_endCap = kEndCapBSplineBasis,
|
2014-10-13 15:52:09 +00:00
|
|
|
g_singleCreasePatch = 1,
|
2016-09-30 18:00:31 +00:00
|
|
|
g_infSharpPatch = 0,
|
2013-08-16 17:51:51 +00:00
|
|
|
g_mbutton[3] = {0, 0, 0},
|
2013-01-29 23:54:18 +00:00
|
|
|
g_running = 1;
|
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
int g_screenSpaceTess = 1,
|
2014-10-13 15:52:09 +00:00
|
|
|
g_fractionalSpacing = 1,
|
|
|
|
g_patchCull = 0,
|
2015-04-17 23:26:57 +00:00
|
|
|
g_displayPatchCounts = 1;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
float g_rotate[2] = {0, 0},
|
|
|
|
g_dolly = 5,
|
|
|
|
g_pan[2] = {0, 0},
|
|
|
|
g_center[3] = {0, 0, 0},
|
|
|
|
g_size = 0;
|
|
|
|
|
|
|
|
int g_prev_x = 0,
|
|
|
|
g_prev_y = 0;
|
|
|
|
|
|
|
|
int g_width = 1024,
|
|
|
|
g_height = 1024;
|
|
|
|
|
|
|
|
GLhud g_hud;
|
2015-05-31 22:08:37 +00:00
|
|
|
GLControlMeshDisplay g_controlMeshDisplay;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// performance
|
|
|
|
float g_cpuTime = 0;
|
|
|
|
float g_gpuTime = 0;
|
|
|
|
Stopwatch g_fpsTimer;
|
|
|
|
|
|
|
|
// geometry
|
2015-05-31 22:08:37 +00:00
|
|
|
std::vector<float> g_orgPositions;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
int g_level = 2;
|
|
|
|
int g_tessLevel = 1;
|
|
|
|
int g_tessLevelMin = 1;
|
|
|
|
int g_kernel = kCPU;
|
|
|
|
float g_moveScale = 0.0f;
|
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
GLuint g_queries[2] = {0, 0};
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
GLuint g_transformUB = 0,
|
|
|
|
g_transformBinding = 0,
|
|
|
|
g_tessellationUB = 0,
|
2015-06-01 18:22:32 +00:00
|
|
|
g_tessellationBinding = 1,
|
2013-01-29 23:54:18 +00:00
|
|
|
g_lightingUB = 0,
|
2015-06-01 18:22:32 +00:00
|
|
|
g_lightingBinding = 2;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
struct Transform {
|
|
|
|
float ModelViewMatrix[16];
|
|
|
|
float ProjectionMatrix[16];
|
|
|
|
float ModelViewProjectionMatrix[16];
|
2015-06-01 18:13:54 +00:00
|
|
|
float ModelViewInverseMatrix[16];
|
2013-01-29 23:54:18 +00:00
|
|
|
} g_transformData;
|
|
|
|
|
|
|
|
GLuint g_vao = 0;
|
2015-04-12 19:28:05 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
// XXX:
|
|
|
|
// this struct meant to be used as a stopgap entity until we fully implement
|
|
|
|
// face-varying stuffs into patch table.
|
|
|
|
//
|
|
|
|
struct FVarData
|
|
|
|
{
|
|
|
|
FVarData() :
|
|
|
|
textureBuffer(0) {
|
|
|
|
}
|
|
|
|
~FVarData() {
|
|
|
|
Release();
|
|
|
|
}
|
|
|
|
void Release() {
|
|
|
|
if (textureBuffer)
|
|
|
|
glDeleteTextures(1, &textureBuffer);
|
|
|
|
textureBuffer = 0;
|
|
|
|
}
|
2015-05-22 18:50:01 +00:00
|
|
|
void Create(OpenSubdiv::Far::PatchTable const *patchTable,
|
2015-05-20 21:36:57 +00:00
|
|
|
int fvarWidth, std::vector<float> const & fvarSrcData) {
|
|
|
|
Release();
|
2015-06-02 20:51:32 +00:00
|
|
|
OpenSubdiv::Far::ConstIndexArray indices = patchTable->GetFVarValues();
|
2015-05-20 21:36:57 +00:00
|
|
|
|
|
|
|
// expand fvardata to per-patch array
|
|
|
|
std::vector<float> data;
|
|
|
|
data.reserve(indices.size() * fvarWidth);
|
|
|
|
|
|
|
|
for (int fvert = 0; fvert < (int)indices.size(); ++fvert) {
|
|
|
|
int index = indices[fvert] * fvarWidth;
|
|
|
|
for (int i = 0; i < fvarWidth; ++i) {
|
|
|
|
data.push_back(fvarSrcData[index++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GLuint buffer;
|
|
|
|
glGenBuffers(1, &buffer);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, data.size()*sizeof(float),
|
|
|
|
&data[0], GL_STATIC_DRAW);
|
|
|
|
|
2015-05-27 22:23:26 +00:00
|
|
|
glGenTextures(1, &textureBuffer);
|
2015-05-20 21:36:57 +00:00
|
|
|
glBindTexture(GL_TEXTURE_BUFFER, textureBuffer);
|
|
|
|
glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER, 0);
|
2015-06-01 03:13:21 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2015-05-20 21:36:57 +00:00
|
|
|
|
|
|
|
glDeleteBuffers(1, &buffer);
|
|
|
|
}
|
|
|
|
GLuint textureBuffer;
|
|
|
|
} g_fvarData;
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
#include "init_shapes.h"
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-09-05 22:07:46 +00:00
|
|
|
updateGeom() {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
std::vector<float> vertex, varying;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
int nverts = 0;
|
|
|
|
int stride = (g_shadingMode == kShadingInterleavedVaryingColor ? 7 : 3);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (g_objAnim && g_currentShape==0) {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
nverts = g_objAnim->GetShape()->GetNumVertices(),
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-12-05 18:50:09 +00:00
|
|
|
vertex.resize(nverts*stride);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor) {
|
2014-12-05 18:50:09 +00:00
|
|
|
varying.resize(nverts*4);
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
g_objAnim->InterpolatePositions(g_animTime, &vertex[0], stride);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor ||
|
2015-06-01 18:13:54 +00:00
|
|
|
g_shadingMode == kShadingInterleavedVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
const float *p = &g_objAnim->GetShape()->verts[0];
|
|
|
|
for (int i = 0; i < nverts; ++i) {
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingInterleavedVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
int ofs = i * stride;
|
|
|
|
vertex[ofs + 0] = p[1];
|
|
|
|
vertex[ofs + 1] = p[2];
|
|
|
|
vertex[ofs + 2] = p[0];
|
|
|
|
vertex[ofs + 3] = 0.0f;
|
|
|
|
p += 3;
|
|
|
|
}
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
varying.push_back(p[2]);
|
|
|
|
varying.push_back(p[1]);
|
|
|
|
varying.push_back(p[0]);
|
|
|
|
varying.push_back(1);
|
|
|
|
p += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2014-05-09 00:21:24 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
nverts = (int)g_orgPositions.size() / 3;
|
2014-05-09 00:21:24 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
vertex.reserve(nverts*stride);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
varying.reserve(nverts*4);
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
const float *p = &g_orgPositions[0];
|
|
|
|
float r = sin(g_frame*0.001f) * g_moveScale;
|
|
|
|
for (int i = 0; i < nverts; ++i) {
|
|
|
|
float ct = cos(p[2] * r);
|
|
|
|
float st = sin(p[2] * r);
|
2015-05-31 22:08:37 +00:00
|
|
|
vertex.push_back( p[0]*ct + p[1]*st);
|
|
|
|
vertex.push_back(-p[0]*st + p[1]*ct);
|
|
|
|
vertex.push_back( p[2]);
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingInterleavedVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
vertex.push_back(p[1]);
|
|
|
|
vertex.push_back(p[2]);
|
|
|
|
vertex.push_back(p[0]);
|
|
|
|
vertex.push_back(1.0f);
|
2015-06-01 18:13:54 +00:00
|
|
|
} else if (g_shadingMode == kShadingVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
varying.push_back(p[2]);
|
|
|
|
varying.push_back(p[1]);
|
|
|
|
varying.push_back(p[0]);
|
|
|
|
varying.push_back(1);
|
|
|
|
}
|
2015-05-31 22:08:37 +00:00
|
|
|
p += 3;
|
2013-06-27 19:57:21 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
g_mesh->UpdateVertexBuffer(&vertex[0], 0, nverts);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor)
|
2013-06-27 19:57:21 +00:00
|
|
|
g_mesh->UpdateVaryingBuffer(&varying[0], 0, nverts);
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
Stopwatch s;
|
|
|
|
s.Start();
|
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
g_mesh->Refine();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
s.Stop();
|
|
|
|
g_cpuTime = float(s.GetElapsed() * 1000.0f);
|
|
|
|
s.Start();
|
|
|
|
|
|
|
|
g_mesh->Synchronize();
|
|
|
|
|
|
|
|
s.Stop();
|
|
|
|
g_gpuTime = float(s.GetElapsed() * 1000.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static const char *
|
|
|
|
getKernelName(int kernel) {
|
|
|
|
|
|
|
|
if (kernel == kCPU)
|
|
|
|
return "CPU";
|
|
|
|
else if (kernel == kOPENMP)
|
|
|
|
return "OpenMP";
|
2013-08-16 17:51:51 +00:00
|
|
|
else if (kernel == kTBB)
|
|
|
|
return "TBB";
|
2013-01-29 23:54:18 +00:00
|
|
|
else if (kernel == kCUDA)
|
|
|
|
return "Cuda";
|
|
|
|
else if (kernel == kGLSL)
|
|
|
|
return "GLSL TransformFeedback";
|
|
|
|
else if (kernel == kGLSLCompute)
|
|
|
|
return "GLSL Compute";
|
|
|
|
else if (kernel == kCL)
|
|
|
|
return "OpenCL";
|
|
|
|
return "Unknown";
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh() {
|
2015-05-09 00:31:26 +00:00
|
|
|
using namespace OpenSubdiv;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
ShapeDesc const &shapeDesc = g_defaultShapes[g_currentShape];
|
|
|
|
int level = g_level;
|
|
|
|
int kernel = g_kernel;
|
2016-02-19 20:57:56 +00:00
|
|
|
bool doAnim = g_objAnim && g_currentShape==0;
|
2015-05-31 22:08:37 +00:00
|
|
|
Scheme scheme = shapeDesc.scheme;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
Shape const * shape = 0;
|
|
|
|
if (doAnim) {
|
|
|
|
shape = g_objAnim->GetShape();
|
|
|
|
} else {
|
2015-05-31 22:08:37 +00:00
|
|
|
shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme,
|
|
|
|
shapeDesc.isLeftHanded);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2015-05-31 05:10:07 +00:00
|
|
|
// create Far mesh (topology)
|
2015-05-09 00:31:26 +00:00
|
|
|
Sdc::SchemeType sdctype = GetSdcType(*shape);
|
|
|
|
Sdc::Options sdcoptions = GetSdcOptions(*shape);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
Far::TopologyRefiner * refiner =
|
|
|
|
Far::TopologyRefinerFactory<Shape>::Create(*shape,
|
|
|
|
Far::TopologyRefinerFactory<Shape>::Options(sdctype, sdcoptions));
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// save coarse topology (used for coarse mesh drawing)
|
2015-05-31 22:08:37 +00:00
|
|
|
g_controlMeshDisplay.SetTopology(refiner->GetLevel(0));
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
g_orgPositions = shape->verts;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
delete g_mesh;
|
|
|
|
g_mesh = NULL;
|
|
|
|
|
|
|
|
// Adaptive refinement currently supported only for catmull-clark scheme
|
2016-02-19 20:57:56 +00:00
|
|
|
bool doAdaptive = (g_adaptive!=0 && scheme==kCatmark);
|
2015-06-01 18:13:54 +00:00
|
|
|
bool interleaveVarying = g_shadingMode == kShadingInterleavedVaryingColor;
|
2016-02-19 20:57:56 +00:00
|
|
|
bool doSingleCreasePatch = (g_singleCreasePatch!=0 && scheme==kCatmark);
|
2016-09-30 18:00:31 +00:00
|
|
|
bool doInfSharpPatch = (g_infSharpPatch!=0 && scheme==kCatmark);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::MeshBitset bits;
|
|
|
|
bits.set(Osd::MeshAdaptive, doAdaptive);
|
|
|
|
bits.set(Osd::MeshUseSingleCreasePatch, doSingleCreasePatch);
|
2016-09-30 18:00:31 +00:00
|
|
|
bits.set(Osd::MeshUseInfSharpPatch, doInfSharpPatch);
|
2015-05-09 00:31:26 +00:00
|
|
|
bits.set(Osd::MeshInterleaveVarying, interleaveVarying);
|
2015-06-01 18:13:54 +00:00
|
|
|
bits.set(Osd::MeshFVarData, g_shadingMode == kShadingFaceVaryingColor);
|
2015-05-09 00:31:26 +00:00
|
|
|
bits.set(Osd::MeshEndCapBSplineBasis, g_endCap == kEndCapBSplineBasis);
|
|
|
|
bits.set(Osd::MeshEndCapGregoryBasis, g_endCap == kEndCapGregoryBasis);
|
|
|
|
bits.set(Osd::MeshEndCapLegacyGregory, g_endCap == kEndCapLegacyGregory);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
int numVertexElements = 3;
|
|
|
|
int numVaryingElements =
|
2016-02-19 20:57:56 +00:00
|
|
|
(g_shadingMode == kShadingVaryingColor || interleaveVarying) ? 4 : 0;
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
if (kernel == kCPU) {
|
2015-05-09 00:31:26 +00:00
|
|
|
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::CpuEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits);
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
|
|
|
} else if (kernel == kOPENMP) {
|
2015-05-09 00:31:26 +00:00
|
|
|
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::OmpEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
2013-08-16 17:51:51 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_TBB
|
|
|
|
} else if (kernel == kTBB) {
|
2015-05-09 00:31:26 +00:00
|
|
|
g_mesh = new Osd::Mesh<Osd::CpuGLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Far::StencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::TbbEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits);
|
2013-02-02 20:53:33 +00:00
|
|
|
#endif
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_OPENCL
|
|
|
|
} else if(kernel == kCL) {
|
2015-05-09 00:31:26 +00:00
|
|
|
// CLKernel
|
|
|
|
static Osd::EvaluatorCacheT<Osd::CLEvaluator> clEvaluatorCache;
|
|
|
|
g_mesh = new Osd::Mesh<Osd::CLGLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Osd::CLStencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::CLEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
CLDeviceContext>(
|
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits,
|
|
|
|
&clEvaluatorCache,
|
|
|
|
&g_clDeviceContext);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_CUDA
|
|
|
|
} else if(kernel == kCUDA) {
|
2015-05-09 00:31:26 +00:00
|
|
|
g_mesh = new Osd::Mesh<Osd::CudaGLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Osd::CudaStencilTable,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::CudaEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
|
|
|
} else if(kernel == kGLSL) {
|
2015-05-09 00:31:26 +00:00
|
|
|
static Osd::EvaluatorCacheT<Osd::GLXFBEvaluator> glXFBEvaluatorCache;
|
|
|
|
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Osd::GLStencilTableTBO,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::GLXFBEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits,
|
|
|
|
&glXFBEvaluatorCache);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
|
|
|
} else if(kernel == kGLSLCompute) {
|
2015-05-09 00:31:26 +00:00
|
|
|
static Osd::EvaluatorCacheT<Osd::GLComputeEvaluator> glComputeEvaluatorCache;
|
|
|
|
g_mesh = new Osd::Mesh<Osd::GLVertexBuffer,
|
2015-05-22 18:50:01 +00:00
|
|
|
Osd::GLStencilTableSSBO,
|
2015-05-09 00:31:26 +00:00
|
|
|
Osd::GLComputeEvaluator,
|
2015-05-20 21:36:57 +00:00
|
|
|
Osd::GLPatchTable>(
|
2015-05-09 00:31:26 +00:00
|
|
|
refiner,
|
|
|
|
numVertexElements,
|
|
|
|
numVaryingElements,
|
|
|
|
level, bits,
|
|
|
|
&glComputeEvaluatorCache);
|
|
|
|
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
} else {
|
|
|
|
printf("Unsupported kernel %s\n", getKernelName(kernel));
|
|
|
|
}
|
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (g_shadingMode == kShadingFaceVaryingColor && shape->HasUV()) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
std::vector<float> fvarData;
|
|
|
|
|
|
|
|
InterpolateFVarData(*refiner, *shape, fvarData);
|
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
// set fvardata to texture buffer
|
2015-05-22 18:50:01 +00:00
|
|
|
g_fvarData.Create(g_mesh->GetFarPatchTable(),
|
2015-05-20 21:36:57 +00:00
|
|
|
shape->GetFVarWidth(), fvarData);
|
|
|
|
}
|
|
|
|
|
|
|
|
// legacy gregory
|
|
|
|
delete g_legacyGregoryPatchTable;
|
|
|
|
g_legacyGregoryPatchTable = NULL;
|
|
|
|
if (g_endCap == kEndCapLegacyGregory) {
|
|
|
|
g_legacyGregoryPatchTable =
|
2015-05-22 18:50:01 +00:00
|
|
|
Osd::GLLegacyGregoryPatchTable::Create(g_mesh->GetFarPatchTable());
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! doAnim) {
|
2014-09-05 22:07:46 +00:00
|
|
|
delete shape;
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// compute model bounding
|
|
|
|
float min[3] = { FLT_MAX, FLT_MAX, FLT_MAX};
|
|
|
|
float max[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
|
|
|
|
for (size_t i=0; i <g_orgPositions.size()/3; ++i) {
|
|
|
|
for(int j=0; j<3; ++j) {
|
|
|
|
float v = g_orgPositions[i*3+j];
|
|
|
|
min[j] = std::min(min[j], v);
|
|
|
|
max[j] = std::max(max[j], v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j=0; j<3; ++j) {
|
|
|
|
g_center[j] = (min[j] + max[j]) * 0.5f;
|
|
|
|
g_size += (max[j]-min[j])*(max[j]-min[j]);
|
|
|
|
}
|
|
|
|
g_size = sqrtf(g_size);
|
|
|
|
|
|
|
|
g_tessLevelMin = 1;
|
|
|
|
|
|
|
|
g_tessLevel = std::max(g_tessLevel,g_tessLevelMin);
|
|
|
|
|
|
|
|
updateGeom();
|
|
|
|
|
2013-08-16 17:51:51 +00:00
|
|
|
// -------- VAO
|
2013-01-29 23:54:18 +00:00
|
|
|
glBindVertexArray(g_vao);
|
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_mesh->GetPatchTable()->GetPatchIndexBuffer());
|
2013-01-29 23:54:18 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, g_mesh->BindVertexBuffer());
|
|
|
|
|
|
|
|
glEnableVertexAttribArray(0);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 3, 0);
|
2013-06-27 19:57:21 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, g_mesh->BindVaryingBuffer());
|
|
|
|
glEnableVertexAttribArray(1);
|
2014-05-09 00:21:24 +00:00
|
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 4, 0);
|
2015-06-01 18:13:54 +00:00
|
|
|
} else if (g_shadingMode == kShadingInterleavedVaryingColor) {
|
2014-09-05 22:07:46 +00:00
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 7, 0);
|
2014-05-09 00:21:24 +00:00
|
|
|
glEnableVertexAttribArray(1);
|
2014-09-05 22:07:46 +00:00
|
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 7, (void*)(sizeof (GLfloat) * 3));
|
2013-06-27 19:57:21 +00:00
|
|
|
} else {
|
2014-09-05 22:07:46 +00:00
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 3, 0);
|
2013-06-27 19:57:21 +00:00
|
|
|
glDisableVertexAttribArray(1);
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2013-06-27 19:57:21 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2013-01-29 23:54:18 +00:00
|
|
|
glBindVertexArray(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
|
|
|
fitFrame() {
|
|
|
|
|
|
|
|
g_pan[0] = g_pan[1] = 0;
|
|
|
|
g_dolly = g_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
2013-06-27 19:57:21 +00:00
|
|
|
|
|
|
|
union Effect {
|
2015-06-01 18:13:54 +00:00
|
|
|
Effect(int displayStyle_, int shadingMode_, int screenSpaceTess_,
|
|
|
|
int fractionalSpacing_, int patchCull_, int singleCreasePatch_)
|
|
|
|
: value(0) {
|
2013-06-27 19:57:21 +00:00
|
|
|
displayStyle = displayStyle_;
|
2015-06-01 18:13:54 +00:00
|
|
|
shadingMode = shadingMode_;
|
2013-06-27 19:57:21 +00:00
|
|
|
screenSpaceTess = screenSpaceTess_;
|
2013-06-27 20:34:25 +00:00
|
|
|
fractionalSpacing = fractionalSpacing_;
|
2013-06-27 19:57:21 +00:00
|
|
|
patchCull = patchCull_;
|
2015-05-15 18:03:31 +00:00
|
|
|
singleCreasePatch = singleCreasePatch_;
|
2013-06-27 19:57:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct {
|
2015-06-01 18:13:54 +00:00
|
|
|
unsigned int displayStyle:2;
|
|
|
|
unsigned int shadingMode:4;
|
2013-07-02 18:16:27 +00:00
|
|
|
unsigned int screenSpaceTess:1;
|
|
|
|
unsigned int fractionalSpacing:1;
|
|
|
|
unsigned int patchCull:1;
|
2015-05-15 18:03:31 +00:00
|
|
|
unsigned int singleCreasePatch:1;
|
2013-06-27 19:57:21 +00:00
|
|
|
};
|
|
|
|
int value;
|
|
|
|
|
|
|
|
bool operator < (const Effect &e) const {
|
|
|
|
return value < e.value;
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
};
|
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
static Effect
|
|
|
|
GetEffect()
|
|
|
|
{
|
|
|
|
return Effect(g_displayStyle,
|
2015-06-01 18:13:54 +00:00
|
|
|
g_shadingMode,
|
2015-05-14 00:35:46 +00:00
|
|
|
g_screenSpaceTess,
|
|
|
|
g_fractionalSpacing,
|
2015-05-15 18:03:31 +00:00
|
|
|
g_patchCull,
|
|
|
|
g_singleCreasePatch);
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
2015-05-12 01:06:46 +00:00
|
|
|
struct EffectDesc {
|
|
|
|
EffectDesc(OpenSubdiv::Far::PatchDescriptor desc,
|
|
|
|
Effect effect) : desc(desc), effect(effect),
|
|
|
|
maxValence(0), numElements(0) { }
|
|
|
|
|
|
|
|
OpenSubdiv::Far::PatchDescriptor desc;
|
|
|
|
Effect effect;
|
|
|
|
int maxValence;
|
|
|
|
int numElements;
|
|
|
|
|
|
|
|
bool operator < (const EffectDesc &e) const {
|
2015-05-15 18:03:31 +00:00
|
|
|
return
|
|
|
|
(desc < e.desc || ((desc == e.desc &&
|
|
|
|
(maxValence < e.maxValence || ((maxValence == e.maxValence) &&
|
|
|
|
(numElements < e.numElements || ((numElements == e.numElements) &&
|
|
|
|
(effect < e.effect))))))));
|
2015-05-12 01:06:46 +00:00
|
|
|
}
|
|
|
|
};
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// ---------------------------------------------------------------------------
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
class ShaderCache : public GLShaderCache<EffectDesc> {
|
|
|
|
public:
|
|
|
|
virtual GLDrawConfig *CreateDrawConfig(EffectDesc const &effectDesc) {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
using namespace OpenSubdiv;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// compile shader program
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-23 03:28:37 +00:00
|
|
|
GLDrawConfig *config = new GLDrawConfig(GLUtils::GetShaderVersionInclude().c_str());
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
Far::PatchDescriptor::Type type = effectDesc.desc.GetType();
|
2015-05-12 01:06:46 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// common defines
|
|
|
|
std::stringstream ss;
|
2015-05-12 01:06:46 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
if (type == Far::PatchDescriptor::QUADS) {
|
|
|
|
ss << "#define PRIM_QUAD\n";
|
|
|
|
} else {
|
|
|
|
ss << "#define PRIM_TRI\n";
|
|
|
|
}
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// OSD tessellation controls
|
|
|
|
if (effectDesc.effect.screenSpaceTess) {
|
|
|
|
ss << "#define OSD_ENABLE_SCREENSPACE_TESSELLATION\n";
|
|
|
|
}
|
|
|
|
if (effectDesc.effect.fractionalSpacing) {
|
|
|
|
ss << "#define OSD_FRACTIONAL_ODD_SPACING\n";
|
|
|
|
}
|
|
|
|
if (effectDesc.effect.patchCull) {
|
|
|
|
ss << "#define OSD_ENABLE_PATCH_CULL\n";
|
|
|
|
}
|
2015-05-15 18:03:31 +00:00
|
|
|
if (effectDesc.effect.singleCreasePatch) {
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << "#define OSD_PATCH_ENABLE_SINGLE_CREASE\n";
|
|
|
|
}
|
|
|
|
// for legacy gregory
|
|
|
|
ss << "#define OSD_MAX_VALENCE " << effectDesc.maxValence << "\n";
|
|
|
|
ss << "#define OSD_NUM_ELEMENTS " << effectDesc.numElements << "\n";
|
|
|
|
|
|
|
|
// display styles
|
|
|
|
switch (effectDesc.effect.displayStyle) {
|
2015-06-01 18:13:54 +00:00
|
|
|
case kDisplayStyleWire:
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << "#define GEOMETRY_OUT_WIRE\n";
|
|
|
|
break;
|
2015-06-01 18:13:54 +00:00
|
|
|
case kDisplayStyleWireOnShaded:
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << "#define GEOMETRY_OUT_LINE\n";
|
|
|
|
break;
|
2015-06-01 18:13:54 +00:00
|
|
|
case kDisplayStyleShaded:
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << "#define GEOMETRY_OUT_FILL\n";
|
|
|
|
break;
|
2015-06-01 18:13:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// shading mode
|
|
|
|
switch(effectDesc.effect.shadingMode) {
|
|
|
|
case kShadingMaterial:
|
|
|
|
ss << "#define SHADING_MATERIAL\n";
|
2015-05-14 00:35:46 +00:00
|
|
|
break;
|
2015-06-01 18:13:54 +00:00
|
|
|
case kShadingVaryingColor:
|
|
|
|
ss << "#define SHADING_VARYING_COLOR\n";
|
|
|
|
break;
|
|
|
|
case kShadingInterleavedVaryingColor:
|
|
|
|
ss << "#define SHADING_VARYING_COLOR\n";
|
2015-05-14 00:35:46 +00:00
|
|
|
break;
|
2015-06-01 18:13:54 +00:00
|
|
|
case kShadingFaceVaryingColor:
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << "#define OSD_FVAR_WIDTH 2\n";
|
2015-06-01 18:13:54 +00:00
|
|
|
ss << "#define SHADING_FACEVARYING_COLOR\n";
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! effectDesc.desc.IsAdaptive()) {
|
2015-06-02 15:49:11 +00:00
|
|
|
ss << "#define SHADING_FACEVARYING_UNIFORM_SUBDIVISION\n";
|
|
|
|
}
|
2015-06-01 18:13:54 +00:00
|
|
|
break;
|
|
|
|
case kShadingPatchType:
|
|
|
|
ss << "#define SHADING_PATCH_TYPE\n";
|
|
|
|
break;
|
|
|
|
case kShadingPatchCoord:
|
|
|
|
ss << "#define SHADING_PATCH_COORD\n";
|
|
|
|
break;
|
|
|
|
case kShadingNormal:
|
|
|
|
ss << "#define SHADING_NORMAL\n";
|
|
|
|
break;
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
2015-06-01 18:13:54 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
if (type == Far::PatchDescriptor::TRIANGLES) {
|
|
|
|
ss << "#define LOOP\n";
|
2015-06-01 18:13:54 +00:00
|
|
|
} else if (type == Far::PatchDescriptor::QUADS) {
|
|
|
|
} else {
|
|
|
|
ss << "#define SMOOTH_NORMALS\n";
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
2013-06-27 19:57:21 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// need for patch color-coding : we need these defines in the fragment shader
|
|
|
|
if (type == Far::PatchDescriptor::GREGORY) {
|
|
|
|
ss << "#define OSD_PATCH_GREGORY\n";
|
|
|
|
} else if (type == Far::PatchDescriptor::GREGORY_BOUNDARY) {
|
|
|
|
ss << "#define OSD_PATCH_GREGORY_BOUNDARY\n";
|
|
|
|
} else if (type == Far::PatchDescriptor::GREGORY_BASIS) {
|
|
|
|
ss << "#define OSD_PATCH_GREGORY_BASIS\n";
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// include osd PatchCommon
|
2016-09-29 17:00:19 +00:00
|
|
|
ss << "#define OSD_PATCH_BASIS_GLSL\n";
|
|
|
|
ss << Osd::GLSLPatchShaderSource::GetPatchBasisShaderSource();
|
2015-05-14 00:35:46 +00:00
|
|
|
ss << Osd::GLSLPatchShaderSource::GetCommonShaderSource();
|
|
|
|
std::string common = ss.str();
|
|
|
|
ss.str("");
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// vertex shader
|
|
|
|
ss << common
|
|
|
|
// enable local vertex shader
|
|
|
|
<< (effectDesc.desc.IsAdaptive() ? "" : "#define VERTEX_SHADER\n")
|
2015-05-29 22:56:36 +00:00
|
|
|
<< shaderSource()
|
2015-05-14 00:35:46 +00:00
|
|
|
<< Osd::GLSLPatchShaderSource::GetVertexShaderSource(type);
|
|
|
|
config->CompileAndAttachShader(GL_VERTEX_SHADER, ss.str());
|
|
|
|
ss.str("");
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
if (effectDesc.desc.IsAdaptive()) {
|
|
|
|
// tess control shader
|
|
|
|
ss << common
|
2015-05-29 22:56:36 +00:00
|
|
|
<< shaderSource()
|
2015-05-14 00:35:46 +00:00
|
|
|
<< Osd::GLSLPatchShaderSource::GetTessControlShaderSource(type);
|
|
|
|
config->CompileAndAttachShader(GL_TESS_CONTROL_SHADER, ss.str());
|
|
|
|
ss.str("");
|
|
|
|
|
|
|
|
// tess eval shader
|
|
|
|
ss << common
|
2015-05-29 22:56:36 +00:00
|
|
|
<< shaderSource()
|
2015-05-14 00:35:46 +00:00
|
|
|
<< Osd::GLSLPatchShaderSource::GetTessEvalShaderSource(type);
|
|
|
|
config->CompileAndAttachShader(GL_TESS_EVALUATION_SHADER, ss.str());
|
|
|
|
ss.str("");
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// geometry shader
|
|
|
|
ss << common
|
|
|
|
<< "#define GEOMETRY_SHADER\n"
|
2015-05-22 01:47:36 +00:00
|
|
|
<< shaderSource();
|
2015-05-14 00:35:46 +00:00
|
|
|
config->CompileAndAttachShader(GL_GEOMETRY_SHADER, ss.str());
|
|
|
|
ss.str("");
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// fragment shader
|
|
|
|
ss << common
|
|
|
|
<< "#define FRAGMENT_SHADER\n"
|
2015-05-22 01:47:36 +00:00
|
|
|
<< shaderSource();
|
2015-05-14 00:35:46 +00:00
|
|
|
config->CompileAndAttachShader(GL_FRAGMENT_SHADER, ss.str());
|
|
|
|
ss.str("");
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
if (!config->Link()) {
|
|
|
|
delete config;
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-05-12 01:06:46 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// assign uniform locations
|
|
|
|
GLuint uboIndex;
|
|
|
|
GLuint program = config->GetProgram();
|
|
|
|
uboIndex = glGetUniformBlockIndex(program, "Transform");
|
|
|
|
if (uboIndex != GL_INVALID_INDEX)
|
|
|
|
glUniformBlockBinding(program, uboIndex, g_transformBinding);
|
|
|
|
|
|
|
|
uboIndex = glGetUniformBlockIndex(program, "Tessellation");
|
|
|
|
if (uboIndex != GL_INVALID_INDEX)
|
|
|
|
glUniformBlockBinding(program, uboIndex, g_tessellationBinding);
|
|
|
|
|
|
|
|
uboIndex = glGetUniformBlockIndex(program, "Lighting");
|
|
|
|
if (uboIndex != GL_INVALID_INDEX)
|
|
|
|
glUniformBlockBinding(program, uboIndex, g_lightingBinding);
|
|
|
|
|
|
|
|
// assign texture locations
|
|
|
|
GLint loc;
|
|
|
|
glUseProgram(program);
|
2015-05-20 21:36:57 +00:00
|
|
|
if ((loc = glGetUniformLocation(program, "OsdPatchParamBuffer")) != -1) {
|
2015-05-14 00:35:46 +00:00
|
|
|
glUniform1i(loc, 0); // GL_TEXTURE0
|
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
if ((loc = glGetUniformLocation(program, "OsdFVarDataBuffer")) != -1) {
|
2015-05-14 00:35:46 +00:00
|
|
|
glUniform1i(loc, 1); // GL_TEXTURE1
|
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
// for legacy gregory patches
|
|
|
|
if ((loc = glGetUniformLocation(program, "OsdVertexBuffer")) != -1) {
|
2015-05-14 00:35:46 +00:00
|
|
|
glUniform1i(loc, 2); // GL_TEXTURE2
|
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
if ((loc = glGetUniformLocation(program, "OsdValenceBuffer")) != -1) {
|
2015-05-14 00:35:46 +00:00
|
|
|
glUniform1i(loc, 3); // GL_TEXTURE3
|
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
if ((loc = glGetUniformLocation(program, "OsdQuadOffsetBuffer")) != -1) {
|
2015-05-14 00:35:46 +00:00
|
|
|
glUniform1i(loc, 4); // GL_TEXTURE4
|
|
|
|
}
|
|
|
|
glUseProgram(0);
|
2015-05-12 01:06:46 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
return config;
|
2015-05-12 01:06:46 +00:00
|
|
|
}
|
2015-05-14 00:35:46 +00:00
|
|
|
};
|
2015-05-12 01:06:46 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
ShaderCache g_shaderCache;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
|
|
|
updateUniformBlocks() {
|
2013-01-29 23:54:18 +00:00
|
|
|
if (! g_transformUB) {
|
|
|
|
glGenBuffers(1, &g_transformUB);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER,
|
|
|
|
sizeof(g_transformData), NULL, GL_STATIC_DRAW);
|
|
|
|
};
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_transformUB);
|
|
|
|
glBufferSubData(GL_UNIFORM_BUFFER,
|
|
|
|
0, sizeof(g_transformData), &g_transformData);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
|
|
|
|
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, g_transformBinding, g_transformUB);
|
|
|
|
|
|
|
|
// Update and bind tessellation state
|
|
|
|
struct Tessellation {
|
|
|
|
float TessLevel;
|
|
|
|
} tessellationData;
|
|
|
|
|
|
|
|
tessellationData.TessLevel = static_cast<float>(1 << g_tessLevel);
|
|
|
|
|
|
|
|
if (! g_tessellationUB) {
|
|
|
|
glGenBuffers(1, &g_tessellationUB);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB);
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER,
|
|
|
|
sizeof(tessellationData), NULL, GL_STATIC_DRAW);
|
|
|
|
};
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_tessellationUB);
|
|
|
|
glBufferSubData(GL_UNIFORM_BUFFER,
|
|
|
|
0, sizeof(tessellationData), &tessellationData);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
|
|
|
|
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, g_tessellationBinding, g_tessellationUB);
|
|
|
|
|
|
|
|
// Update and bind lighting state
|
|
|
|
struct Lighting {
|
|
|
|
struct Light {
|
|
|
|
float position[4];
|
|
|
|
float ambient[4];
|
|
|
|
float diffuse[4];
|
|
|
|
float specular[4];
|
|
|
|
} lightSource[2];
|
|
|
|
} lightingData = {
|
|
|
|
{{ { 0.5, 0.2f, 1.0f, 0.0f },
|
|
|
|
{ 0.1f, 0.1f, 0.1f, 1.0f },
|
|
|
|
{ 0.7f, 0.7f, 0.7f, 1.0f },
|
|
|
|
{ 0.8f, 0.8f, 0.8f, 1.0f } },
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
{ { -0.8f, 0.4f, -1.0f, 0.0f },
|
|
|
|
{ 0.0f, 0.0f, 0.0f, 1.0f },
|
|
|
|
{ 0.5f, 0.5f, 0.5f, 1.0f },
|
|
|
|
{ 0.8f, 0.8f, 0.8f, 1.0f } }}
|
|
|
|
};
|
|
|
|
if (! g_lightingUB) {
|
|
|
|
glGenBuffers(1, &g_lightingUB);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB);
|
|
|
|
glBufferData(GL_UNIFORM_BUFFER,
|
|
|
|
sizeof(lightingData), NULL, GL_STATIC_DRAW);
|
|
|
|
};
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, g_lightingUB);
|
|
|
|
glBufferSubData(GL_UNIFORM_BUFFER,
|
|
|
|
0, sizeof(lightingData), &lightingData);
|
|
|
|
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
|
|
|
|
|
|
glBindBufferBase(GL_UNIFORM_BUFFER, g_lightingBinding, g_lightingUB);
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
static void
|
|
|
|
bindTextures() {
|
|
|
|
// bind patch textures
|
2015-05-20 21:36:57 +00:00
|
|
|
if (g_mesh->GetPatchTable()->GetPatchParamTextureBuffer()) {
|
2013-01-29 23:54:18 +00:00
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER,
|
2015-05-20 21:36:57 +00:00
|
|
|
g_mesh->GetPatchTable()->GetPatchParamTextureBuffer());
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
|
|
|
|
if (true) {
|
2013-01-29 23:54:18 +00:00
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER,
|
2015-05-20 21:36:57 +00:00
|
|
|
g_fvarData.textureBuffer);
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
2015-05-20 21:36:57 +00:00
|
|
|
|
|
|
|
// legacy gregory
|
|
|
|
if (g_legacyGregoryPatchTable) {
|
2013-01-29 23:54:18 +00:00
|
|
|
glActiveTexture(GL_TEXTURE2);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER,
|
2015-05-20 21:36:57 +00:00
|
|
|
g_legacyGregoryPatchTable->GetVertexTextureBuffer());
|
2013-01-29 23:54:18 +00:00
|
|
|
glActiveTexture(GL_TEXTURE3);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER,
|
2015-05-20 21:36:57 +00:00
|
|
|
g_legacyGregoryPatchTable->GetVertexValenceTextureBuffer());
|
2013-07-02 18:16:27 +00:00
|
|
|
glActiveTexture(GL_TEXTURE4);
|
|
|
|
glBindTexture(GL_TEXTURE_BUFFER,
|
2015-05-20 21:36:57 +00:00
|
|
|
g_legacyGregoryPatchTable->GetQuadOffsetsTextureBuffer());
|
2013-07-02 18:16:27 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
glActiveTexture(GL_TEXTURE0);
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static GLenum
|
|
|
|
bindProgram(Effect effect,
|
Osd API refactor: EvalStencils and EvalPatches
Add EvalStencils and EvalPatches API for most of CPU and GPU evaluators.
with this change, Eval API in the osd layer consists of following parts:
- Evaluators (Cpu, Omp, Tbb, Cuda, CL, GLXFB, GLCompute, D3D11Compute)
implements EvalStencils and EvalPatches(*). Both supports derivatives
(not fully implemented though)
- Interop vertex buffer classes (optional, same as before)
Note that these classes are not necessary to use Evaluators.
All evaluators have EvalStencils/Patches which take device-specific
buffer objects. For example, GLXFBEvaluator can take GLuint directly
for both stencil tables and input primvars. Although using these
interop classes makes it easy to integrate osd into relatively
simple applications.
- device-dependent StencilTable and PatchTable (optional)
These are also optional, but can be used simply a substitute of
Far::StencilTable and Far::PatchTable for osd evaluators.
- PatchArray, PatchCoord, PatchParam
They are tiny structs used for GPU based patch evaluation.
(*) TODO and known issues:
- CLEvaluator and D3D11Evaluator's EvalPatches() have not been implemented.
- GPU Gregory patch evaluation has not been implemented in EvalPatches().
- CudaEvaluator::EvalPatches() is very unstable.
- All patch evaluation kernels have not been well optimized.
- Currently GLXFB kernel doesn't support derivative evaluation.
There's a technical difficulty for the multi-stream output.
2015-05-26 04:51:55 +00:00
|
|
|
OpenSubdiv::Osd::PatchArray const & patch) {
|
2015-05-14 00:35:46 +00:00
|
|
|
EffectDesc effectDesc(patch.GetDescriptor(), effect);
|
|
|
|
|
|
|
|
// only legacy gregory needs maxValence and numElements
|
2015-05-15 18:03:31 +00:00
|
|
|
// neither legacy gregory nor gregory basis need single crease
|
2015-05-14 00:35:46 +00:00
|
|
|
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
|
2016-02-19 20:57:56 +00:00
|
|
|
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY ||
|
2015-05-14 00:35:46 +00:00
|
|
|
patch.GetDescriptor().GetType() == Descriptor::GREGORY_BOUNDARY) {
|
2015-05-20 21:36:57 +00:00
|
|
|
int maxValence = g_mesh->GetMaxValence();
|
2015-06-01 18:13:54 +00:00
|
|
|
int numElements = (g_shadingMode == kShadingInterleavedVaryingColor ? 7 : 3);
|
2015-05-14 00:35:46 +00:00
|
|
|
effectDesc.maxValence = maxValence;
|
|
|
|
effectDesc.numElements = numElements;
|
2015-05-15 18:03:31 +00:00
|
|
|
effectDesc.effect.singleCreasePatch = 0;
|
|
|
|
}
|
|
|
|
if (patch.GetDescriptor().GetType() == Descriptor::GREGORY_BASIS) {
|
|
|
|
effectDesc.effect.singleCreasePatch = 0;
|
2015-05-14 00:35:46 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// lookup shader cache (compile the shader if needed)
|
|
|
|
GLDrawConfig *config = g_shaderCache.GetDrawConfig(effectDesc);
|
|
|
|
if (!config) return 0;
|
|
|
|
|
|
|
|
GLuint program = config->GetProgram();
|
|
|
|
|
|
|
|
glUseProgram(program);
|
|
|
|
|
|
|
|
// bind standalone uniforms
|
|
|
|
GLint uniformPrimitiveIdBase =
|
|
|
|
glGetUniformLocation(program, "PrimitiveIdBase");
|
|
|
|
if (uniformPrimitiveIdBase >=0)
|
2015-05-20 21:36:57 +00:00
|
|
|
glUniform1i(uniformPrimitiveIdBase, patch.GetPrimitiveIdBase());
|
|
|
|
|
|
|
|
// legacy gregory
|
|
|
|
if (g_endCap == kEndCapLegacyGregory) {
|
|
|
|
GLint uniformGregoryQuadOffsetBase =
|
|
|
|
glGetUniformLocation(program, "GregoryQuadOffsetBase");
|
|
|
|
int quadOffsetBase =
|
|
|
|
g_legacyGregoryPatchTable->GetQuadOffsetsBase(patch.GetDescriptor().GetType());
|
|
|
|
if (uniformGregoryQuadOffsetBase >= 0)
|
|
|
|
glUniform1i(uniformGregoryQuadOffsetBase, quadOffsetBase);
|
|
|
|
}
|
2015-05-14 00:35:46 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
// update uniform
|
|
|
|
GLint uniformDiffuseColor =
|
|
|
|
glGetUniformLocation(program, "diffuseColor");
|
|
|
|
if (uniformDiffuseColor >= 0)
|
|
|
|
glUniform4f(uniformDiffuseColor, 0.4f, 0.4f, 0.8f, 1);
|
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// return primtype
|
|
|
|
GLenum primType;
|
|
|
|
switch(effectDesc.desc.GetType()) {
|
|
|
|
case Descriptor::QUADS:
|
|
|
|
primType = GL_LINES_ADJACENCY;
|
|
|
|
break;
|
|
|
|
case Descriptor::TRIANGLES:
|
|
|
|
primType = GL_TRIANGLES;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
#if defined(GL_ARB_tessellation_shader) || defined(GL_VERSION_4_0)
|
|
|
|
primType = GL_PATCHES;
|
|
|
|
glPatchParameteri(GL_PATCH_VERTICES, effectDesc.desc.GetNumControlVertices());
|
|
|
|
#else
|
|
|
|
primType = GL_POINTS;
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return primType;
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
|
|
|
display() {
|
|
|
|
Stopwatch s;
|
|
|
|
s.Start();
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
glViewport(0, 0, g_width, g_height);
|
2015-06-01 03:13:21 +00:00
|
|
|
g_hud.FillBackground();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// prepare view matrix
|
|
|
|
double aspect = g_width/(double)g_height;
|
|
|
|
identity(g_transformData.ModelViewMatrix);
|
|
|
|
translate(g_transformData.ModelViewMatrix, -g_pan[0], -g_pan[1], -g_dolly);
|
|
|
|
rotate(g_transformData.ModelViewMatrix, g_rotate[1], 1, 0, 0);
|
|
|
|
rotate(g_transformData.ModelViewMatrix, g_rotate[0], 0, 1, 0);
|
|
|
|
rotate(g_transformData.ModelViewMatrix, -90, 1, 0, 0);
|
|
|
|
translate(g_transformData.ModelViewMatrix,
|
|
|
|
-g_center[0], -g_center[1], -g_center[2]);
|
|
|
|
perspective(g_transformData.ProjectionMatrix,
|
2015-06-01 03:13:21 +00:00
|
|
|
45.0f, (float)aspect, 0.1f, 500.0f);
|
2013-01-29 23:54:18 +00:00
|
|
|
multMatrix(g_transformData.ModelViewProjectionMatrix,
|
|
|
|
g_transformData.ModelViewMatrix,
|
|
|
|
g_transformData.ProjectionMatrix);
|
2015-06-01 18:13:54 +00:00
|
|
|
inverseMatrix(g_transformData.ModelViewInverseMatrix,
|
|
|
|
g_transformData.ModelViewMatrix);
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
// make sure that the vertex buffer is interoped back as a GL resources.
|
2015-05-20 21:36:57 +00:00
|
|
|
GLuint vbo = g_mesh->BindVertexBuffer();
|
|
|
|
|
|
|
|
// vertex texture update for legacy gregory drawing
|
|
|
|
if (g_legacyGregoryPatchTable) {
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
|
|
g_legacyGregoryPatchTable->UpdateVertexBuffer(vbo);
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor)
|
2013-06-27 19:57:21 +00:00
|
|
|
g_mesh->BindVaryingBuffer();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// update transform and lighting uniform blocks
|
|
|
|
updateUniformBlocks();
|
|
|
|
|
|
|
|
// also bind patch related textures
|
|
|
|
bindTextures();
|
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_displayStyle == kDisplayStyleWire)
|
2015-05-14 00:35:46 +00:00
|
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
|
2014-05-15 20:53:43 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
|
2013-06-27 19:57:21 +00:00
|
|
|
glBindVertexArray(g_vao);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
Osd API refactor: EvalStencils and EvalPatches
Add EvalStencils and EvalPatches API for most of CPU and GPU evaluators.
with this change, Eval API in the osd layer consists of following parts:
- Evaluators (Cpu, Omp, Tbb, Cuda, CL, GLXFB, GLCompute, D3D11Compute)
implements EvalStencils and EvalPatches(*). Both supports derivatives
(not fully implemented though)
- Interop vertex buffer classes (optional, same as before)
Note that these classes are not necessary to use Evaluators.
All evaluators have EvalStencils/Patches which take device-specific
buffer objects. For example, GLXFBEvaluator can take GLuint directly
for both stencil tables and input primvars. Although using these
interop classes makes it easy to integrate osd into relatively
simple applications.
- device-dependent StencilTable and PatchTable (optional)
These are also optional, but can be used simply a substitute of
Far::StencilTable and Far::PatchTable for osd evaluators.
- PatchArray, PatchCoord, PatchParam
They are tiny structs used for GPU based patch evaluation.
(*) TODO and known issues:
- CLEvaluator and D3D11Evaluator's EvalPatches() have not been implemented.
- GPU Gregory patch evaluation has not been implemented in EvalPatches().
- CudaEvaluator::EvalPatches() is very unstable.
- All patch evaluation kernels have not been well optimized.
- Currently GLXFB kernel doesn't support derivative evaluation.
There's a technical difficulty for the multi-stream output.
2015-05-26 04:51:55 +00:00
|
|
|
OpenSubdiv::Osd::PatchArrayVector const & patches =
|
2015-05-20 21:36:57 +00:00
|
|
|
g_mesh->GetPatchTable()->GetPatchArrays();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// patch drawing
|
2015-05-22 18:50:01 +00:00
|
|
|
int patchCount[13]; // [Type] (see far/patchTable.h)
|
2014-10-13 15:52:09 +00:00
|
|
|
int numTotalPatches = 0;
|
|
|
|
int numDrawCalls = 0;
|
2013-05-09 16:23:01 +00:00
|
|
|
memset(patchCount, 0, sizeof(patchCount));
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
// primitive counting
|
2014-05-15 16:32:47 +00:00
|
|
|
glBeginQuery(GL_PRIMITIVES_GENERATED, g_queries[0]);
|
|
|
|
#if defined(GL_VERSION_3_3)
|
|
|
|
glBeginQuery(GL_TIME_ELAPSED, g_queries[1]);
|
|
|
|
#endif
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
// core draw-calls
|
2013-01-29 23:54:18 +00:00
|
|
|
for (int i=0; i<(int)patches.size(); ++i) {
|
Osd API refactor: EvalStencils and EvalPatches
Add EvalStencils and EvalPatches API for most of CPU and GPU evaluators.
with this change, Eval API in the osd layer consists of following parts:
- Evaluators (Cpu, Omp, Tbb, Cuda, CL, GLXFB, GLCompute, D3D11Compute)
implements EvalStencils and EvalPatches(*). Both supports derivatives
(not fully implemented though)
- Interop vertex buffer classes (optional, same as before)
Note that these classes are not necessary to use Evaluators.
All evaluators have EvalStencils/Patches which take device-specific
buffer objects. For example, GLXFBEvaluator can take GLuint directly
for both stencil tables and input primvars. Although using these
interop classes makes it easy to integrate osd into relatively
simple applications.
- device-dependent StencilTable and PatchTable (optional)
These are also optional, but can be used simply a substitute of
Far::StencilTable and Far::PatchTable for osd evaluators.
- PatchArray, PatchCoord, PatchParam
They are tiny structs used for GPU based patch evaluation.
(*) TODO and known issues:
- CLEvaluator and D3D11Evaluator's EvalPatches() have not been implemented.
- GPU Gregory patch evaluation has not been implemented in EvalPatches().
- CudaEvaluator::EvalPatches() is very unstable.
- All patch evaluation kernels have not been well optimized.
- Currently GLXFB kernel doesn't support derivative evaluation.
There's a technical difficulty for the multi-stream output.
2015-05-26 04:51:55 +00:00
|
|
|
OpenSubdiv::Osd::PatchArray const & patch = patches[i];
|
2013-05-09 16:23:01 +00:00
|
|
|
|
2015-05-12 01:06:46 +00:00
|
|
|
OpenSubdiv::Far::PatchDescriptor desc = patch.GetDescriptor();
|
2014-11-25 20:41:19 +00:00
|
|
|
OpenSubdiv::Far::PatchDescriptor::Type patchType = desc.GetType();
|
2013-05-09 16:23:01 +00:00
|
|
|
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[patchType] += patch.GetNumPatches();
|
2014-10-13 15:52:09 +00:00
|
|
|
numTotalPatches += patch.GetNumPatches();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-14 00:35:46 +00:00
|
|
|
GLenum primType = bindProgram(GetEffect(), patch);
|
2013-05-09 16:23:01 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-20 21:36:57 +00:00
|
|
|
glDrawElements(primType,
|
|
|
|
patch.GetNumPatches() * desc.GetNumControlVertices(),
|
|
|
|
GL_UNSIGNED_INT,
|
|
|
|
(void *)(patch.GetIndexBase() * sizeof(unsigned int)));
|
2014-10-13 15:52:09 +00:00
|
|
|
++numDrawCalls;
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
s.Stop();
|
|
|
|
float drawCpuTime = float(s.GetElapsed() * 1000.0f);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
glEndQuery(GL_PRIMITIVES_GENERATED);
|
|
|
|
#if defined(GL_VERSION_3_3)
|
|
|
|
glEndQuery(GL_TIME_ELAPSED);
|
|
|
|
#endif
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
glUseProgram(0);
|
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
if (g_displayStyle == kDisplayStyleWire)
|
2015-05-14 00:35:46 +00:00
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
// draw the control mesh
|
2015-06-01 18:13:54 +00:00
|
|
|
int stride = g_shadingMode == kShadingInterleavedVaryingColor ? 7 : 3;
|
2015-05-31 22:08:37 +00:00
|
|
|
g_controlMeshDisplay.Draw(vbo, stride*sizeof(float),
|
|
|
|
g_transformData.ModelViewProjectionMatrix);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
GLuint numPrimsGenerated = 0;
|
|
|
|
GLuint timeElapsed = 0;
|
|
|
|
glGetQueryObjectuiv(g_queries[0], GL_QUERY_RESULT, &numPrimsGenerated);
|
|
|
|
#if defined(GL_VERSION_3_3)
|
|
|
|
glGetQueryObjectuiv(g_queries[1], GL_QUERY_RESULT, &timeElapsed);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
float drawGpuTime = timeElapsed / 1000.0f / 1000.0f;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
g_fpsTimer.Stop();
|
|
|
|
float elapsed = (float)g_fpsTimer.GetElapsed();
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! g_freeze) {
|
2014-09-05 22:07:46 +00:00
|
|
|
g_animTime += elapsed;
|
|
|
|
}
|
|
|
|
g_fpsTimer.Start();
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
if (g_hud.IsVisible()) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2014-11-25 20:41:19 +00:00
|
|
|
typedef OpenSubdiv::Far::PatchDescriptor Descriptor;
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
double fps = 1.0/elapsed;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-10-13 15:52:09 +00:00
|
|
|
if (g_displayPatchCounts) {
|
|
|
|
int x = -280;
|
2015-04-17 23:26:57 +00:00
|
|
|
int y = -180;
|
2014-10-13 15:52:09 +00:00
|
|
|
g_hud.DrawString(x, y, "NonPatch : %d",
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[Descriptor::QUADS]); y += 20;
|
2014-10-13 15:52:09 +00:00
|
|
|
g_hud.DrawString(x, y, "Regular : %d",
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[Descriptor::REGULAR]); y+= 20;
|
2014-10-13 15:52:09 +00:00
|
|
|
g_hud.DrawString(x, y, "Gregory : %d",
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[Descriptor::GREGORY]); y+= 20;
|
2014-10-13 15:52:09 +00:00
|
|
|
g_hud.DrawString(x, y, "Boundary Gregory : %d",
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[Descriptor::GREGORY_BOUNDARY]); y+= 20;
|
2015-04-08 01:34:05 +00:00
|
|
|
g_hud.DrawString(x, y, "Gregory Basis : %d",
|
2015-04-17 14:42:53 +00:00
|
|
|
patchCount[Descriptor::GREGORY_BASIS]); y+= 20;
|
2014-10-13 15:52:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int y = -220;
|
|
|
|
g_hud.DrawString(10, y, "Tess level : %d", g_tessLevel); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "Patches : %d", numTotalPatches); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "Draw calls : %d", numDrawCalls); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "Primitives : %d", numPrimsGenerated); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "Vertices : %d", g_mesh->GetNumVertices()); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "GPU Kernel : %.3f ms", g_gpuTime); y+= 20;
|
2015-05-31 22:08:37 +00:00
|
|
|
g_hud.DrawString(10, y, "CPU Kernel : %.3f ms", g_cpuTime); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "GPU Draw : %.3f ms", drawGpuTime); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "CPU Draw : %.3f ms", drawCpuTime); y+= 20;
|
|
|
|
g_hud.DrawString(10, y, "FPS : %3.1f", fps); y+= 20;
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
g_hud.Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
glFinish();
|
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
GLUtils::CheckGLErrors("display leave\n");
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2013-04-19 02:15:30 +00:00
|
|
|
motion(GLFWwindow *, double dx, double dy) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2013-04-19 02:15:30 +00:00
|
|
|
int x=(int)dx, y=(int)dy;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2014-05-15 20:53:43 +00:00
|
|
|
if (g_hud.MouseCapture()) {
|
|
|
|
// check gui
|
|
|
|
g_hud.MouseMotion(x, y);
|
|
|
|
} else if (g_mbutton[0] && !g_mbutton[1] && !g_mbutton[2]) {
|
2013-01-29 23:54:18 +00:00
|
|
|
// orbit
|
|
|
|
g_rotate[0] += x - g_prev_x;
|
|
|
|
g_rotate[1] += y - g_prev_y;
|
|
|
|
} else if (!g_mbutton[0] && !g_mbutton[1] && g_mbutton[2]) {
|
|
|
|
// pan
|
|
|
|
g_pan[0] -= g_dolly*(x - g_prev_x)/g_width;
|
|
|
|
g_pan[1] += g_dolly*(y - g_prev_y)/g_height;
|
2016-02-19 20:57:56 +00:00
|
|
|
} else if ((g_mbutton[0] && !g_mbutton[1] && g_mbutton[2]) ||
|
2013-01-29 23:54:18 +00:00
|
|
|
(!g_mbutton[0] && g_mbutton[1] && !g_mbutton[2])) {
|
|
|
|
// dolly
|
|
|
|
g_dolly -= g_dolly*0.01f*(x - g_prev_x);
|
|
|
|
if(g_dolly <= 0.01) g_dolly = 0.01f;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_prev_x = x;
|
|
|
|
g_prev_y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-05-15 20:53:43 +00:00
|
|
|
mouse(GLFWwindow *, int button, int state, int /* mods */) {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2014-05-15 20:53:43 +00:00
|
|
|
if (state == GLFW_RELEASE)
|
|
|
|
g_hud.MouseRelease();
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
if (button == 0 && state == GLFW_PRESS && g_hud.MouseClick(g_prev_x, g_prev_y))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (button < 3) {
|
|
|
|
g_mbutton[button] = (state == GLFW_PRESS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
|
|
|
uninitGL() {
|
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
glDeleteQueries(2, g_queries);
|
2013-01-29 23:54:18 +00:00
|
|
|
glDeleteVertexArrays(1, &g_vao);
|
|
|
|
|
|
|
|
if (g_mesh)
|
|
|
|
delete g_mesh;
|
2015-05-20 21:36:57 +00:00
|
|
|
|
|
|
|
if (g_legacyGregoryPatchTable)
|
|
|
|
delete g_legacyGregoryPatchTable;
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2013-01-31 23:34:35 +00:00
|
|
|
reshape(GLFWwindow *, int width, int height) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
g_width = width;
|
|
|
|
g_height = height;
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2014-02-22 03:25:00 +00:00
|
|
|
int windowWidth = g_width, windowHeight = g_height;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2014-02-22 03:25:00 +00:00
|
|
|
// window size might not match framebuffer size on a high DPI display
|
|
|
|
glfwGetWindowSize(g_window, &windowWidth, &windowHeight);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2014-05-23 20:24:31 +00:00
|
|
|
g_hud.Rebuild(windowWidth, windowHeight, width, height);
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2013-02-16 21:26:46 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2013-03-17 01:44:53 +00:00
|
|
|
void windowClose(GLFWwindow*) {
|
|
|
|
g_running = false;
|
|
|
|
}
|
2013-02-16 21:26:46 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2013-08-16 17:51:51 +00:00
|
|
|
static void
|
2013-02-08 22:06:44 +00:00
|
|
|
toggleFullScreen() {
|
|
|
|
// XXXX manuelk : to re-implement from glut
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-05-15 20:53:43 +00:00
|
|
|
keyboard(GLFWwindow *, int key, int /* scancode */, int event, int /* mods */) {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
if (event == GLFW_RELEASE) return;
|
|
|
|
if (g_hud.KeyDown(tolower(key))) return;
|
|
|
|
|
|
|
|
switch (key) {
|
|
|
|
case 'Q': g_running = 0; break;
|
|
|
|
case 'F': fitFrame(); break;
|
|
|
|
case GLFW_KEY_TAB: toggleFullScreen(); break;
|
|
|
|
case '+':
|
|
|
|
case '=': g_tessLevel++; break;
|
|
|
|
case '-': g_tessLevel = std::max(g_tessLevelMin, g_tessLevel-1); break;
|
2013-06-20 18:53:33 +00:00
|
|
|
case GLFW_KEY_ESCAPE: g_hud.SetVisible(!g_hud.IsVisible()); break;
|
2015-06-01 03:13:21 +00:00
|
|
|
case 'X': GLUtils::WriteScreenshot(g_width, g_height); break;
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
2013-06-27 19:57:21 +00:00
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackDisplayStyle(int b) {
|
2015-06-01 18:13:54 +00:00
|
|
|
g_displayStyle = b;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
callbackShadingMode(int b) {
|
2016-02-19 20:57:56 +00:00
|
|
|
if (g_shadingMode == kShadingVaryingColor || b == kShadingVaryingColor ||
|
|
|
|
g_shadingMode == kShadingInterleavedVaryingColor || b == kShadingInterleavedVaryingColor ||
|
|
|
|
g_shadingMode == kShadingFaceVaryingColor || b == kShadingFaceVaryingColor) {
|
2013-06-27 19:57:21 +00:00
|
|
|
// need to rebuild for varying reconstruct
|
2015-06-01 18:13:54 +00:00
|
|
|
g_shadingMode = b;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2013-06-27 19:57:21 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-06-01 18:13:54 +00:00
|
|
|
g_shadingMode = b;
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2015-04-18 00:36:55 +00:00
|
|
|
static void
|
|
|
|
callbackEndCap(int endCap) {
|
|
|
|
g_endCap = endCap;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2015-04-18 00:36:55 +00:00
|
|
|
}
|
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackKernel(int k) {
|
2013-01-29 23:54:18 +00:00
|
|
|
g_kernel = k;
|
|
|
|
|
|
|
|
#ifdef OPENSUBDIV_HAS_OPENCL
|
2016-06-25 21:26:54 +00:00
|
|
|
if (g_kernel == kCL && (!g_clDeviceContext.IsInitialized())) {
|
2015-04-28 22:46:37 +00:00
|
|
|
if (g_clDeviceContext.Initialize() == false) {
|
2013-01-29 23:54:18 +00:00
|
|
|
printf("Error in initializing OpenCL\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_CUDA
|
2016-06-25 21:26:54 +00:00
|
|
|
if (g_kernel == kCUDA && (!g_cudaDeviceContext.IsInitialized())) {
|
2015-04-28 22:46:37 +00:00
|
|
|
if (g_cudaDeviceContext.Initialize() == false) {
|
|
|
|
printf("Error in initializing Cuda\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackLevel(int l) {
|
2013-01-29 23:54:18 +00:00
|
|
|
g_level = l;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackModel(int m) {
|
2013-01-29 23:54:18 +00:00
|
|
|
if (m < 0)
|
|
|
|
m = 0;
|
|
|
|
|
|
|
|
if (m >= (int)g_defaultShapes.size())
|
|
|
|
m = (int)g_defaultShapes.size() - 1;
|
|
|
|
|
|
|
|
g_currentShape = m;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-04-18 00:36:55 +00:00
|
|
|
callbackCheckBox(bool checked, int button) {
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-19 01:04:38 +00:00
|
|
|
if (GLUtils::SupportsAdaptiveTessellation()) {
|
2015-04-18 00:36:55 +00:00
|
|
|
switch(button) {
|
|
|
|
case kHUD_CB_ADAPTIVE:
|
|
|
|
g_adaptive = checked;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2015-04-18 00:36:55 +00:00
|
|
|
return;
|
|
|
|
case kHUD_CB_SINGLE_CREASE_PATCH:
|
|
|
|
g_singleCreasePatch = checked;
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2015-04-18 00:36:55 +00:00
|
|
|
return;
|
2016-09-30 18:00:31 +00:00
|
|
|
case kHUD_CB_INF_SHARP_PATCH:
|
|
|
|
g_infSharpPatch = checked;
|
|
|
|
rebuildMesh();
|
|
|
|
return;
|
2015-04-18 00:36:55 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2014-10-13 15:52:09 +00:00
|
|
|
}
|
|
|
|
|
2013-06-27 19:57:21 +00:00
|
|
|
switch (button) {
|
2015-05-31 22:08:37 +00:00
|
|
|
case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES:
|
|
|
|
g_controlMeshDisplay.SetEdgesDisplay(checked);
|
2013-06-27 19:57:21 +00:00
|
|
|
break;
|
2015-05-31 22:08:37 +00:00
|
|
|
case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS:
|
|
|
|
g_controlMeshDisplay.SetVerticesDisplay(checked);
|
2013-06-27 19:57:21 +00:00
|
|
|
break;
|
|
|
|
case kHUD_CB_ANIMATE_VERTICES:
|
|
|
|
g_moveScale = checked;
|
|
|
|
break;
|
|
|
|
case kHUD_CB_VIEW_LOD:
|
|
|
|
g_screenSpaceTess = checked;
|
|
|
|
break;
|
2013-06-27 20:34:25 +00:00
|
|
|
case kHUD_CB_FRACTIONAL_SPACING:
|
|
|
|
g_fractionalSpacing = checked;
|
|
|
|
break;
|
2013-06-27 19:57:21 +00:00
|
|
|
case kHUD_CB_PATCH_CULL:
|
|
|
|
g_patchCull = checked;
|
|
|
|
break;
|
|
|
|
case kHUD_CB_FREEZE:
|
|
|
|
g_freeze = checked;
|
|
|
|
break;
|
2014-10-13 15:52:09 +00:00
|
|
|
case kHUD_CB_DISPLAY_PATCH_COUNTS:
|
|
|
|
g_displayPatchCounts = checked;
|
|
|
|
break;
|
2013-06-27 19:57:21 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
initHUD() {
|
2014-02-22 03:25:00 +00:00
|
|
|
int windowWidth = g_width, windowHeight = g_height;
|
2014-05-23 20:24:31 +00:00
|
|
|
int frameBufferWidth = g_width, frameBufferHeight = g_height;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2014-02-22 03:25:00 +00:00
|
|
|
// window size might not match framebuffer size on a high DPI display
|
|
|
|
glfwGetWindowSize(g_window, &windowWidth, &windowHeight);
|
2014-05-23 20:24:31 +00:00
|
|
|
glfwGetFramebufferSize(g_window, &frameBufferWidth, &frameBufferHeight);
|
2014-05-16 20:38:25 +00:00
|
|
|
|
2014-05-23 20:24:31 +00:00
|
|
|
g_hud.Init(windowWidth, windowHeight, frameBufferWidth, frameBufferHeight);
|
2014-05-16 20:38:25 +00:00
|
|
|
|
2015-06-01 18:13:54 +00:00
|
|
|
int y = 10;
|
2015-05-31 22:08:37 +00:00
|
|
|
g_hud.AddCheckBox("Control edges (H)",
|
|
|
|
g_controlMeshDisplay.GetEdgesDisplay(),
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox,
|
2015-05-31 22:08:37 +00:00
|
|
|
kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h');
|
2015-06-01 18:13:54 +00:00
|
|
|
y += 20;
|
2015-05-31 22:08:37 +00:00
|
|
|
g_hud.AddCheckBox("Control vertices (J)",
|
|
|
|
g_controlMeshDisplay.GetVerticesDisplay(),
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox,
|
2015-05-31 22:08:37 +00:00
|
|
|
kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j');
|
2015-06-01 18:13:54 +00:00
|
|
|
y += 20;
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0,
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'm');
|
|
|
|
y += 20;
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddCheckBox("Screen space LOD (V)", g_screenSpaceTess != 0,
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox, kHUD_CB_VIEW_LOD, 'v');
|
|
|
|
y += 20;
|
2015-10-23 22:26:46 +00:00
|
|
|
g_hud.AddCheckBox("Fractional spacing (T)", g_fractionalSpacing != 0,
|
|
|
|
10, y, callbackCheckBox, kHUD_CB_FRACTIONAL_SPACING, 't');
|
|
|
|
y += 20;
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddCheckBox("Frustum Patch Culling (B)", g_patchCull != 0,
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox, kHUD_CB_PATCH_CULL, 'b');
|
|
|
|
y += 20;
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddCheckBox("Freeze (spc)", g_freeze != 0,
|
2015-06-01 18:13:54 +00:00
|
|
|
10, y, callbackCheckBox, kHUD_CB_FREEZE, ' ');
|
|
|
|
y += 20;
|
|
|
|
|
|
|
|
int displaystyle_pulldown = g_hud.AddPullDown("DisplayStyle (W)", 200, 10, 250,
|
|
|
|
callbackDisplayStyle, 'w');
|
|
|
|
g_hud.AddPullDownButton(displaystyle_pulldown, "Wire", kDisplayStyleWire,
|
|
|
|
g_displayStyle == kDisplayStyleWire);
|
|
|
|
g_hud.AddPullDownButton(displaystyle_pulldown, "Shaded", kDisplayStyleShaded,
|
|
|
|
g_displayStyle == kDisplayStyleShaded);
|
|
|
|
g_hud.AddPullDownButton(displaystyle_pulldown, "Wire+Shaded", kDisplayStyleWireOnShaded,
|
|
|
|
g_displayStyle == kDisplayStyleWireOnShaded);
|
|
|
|
|
|
|
|
int shading_pulldown = g_hud.AddPullDown("Shading (C)", 200, 70, 250,
|
|
|
|
callbackShadingMode, 'c');
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Material",
|
|
|
|
kShadingMaterial,
|
|
|
|
g_shadingMode == kShadingMaterial);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Varying Color",
|
|
|
|
kShadingVaryingColor,
|
|
|
|
g_shadingMode == kShadingVaryingColor);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Varying Color (Interleaved)",
|
|
|
|
kShadingInterleavedVaryingColor,
|
|
|
|
g_shadingMode == kShadingInterleavedVaryingColor);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "FaceVarying Color",
|
|
|
|
kShadingFaceVaryingColor,
|
|
|
|
g_shadingMode == kShadingFaceVaryingColor);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Patch Type",
|
|
|
|
kShadingPatchType,
|
|
|
|
g_shadingMode == kShadingPatchType);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Patch Coord",
|
|
|
|
kShadingPatchCoord,
|
|
|
|
g_shadingMode == kShadingPatchCoord);
|
|
|
|
g_hud.AddPullDownButton(shading_pulldown, "Normal",
|
|
|
|
kShadingNormal,
|
|
|
|
g_shadingMode == kShadingNormal);
|
2014-04-28 23:36:39 +00:00
|
|
|
|
|
|
|
int compute_pulldown = g_hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k');
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "CPU", kCPU);
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_OPENMP
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "OpenMP", kOPENMP);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
2013-08-16 17:51:51 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_TBB
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "TBB", kTBB);
|
2013-08-16 17:51:51 +00:00
|
|
|
#endif
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef OPENSUBDIV_HAS_CUDA
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "CUDA", kCUDA);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_OPENCL
|
2015-04-28 22:46:37 +00:00
|
|
|
if (CLDeviceContext::HAS_CL_VERSION_1_1()) {
|
2014-05-21 08:10:45 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "OpenCL", kCL);
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_TRANSFORM_FEEDBACK
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "GLSL TransformFeedback", kGLSL);
|
2013-01-29 23:54:18 +00:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSUBDIV_HAS_GLSL_COMPUTE
|
2015-05-28 15:43:05 +00:00
|
|
|
if (GLUtils::GL_ARBComputeShaderOrGL_VERSION_4_3()) {
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(compute_pulldown, "GLSL Compute", kGLSLCompute);
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
#endif
|
2015-05-19 01:04:38 +00:00
|
|
|
if (GLUtils::SupportsAdaptiveTessellation()) {
|
2015-04-18 00:36:55 +00:00
|
|
|
g_hud.AddCheckBox("Adaptive (`)", g_adaptive!=0,
|
|
|
|
10, 190, callbackCheckBox, kHUD_CB_ADAPTIVE, '`');
|
|
|
|
g_hud.AddCheckBox("Single Crease Patch (S)", g_singleCreasePatch!=0,
|
|
|
|
10, 210, callbackCheckBox, kHUD_CB_SINGLE_CREASE_PATCH, 's');
|
2016-09-30 18:00:31 +00:00
|
|
|
g_hud.AddCheckBox("Inf Sharp Patch (I)", g_infSharpPatch!=0,
|
|
|
|
10, 230, callbackCheckBox, kHUD_CB_INF_SHARP_PATCH, 'i');
|
2015-04-18 00:36:55 +00:00
|
|
|
|
|
|
|
int endcap_pulldown = g_hud.AddPullDown(
|
2016-09-30 18:00:31 +00:00
|
|
|
"End cap (E)", 10, 250, 200, callbackEndCap, 'e');
|
2015-04-18 00:36:55 +00:00
|
|
|
g_hud.AddPullDownButton(endcap_pulldown,"None",
|
|
|
|
kEndCapNone,
|
|
|
|
g_endCap == kEndCapNone);
|
2015-04-23 23:58:45 +00:00
|
|
|
g_hud.AddPullDownButton(endcap_pulldown, "BSpline",
|
|
|
|
kEndCapBSplineBasis,
|
|
|
|
g_endCap == kEndCapBSplineBasis);
|
2015-04-18 00:36:55 +00:00
|
|
|
g_hud.AddPullDownButton(endcap_pulldown, "GregoryBasis",
|
|
|
|
kEndCapGregoryBasis,
|
|
|
|
g_endCap == kEndCapGregoryBasis);
|
|
|
|
g_hud.AddPullDownButton(endcap_pulldown, "LegacyGregory",
|
|
|
|
kEndCapLegacyGregory,
|
|
|
|
g_endCap == kEndCapLegacyGregory);
|
2014-10-13 15:52:09 +00:00
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
for (int i = 1; i < 11; ++i) {
|
|
|
|
char level[16];
|
|
|
|
sprintf(level, "Lv. %d", i);
|
2015-04-18 00:36:55 +00:00
|
|
|
g_hud.AddRadioButton(3, level, i==2, 10, 310+i*20, callbackLevel, i, '0'+(i%10));
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
2014-04-28 23:36:39 +00:00
|
|
|
int shapes_pulldown = g_hud.AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n');
|
2013-01-29 23:54:18 +00:00
|
|
|
for (int i = 0; i < (int)g_defaultShapes.size(); ++i) {
|
2014-04-28 06:05:18 +00:00
|
|
|
g_hud.AddPullDownButton(shapes_pulldown, g_defaultShapes[i].name.c_str(),i);
|
2014-05-15 20:53:43 +00:00
|
|
|
}
|
2014-09-10 22:29:24 +00:00
|
|
|
|
2014-10-13 15:52:09 +00:00
|
|
|
g_hud.AddCheckBox("Show patch counts", g_displayPatchCounts!=0, -280, -20, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_COUNTS);
|
|
|
|
|
2014-10-24 18:15:19 +00:00
|
|
|
g_hud.Rebuild(windowWidth, windowHeight, frameBufferWidth, frameBufferHeight);
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
initGL() {
|
2015-06-01 03:13:21 +00:00
|
|
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
2013-01-29 23:54:18 +00:00
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
glCullFace(GL_BACK);
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
|
2014-05-15 16:32:47 +00:00
|
|
|
glGenQueries(2, g_queries);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
glGenVertexArrays(1, &g_vao);
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
|
|
|
idle() {
|
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! g_freeze) {
|
2013-01-29 23:54:18 +00:00
|
|
|
g_frame++;
|
2014-05-02 21:19:08 +00:00
|
|
|
updateGeom();
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (g_repeatCount != 0 && g_frame >= g_repeatCount)
|
2013-01-29 23:54:18 +00:00
|
|
|
g_running = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackErrorOsd(OpenSubdiv::Far::ErrorType err, const char *message) {
|
2014-12-04 01:19:07 +00:00
|
|
|
printf("Error: %d\n", err);
|
2013-01-29 23:54:18 +00:00
|
|
|
printf("%s", message);
|
|
|
|
}
|
|
|
|
|
2013-01-31 23:34:35 +00:00
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
static void
|
2014-12-20 22:44:50 +00:00
|
|
|
callbackErrorGLFW(int error, const char* description) {
|
|
|
|
fprintf(stderr, "GLFW Error (%d) : %s\n", error, description);
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
2013-01-29 23:54:18 +00:00
|
|
|
//------------------------------------------------------------------------------
|
2014-12-04 01:19:07 +00:00
|
|
|
int main(int argc, char ** argv) {
|
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
bool fullscreen = false;
|
|
|
|
std::string str;
|
|
|
|
std::vector<char const *> animobjs;
|
|
|
|
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
if (strstr(argv[i], ".obj")) {
|
|
|
|
animobjs.push_back(argv[i]);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "-axis")) {
|
|
|
|
g_axis = false;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "-d")) {
|
|
|
|
g_level = atoi(argv[++i]);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "-c")) {
|
|
|
|
g_repeatCount = atoi(argv[++i]);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "-f")) {
|
|
|
|
fullscreen = true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
std::ifstream ifs(argv[1]);
|
|
|
|
if (ifs) {
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << ifs.rdbuf();
|
|
|
|
ifs.close();
|
|
|
|
str = ss.str();
|
|
|
|
g_defaultShapes.push_back(ShapeDesc(argv[1], str.c_str(), kCatmark));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! animobjs.empty()) {
|
2015-05-29 22:56:36 +00:00
|
|
|
|
|
|
|
g_defaultShapes.push_back(ShapeDesc(animobjs[0], "", kCatmark));
|
|
|
|
|
|
|
|
g_objAnim = ObjAnim::Create(animobjs, g_axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
initShapes();
|
|
|
|
|
|
|
|
g_fpsTimer.Start();
|
|
|
|
|
|
|
|
OpenSubdiv::Far::SetErrorCallback(callbackErrorOsd);
|
|
|
|
|
|
|
|
glfwSetErrorCallback(callbackErrorGLFW);
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! glfwInit()) {
|
2015-05-29 22:56:36 +00:00
|
|
|
printf("Failed to initialize GLFW\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char windowTitle[] = "OpenSubdiv glViewer " OPENSUBDIV_VERSION_STRING;
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-31 07:35:45 +00:00
|
|
|
GLUtils::SetMinimumGLVersion(argc, argv);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
if (fullscreen) {
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
g_primary = glfwGetPrimaryMonitor();
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
// apparently glfwGetPrimaryMonitor fails under linux : if no primary,
|
|
|
|
// settle for the first one in the list
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! g_primary) {
|
2015-05-29 22:56:36 +00:00
|
|
|
int count = 0;
|
|
|
|
GLFWmonitor ** monitors = glfwGetMonitors(&count);
|
2014-09-05 22:07:46 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
if (count)
|
|
|
|
g_primary = monitors[0];
|
|
|
|
}
|
2013-01-29 23:54:18 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
if (g_primary) {
|
|
|
|
GLFWvidmode const * vidmode = glfwGetVideoMode(g_primary);
|
|
|
|
g_width = vidmode->width;
|
|
|
|
g_height = vidmode->height;
|
|
|
|
}
|
|
|
|
}
|
2013-01-31 23:34:35 +00:00
|
|
|
|
2015-05-29 22:56:36 +00:00
|
|
|
g_window = glfwCreateWindow(g_width, g_height, windowTitle,
|
2016-02-19 20:57:56 +00:00
|
|
|
fullscreen && g_primary ? g_primary : NULL, NULL);
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2016-02-19 20:57:56 +00:00
|
|
|
if (! g_window) {
|
2015-05-30 05:33:51 +00:00
|
|
|
std::cerr << "Failed to create OpenGL context.\n";
|
2015-05-29 22:56:36 +00:00
|
|
|
glfwTerminate();
|
|
|
|
return 1;
|
|
|
|
}
|
2013-02-06 00:28:20 +00:00
|
|
|
|
2013-01-31 23:34:35 +00:00
|
|
|
glfwMakeContextCurrent(g_window);
|
2015-05-30 05:33:51 +00:00
|
|
|
GLUtils::PrintGLVersion();
|
2014-02-22 03:25:00 +00:00
|
|
|
|
|
|
|
// accommocate high DPI displays (e.g. mac retina displays)
|
|
|
|
glfwGetFramebufferSize(g_window, &g_width, &g_height);
|
|
|
|
glfwSetFramebufferSizeCallback(g_window, reshape);
|
|
|
|
|
2013-01-31 23:34:35 +00:00
|
|
|
glfwSetKeyCallback(g_window, keyboard);
|
|
|
|
glfwSetCursorPosCallback(g_window, motion);
|
|
|
|
glfwSetMouseButtonCallback(g_window, mouse);
|
2013-02-19 18:14:56 +00:00
|
|
|
glfwSetWindowCloseCallback(g_window, windowClose);
|
2013-02-16 21:26:46 +00:00
|
|
|
|
2013-06-26 07:52:57 +00:00
|
|
|
#if defined(OSD_USES_GLEW)
|
2013-01-29 23:54:18 +00:00
|
|
|
#ifdef CORE_PROFILE
|
|
|
|
// this is the only way to initialize glew correctly under core profile context.
|
|
|
|
glewExperimental = true;
|
|
|
|
#endif
|
|
|
|
if (GLenum r = glewInit() != GLEW_OK) {
|
2013-01-31 23:34:35 +00:00
|
|
|
printf("Failed to initialize glew. Error = %s\n", glewGetErrorString(r));
|
2013-01-29 23:54:18 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
#ifdef CORE_PROFILE
|
|
|
|
// clear GL errors which was generated during glewInit()
|
|
|
|
glGetError();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2013-02-05 23:04:07 +00:00
|
|
|
// activate feature adaptive tessellation if OSD supports it
|
2015-05-19 01:04:38 +00:00
|
|
|
g_adaptive = GLUtils::SupportsAdaptiveTessellation();
|
2013-02-05 23:04:07 +00:00
|
|
|
|
2013-01-29 23:54:18 +00:00
|
|
|
initGL();
|
|
|
|
|
2013-02-04 09:59:53 +00:00
|
|
|
glfwSwapInterval(0);
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
initHUD();
|
2015-05-31 22:08:37 +00:00
|
|
|
rebuildMesh();
|
2013-01-29 23:54:18 +00:00
|
|
|
|
|
|
|
while (g_running) {
|
|
|
|
idle();
|
|
|
|
display();
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2013-01-31 23:34:35 +00:00
|
|
|
glfwPollEvents();
|
|
|
|
glfwSwapBuffers(g_window);
|
2013-08-16 17:51:51 +00:00
|
|
|
|
2013-01-31 23:34:35 +00:00
|
|
|
glFinish();
|
2013-01-29 23:54:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uninitGL();
|
|
|
|
glfwTerminate();
|
|
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|