diff --git a/examples/common/CMakeLists.txt b/examples/common/CMakeLists.txt index cf41ec80..f85a0a46 100644 --- a/examples/common/CMakeLists.txt +++ b/examples/common/CMakeLists.txt @@ -52,6 +52,7 @@ set(EXAMPLES_COMMON_HEADER_FILES if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND)) list(APPEND EXAMPLES_COMMON_SOURCE_FILES + glControlMeshDisplay.cpp glFramebuffer.cpp glHud.cpp glUtils.cpp @@ -59,6 +60,7 @@ if( OPENGL_FOUND AND (GLEW_FOUND AND GLFW_FOUND) OR (APPLE AND GLFW_FOUND)) ) list(APPEND EXAMPLES_COMMON_HEADER_FILES + glControlMeshDisplay.h glFramebuffer.h glHud.h glUtils.h @@ -83,12 +85,14 @@ endif() if(DXSDK_FOUND) list(APPEND EXAMPLES_COMMON_SOURCE_FILES + d3d11ControlMeshDisplay.cpp d3d11Hud.cpp d3d11Utils.cpp d3d11ShaderCache.cpp ) list(APPEND EXAMPLES_COMMON_HEADER_FILES + d3d11ControlMeshDisplay.h d3d11Hud.h d3d11Utils.h d3d11ShaderCache.h diff --git a/examples/common/d3d11ControlMeshDisplay.cpp b/examples/common/d3d11ControlMeshDisplay.cpp new file mode 100644 index 00000000..1b28ad07 --- /dev/null +++ b/examples/common/d3d11ControlMeshDisplay.cpp @@ -0,0 +1,268 @@ +// +// Copyright 2015 Pixar +// +// 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: +// +// 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. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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. +// + +#include "d3d11ControlMeshDisplay.h" +#include "../common/d3d11Utils.h" + +#include + +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +static const char *s_VS = +"cbuffer cbPerFrame : register( b0 ) { matrix g_mViewProjection; }; \n" +"struct vertexIn { float3 pos : POSITION0; float sharpness : COLOR0; }; \n" +"struct vertexOut { float4 pos : SV_POSITION; float sharpness : COLOR0; }; \n" +"vertexOut vs_main(vertexIn IN) { \n" +" vertexOut vout; \n" +" vout.pos = mul(g_mViewProjection, float4(IN.pos, 1)); \n" +" vout.sharpness = IN.sharpness; \n" +" return vout; \n" +"} \n"; + +static const char *s_PS = +"struct pixelIn { float4 pos : SV_POSITION; float sharpness : COLOR0; }; \n" +"Buffer edgeSharpness : register(t0); \n" +"float4 sharpnessToColor(float s) { \n" +" // 0.0 2.0 4.0 \n" +" // green --- yellow --- red \n" +" return float4(min(1, s * 0.5), \n" +" min(1, 2 - s * 0.5), \n" +" 0, 1); \n" +"} \n" +"float4 ps_main(pixelIn IN, uint primitiveID : SV_PrimitiveID) \n" +" : SV_Target { \n" +" float sharpness = edgeSharpness[primitiveID]; \n" +" return sharpnessToColor(sharpness); \n" +"} \n"; + +namespace { + struct CB_CONTROL_MESH_DISPLAY + { + float mViewProjection[16]; + }; +}; + +D3D11ControlMeshDisplay::D3D11ControlMeshDisplay( + ID3D11DeviceContext *deviceContext) : + _displayEdges(true), _displayVertices(false), + _deviceContext(deviceContext), _inputLayout(0), _vertexShader(0), + _pixelShader(0), _rasterizerState(0), _constantBuffer(0), + _edgeSharpnessSRV(0), _edgeSharpness(0), _edgeIndices(0), + _numEdges(0), _numPoints(0) { +} + +D3D11ControlMeshDisplay::~D3D11ControlMeshDisplay() { + SAFE_RELEASE(_inputLayout); + SAFE_RELEASE(_vertexShader); + SAFE_RELEASE(_pixelShader); + SAFE_RELEASE(_rasterizerState); + SAFE_RELEASE(_constantBuffer); + SAFE_RELEASE(_edgeSharpness); + SAFE_RELEASE(_edgeSharpnessSRV); + SAFE_RELEASE(_edgeIndices); +} + +bool +D3D11ControlMeshDisplay::createProgram() { + ID3D11Device *device = NULL; + _deviceContext->GetDevice(&device); + + ID3DBlob* pVSBlob; + ID3DBlob* pPSBlob; + pVSBlob = D3D11Utils::CompileShader(s_VS, "vs_main", "vs_4_0"); + pPSBlob = D3D11Utils::CompileShader(s_PS, "ps_main", "ps_4_0"); + assert(pVSBlob); + assert(pPSBlob); + + D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, + D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32_FLOAT, 0, sizeof(float)*3, + D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc), + pVSBlob->GetBufferPointer(), + pVSBlob->GetBufferSize(), + &_inputLayout); + assert(_inputLayout); + + device->CreateVertexShader(pVSBlob->GetBufferPointer(), + pVSBlob->GetBufferSize(), + NULL, &_vertexShader); + assert(_vertexShader); + + device->CreatePixelShader(pPSBlob->GetBufferPointer(), + pPSBlob->GetBufferSize(), + NULL, &_pixelShader); + assert(_pixelShader); + + D3D11_RASTERIZER_DESC rasDesc; + rasDesc.FillMode = D3D11_FILL_SOLID; + rasDesc.CullMode = D3D11_CULL_NONE; + rasDesc.FrontCounterClockwise = FALSE; + rasDesc.DepthBias = 0; + rasDesc.DepthBiasClamp = 0; + rasDesc.SlopeScaledDepthBias = 0.0f; + rasDesc.DepthClipEnable = FALSE; + rasDesc.ScissorEnable = FALSE; + rasDesc.MultisampleEnable = FALSE; + rasDesc.AntialiasedLineEnable = FALSE; + device->CreateRasterizerState(&rasDesc, &_rasterizerState); + assert(_rasterizerState); + + // constant buffer + D3D11_BUFFER_DESC cbDesc; + cbDesc.Usage = D3D11_USAGE_DYNAMIC; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + cbDesc.MiscFlags = 0; + cbDesc.ByteWidth = sizeof(CB_CONTROL_MESH_DISPLAY); + + device->CreateBuffer(&cbDesc, NULL, &_constantBuffer); + assert(_constantBuffer); + return true; +} + + +void +D3D11ControlMeshDisplay::Draw(ID3D11Buffer *buffer, int stride, + const float *modelViewProjectionMatrix) { + + if (_displayEdges == false && _displayVertices == false) return; + + if (_vertexShader == NULL) createProgram(); + if (_vertexShader == NULL) return; + + UINT hStrides = stride*sizeof(float); + UINT hOffsets = 0; + _deviceContext->IASetVertexBuffers(0, 1, &buffer, &hStrides, &hOffsets); + + D3D11_MAPPED_SUBRESOURCE MappedResource; + _deviceContext->Map(_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource); + CB_CONTROL_MESH_DISPLAY * pData = (CB_CONTROL_MESH_DISPLAY *)MappedResource.pData; + memcpy(pData->mViewProjection, modelViewProjectionMatrix, sizeof(float) * 16); + _deviceContext->Unmap(_constantBuffer, 0); + + _deviceContext->IASetInputLayout(_inputLayout); + _deviceContext->VSSetShader(_vertexShader, NULL, 0); + _deviceContext->HSSetShader(NULL, NULL, 0); + _deviceContext->DSSetShader(NULL, NULL, 0); + _deviceContext->GSSetShader(NULL, NULL, 0); + _deviceContext->PSSetShaderResources(0, 1, &_edgeSharpnessSRV); + _deviceContext->PSSetShader(_pixelShader, NULL, 0); + _deviceContext->RSSetState(_rasterizerState); + _deviceContext->VSSetConstantBuffers(0, 1, &_constantBuffer); + + if (_displayEdges) { + _deviceContext->IASetIndexBuffer(_edgeIndices, DXGI_FORMAT_R32_UINT, 0); + _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST); + _deviceContext->DrawIndexed(_numEdges * 2, 0, 0); + } + if (_displayVertices) { + // TODO: need geometry shader to draw bigger points + _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + _deviceContext->Draw(_numPoints, 0); + } + +} + +void +D3D11ControlMeshDisplay::SetTopology( + OpenSubdiv::Far::TopologyLevel const &level) { + int nEdges = level.GetNumEdges(); + int nVerts = level.GetNumVertices(); + + std::vector edgeIndices; + std::vector edgeSharpnesses; + std::vector vertSharpnesses; + + edgeIndices.reserve(nEdges * 2); + edgeSharpnesses.reserve(nEdges); + vertSharpnesses.reserve(nVerts); + + for (int i = 0; i < nEdges; ++i) { + OpenSubdiv::Far::ConstIndexArray verts = level.GetEdgeVertices(i); + edgeIndices.push_back(verts[0]); + edgeIndices.push_back(verts[1]); + edgeSharpnesses.push_back(level.GetEdgeSharpness(i)); + } + + for (int i = 0; i < nVerts; ++i) { + vertSharpnesses.push_back(level.GetVertexSharpness(i)); + } + + _numEdges = nEdges; + _numPoints = nVerts; + + ID3D11Device *device = NULL; + _deviceContext->GetDevice(&device); + + SAFE_RELEASE(_edgeIndices); + // create edge index buffer + D3D11_BUFFER_DESC bufferDesc; + ZeroMemory(&bufferDesc, sizeof(bufferDesc)); + bufferDesc.ByteWidth = (int)edgeIndices.size() * sizeof(int); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = sizeof(int); + + D3D11_SUBRESOURCE_DATA subData; + ZeroMemory(&subData, sizeof(subData)); + subData.pSysMem = &edgeIndices[0]; + subData.SysMemPitch = 0; + subData.SysMemSlicePitch = 0; + + HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_edgeIndices); + assert(_edgeIndices); + + // edge sharpness + SAFE_RELEASE(_edgeSharpness); + SAFE_RELEASE(_edgeSharpnessSRV); + ZeroMemory(&bufferDesc, sizeof(bufferDesc)); + bufferDesc.ByteWidth = (int)edgeSharpnesses.size() * sizeof(float); + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = sizeof(float); + + ZeroMemory(&subData, sizeof(subData)); + subData.pSysMem = &edgeSharpnesses[0]; + subData.SysMemPitch = 0; + subData.SysMemSlicePitch = 0; + + hr = device->CreateBuffer(&bufferDesc, &subData, &_edgeSharpness); + assert(_edgeSharpness); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R32_FLOAT; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + srvDesc.Buffer.NumElements = _numEdges; + hr = device->CreateShaderResourceView(_edgeSharpness, &srvDesc, &_edgeSharpnessSRV); + assert(_edgeSharpnessSRV); +} + diff --git a/examples/common/d3d11ControlMeshDisplay.h b/examples/common/d3d11ControlMeshDisplay.h new file mode 100644 index 00000000..22cb9b55 --- /dev/null +++ b/examples/common/d3d11ControlMeshDisplay.h @@ -0,0 +1,65 @@ +// +// Copyright 2015 Pixar +// +// 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: +// +// 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. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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. +// + +#ifndef OPENSUBDIV_EXAMPLES_D3D11_CONTROL_MESH_DISPLAY_H +#define OPENSUBDIV_EXAMPLES_D3D11_CONTROL_MESH_DISPLAY_H + +#include +#include + +class D3D11ControlMeshDisplay { +public: + D3D11ControlMeshDisplay(ID3D11DeviceContext *deviceContext); + ~D3D11ControlMeshDisplay(); + + void Draw(ID3D11Buffer *buffer, int stride, + const float *modelViewProjectionMatrix); + + void SetTopology(OpenSubdiv::Far::TopologyLevel const &level); + + bool GetEdgesDisplay() const { return _displayEdges; } + void SetEdgesDisplay(bool display) { _displayEdges = display; } + bool GetVerticesDisplay() const { return _displayVertices; } + void SetVerticesDisplay(bool display) { _displayVertices = display; } + +private: + bool createProgram(); + + bool _displayEdges; + bool _displayVertices; + + ID3D11DeviceContext *_deviceContext; + ID3D11InputLayout *_inputLayout; + ID3D11VertexShader *_vertexShader; + ID3D11PixelShader *_pixelShader; + ID3D11RasterizerState *_rasterizerState; + ID3D11Buffer *_constantBuffer; + ID3D11ShaderResourceView *_edgeSharpnessSRV; + ID3D11Buffer *_edgeSharpness; + ID3D11Buffer *_edgeIndices; + + int _numEdges, _numPoints; +}; + +#endif // OPENSUBDIV_EXAMPLES_D3D11_CONTROL_MESH_DISPLAY_H diff --git a/examples/common/glControlMeshDisplay.cpp b/examples/common/glControlMeshDisplay.cpp new file mode 100644 index 00000000..6ba5a5e0 --- /dev/null +++ b/examples/common/glControlMeshDisplay.cpp @@ -0,0 +1,224 @@ +// +// Copyright 2015 Pixar +// +// 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: +// +// 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. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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. +// + +#include "glControlMeshDisplay.h" +#include "../common/glUtils.h" + +#include + +GLControlMeshDisplay::GLControlMeshDisplay() : + _displayEdges(true), _displayVertices(false), + _program(0), _vao(0), + _vertSharpness(0), _edgeSharpnessTexture(0), _edgeIndices(0), + _numEdges(0), _numPoints(0) { +} + +GLControlMeshDisplay::~GLControlMeshDisplay() { + if (_program) glDeleteProgram(_program); + if (_vertSharpness) glDeleteBuffers(1, &_vertSharpness); + if (_edgeSharpnessTexture) glDeleteTextures(1, &_edgeSharpnessTexture); + if (_edgeIndices) glDeleteBuffers(1, &_edgeIndices); + if (_vao) glDeleteVertexArrays(1, &_vao); +} + +bool +GLControlMeshDisplay::createProgram() { + if (_program != 0) glDeleteProgram(_program); + + const std::string glsl_version = GLUtils::GetShaderVersionInclude(); + + static const std::string vsSrc = + glsl_version + + "in vec3 position; \n" + "in float vertSharpness; \n" + "out float sharpness; \n" + "uniform mat4 mvpMatrix; \n" + "void main() { \n" + " sharpness = vertSharpness; \n" + " gl_Position = mvpMatrix * vec4(position, 1); \n" + "} \n"; + + static const std::string fsSrc = + glsl_version + + "in float sharpness; \n" + "out vec4 color; \n" + "uniform int drawMode = 0; \n" + "uniform samplerBuffer edgeSharpness; \n" + "vec4 sharpnessToColor(float s) { \n" + " // 0.0 2.0 4.0 \n" + " // green --- yellow --- red \n" + " return vec4(min(1, s * 0.5), \n" + " min(1, 2 - s * 0.5), \n" + " 0, 1); \n" + "} \n" + "void main() { \n" + " float sharp = sharpness; \n" + " if (drawMode == 1) { \n" + " sharp = texelFetch(edgeSharpness, gl_PrimitiveID).x; \n" + " } \n" + " color = sharpnessToColor(sharp); \n" + "} \n"; + + GLuint vertexShader = + GLUtils::CompileShader(GL_VERTEX_SHADER, vsSrc.c_str()); + GLuint fragmentShader = + GLUtils::CompileShader(GL_FRAGMENT_SHADER, fsSrc.c_str()); + + _program = glCreateProgram(); + glAttachShader(_program, vertexShader); + glAttachShader(_program, fragmentShader); + glLinkProgram(_program); + + GLint status; + glGetProgramiv(_program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &infoLogLength); + char *infoLog = new char[infoLogLength]; + glGetProgramInfoLog(_program, infoLogLength, NULL, infoLog); + printf("%s\n", infoLog); + delete[] infoLog; + exit(1); + return false; + } + + _uniformMvpMatrix = + glGetUniformLocation(_program, "mvpMatrix"); + _uniformDrawMode = + glGetUniformLocation(_program, "drawMode"); + _uniformEdgeSharpness = + glGetUniformLocation(_program, "edgeSharpness"); + return true; +} + +void +GLControlMeshDisplay::Draw(GLuint vbo, GLint stride, + const float *modelViewProjectionMatrix) { + if (_program == 0) { + createProgram(); + if (_program == 0) return; + } + + if (_vao == 0) { + glGenVertexArrays(1, &_vao); + } + glBindVertexArray(_vao); + + glUseProgram(_program); + + glUniformMatrix4fv(_uniformMvpMatrix, + 1, GL_FALSE, modelViewProjectionMatrix); + glUniform1i(_uniformEdgeSharpness, 0); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_BUFFER, _edgeSharpnessTexture); + + // bind vbo to points + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0); + glBindBuffer(GL_ARRAY_BUFFER, _vertSharpness); + glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, 0); + + glPointSize(10.0); + + // draw edges + if (_displayEdges) { + glUniform1i(_uniformDrawMode, 1); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _edgeIndices); + glDrawElements(GL_LINES, _numEdges*2, GL_UNSIGNED_INT, 0); + } + + // draw vertices + if (_displayVertices) { + glUniform1i(_uniformDrawMode, 0); + glDrawArrays(GL_POINTS, 0, _numPoints); + } + + glPointSize(1.0f); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + glUseProgram(0); +} + +void +GLControlMeshDisplay::SetTopology(OpenSubdiv::Far::TopologyLevel const &level) { + int nEdges = level.GetNumEdges(); + int nVerts = level.GetNumVertices(); + + std::vector edgeIndices; + std::vector edgeSharpnesses; + std::vector vertSharpnesses; + + edgeIndices.reserve(nEdges * 2); + edgeSharpnesses.reserve(nEdges); + vertSharpnesses.reserve(nVerts); + + for (int i = 0; i < nEdges; ++i) { + OpenSubdiv::Far::ConstIndexArray verts = level.GetEdgeVertices(i); + edgeIndices.push_back(verts[0]); + edgeIndices.push_back(verts[1]); + edgeSharpnesses.push_back(level.GetEdgeSharpness(i)); + } + + for (int i = 0; i < nVerts; ++i) { + vertSharpnesses.push_back(level.GetVertexSharpness(i)); + } + + if (_vertSharpness == 0) glGenBuffers(1, &_vertSharpness); + if (_edgeIndices == 0) glGenBuffers(1, &_edgeIndices); + if (_edgeSharpnessTexture == 0) glGenTextures(1, &_edgeSharpnessTexture); + GLuint buffer = 0; + glGenBuffers(1, &buffer); + + glBindBuffer(GL_ARRAY_BUFFER, _vertSharpness); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*nVerts, + &vertSharpnesses[0], GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, _edgeIndices); + glBufferData(GL_ARRAY_BUFFER, sizeof(int)*nEdges*2, + &edgeIndices[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(float)*nEdges, + &edgeSharpnesses[0], GL_STATIC_DRAW); + + glBindTexture(GL_TEXTURE_BUFFER, _edgeSharpnessTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, buffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDeleteBuffers(1, &buffer); + + _numEdges = nEdges; + _numPoints = nVerts; +} + diff --git a/examples/common/glControlMeshDisplay.h b/examples/common/glControlMeshDisplay.h new file mode 100644 index 00000000..919c35e0 --- /dev/null +++ b/examples/common/glControlMeshDisplay.h @@ -0,0 +1,65 @@ +// +// Copyright 2015 Pixar +// +// 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: +// +// 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. +// +// You may obtain a copy of the Apache License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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. +// + +#ifndef OPENSUBDIV_EXAMPLES_GL_CONTROL_MESH_DISPLAY_H +#define OPENSUBDIV_EXAMPLES_GL_CONTROL_MESH_DISPLAY_H + +#include +#include + +class GLControlMeshDisplay { +public: + GLControlMeshDisplay(); + ~GLControlMeshDisplay(); + + void Draw(GLuint pointsVBO, GLint stride, + const float *modelViewProjectionMatrix); + + void SetTopology(OpenSubdiv::Far::TopologyLevel const &level); + + bool GetEdgesDisplay() const { return _displayEdges; } + void SetEdgesDisplay(bool display) { _displayEdges = display; } + bool GetVerticesDisplay() const { return _displayVertices; } + void SetVerticesDisplay(bool display) { _displayVertices = display; } + +private: + bool createProgram(); + + bool _displayEdges; + bool _displayVertices; + + GLuint _program; + GLuint _uniformMvpMatrix; + GLuint _uniformDrawMode; + GLuint _uniformEdgeSharpness; + + GLuint _vao; + GLuint _vertSharpness; + GLuint _edgeSharpnessTexture; + GLuint _edgeIndices; + + int _numEdges, _numPoints; +}; + +#endif // OPENSUBDIV_EXAMPLES_GL_CONTROL_MESH_DISPLAY_H diff --git a/examples/dxViewer/dxviewer.cpp b/examples/dxViewer/dxviewer.cpp index ca520c17..41d1cd40 100644 --- a/examples/dxViewer/dxviewer.cpp +++ b/examples/dxViewer/dxviewer.cpp @@ -63,6 +63,7 @@ OpenSubdiv::Osd::D3D11LegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; #include "../../regression/common/far_utils.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" +#include "../common/d3d11ControlMeshDisplay.h" #include "../common/d3d11Hud.h" #include "../common/d3d11Utils.h" #include "../common/d3d11ShaderCache.h" @@ -100,8 +101,8 @@ enum EndCap { kEndCapNone = 0, kEndCapGregoryBasis, kEndCapLegacyGregory }; -enum HudCheckBox { kHUD_CB_DISPLAY_CAGE_EDGES, - kHUD_CB_DISPLAY_CAGE_VERTS, +enum HudCheckBox { kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, kHUD_CB_ANIMATE_VERTICES, kHUD_CB_DISPLAY_PATCH_COLOR, kHUD_CB_DISPLAY_PATCH_CVs, @@ -122,8 +123,6 @@ int g_freeze = 0, g_adaptive = 1, g_endCap = kEndCapBSplineBasis, g_singleCreasePatch = 1, - g_drawCageEdges = 1, - g_drawCageVertices = 0, g_drawPatchCVs = 0, g_drawNormals = 0, g_mbutton[3] = {0, 0, 0}; @@ -146,6 +145,8 @@ int g_width = 1024, g_height = 1024; D3D11hud *g_hud = NULL; +D3D11ControlMeshDisplay *g_controlMeshDisplay = NULL; +float g_modelViewProjectionMatrix[16]; // performance float g_cpuTime = 0; @@ -164,10 +165,6 @@ int g_tessLevelMin = 1; int g_kernel = kCPU; float g_moveScale = 0.0f; -std::vector g_coarseEdges; -std::vector g_coarseEdgeSharpness; -std::vector g_coarseVertexSharpness; - ID3D11Device * g_pd3dDevice = NULL; ID3D11DeviceContext * g_pd3dDeviceContext = NULL; IDXGISwapChain * g_pSwapChain = NULL; @@ -278,24 +275,9 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= // save coarse topology (used for coarse mesh drawing) Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + g_controlMeshDisplay->SetTopology(refBaseLevel); - int nedges = refBaseLevel.GetNumEdges(), - nverts = refBaseLevel.GetNumVertices(); - - g_coarseEdges.resize(nedges*2); - g_coarseEdgeSharpness.resize(nedges); - g_coarseVertexSharpness.resize(nverts); - - for(int i=0; iverts; @@ -689,6 +671,8 @@ bindProgram(Effect effect, OpenSubdiv::Osd::PatchArray const & patch) { perspective(pData->ProjectionMatrix, 45.0, aspect, 0.01f, 500.0); multMatrix(pData->ModelViewProjectionMatrix, pData->ModelViewMatrix, pData->ProjectionMatrix); + memcpy(g_modelViewProjectionMatrix, pData->ModelViewProjectionMatrix, sizeof(float) * 16); + g_pd3dDeviceContext->Unmap( g_pcbPerFrame, 0 ); } @@ -884,6 +868,9 @@ display() { patch.GetIndexBase(), 0); } + // draw the control mesh + g_controlMeshDisplay->Draw(buffer, 6, g_modelViewProjectionMatrix); + g_fpsTimer.Stop(); float elapsed = (float)g_fpsTimer.GetElapsed(); g_fpsTimer.Start(); @@ -970,6 +957,9 @@ quit() { if (g_hud) delete g_hud; + if (g_controlMeshDisplay) + delete g_controlMeshDisplay; + SAFE_RELEASE(g_pRasterizerState); SAFE_RELEASE(g_pInputLayout); SAFE_RELEASE(g_pDepthStencilState); @@ -1097,11 +1087,11 @@ callbackSingleCreasePatch(bool checked, int /* a */) { static void callbackCheckBox(bool checked, int button) { switch (button) { - case kHUD_CB_DISPLAY_CAGE_EDGES: - g_drawCageEdges = checked; + case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES: + g_controlMeshDisplay->SetEdgesDisplay(checked); break; - case kHUD_CB_DISPLAY_CAGE_VERTS: - g_drawCageVertices = checked; + case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS: + g_controlMeshDisplay->SetVerticesDisplay(checked); break; case kHUD_CB_ANIMATE_VERTICES: g_moveScale = checked; @@ -1161,23 +1151,28 @@ initHUD() { g_hud->AddPullDownButton(shading_pulldown, "Shaded", 1, g_displayStyle==kShaded); g_hud->AddPullDownButton(shading_pulldown, "Wire+Shaded", 2, g_displayStyle==kWireShaded); -// g_hud->AddCheckBox("Cage Edges (H)", true, 10, 10, callbackDisplayCageEdges, 0, 'H'); -// g_hud->AddCheckBox("Cage Verts (J)", false, 10, 30, callbackDisplayCageVertices, 0, 'J'); -// g_hud->AddCheckBox("Show normal vector (E)", false, 10, 10, callbackDisplayNormal, 0, 'E'); + g_hud->AddCheckBox("Control edges (H)", + g_controlMeshDisplay->GetEdgesDisplay(), + 10, 10, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'H'); + g_hud->AddCheckBox("Control vertices (J)", + g_controlMeshDisplay->GetVerticesDisplay(), + 10, 30, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'J'); - g_hud->AddCheckBox("Patch CVs (L)", false, 10, 10, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_CVs, 'L'); - g_hud->AddCheckBox("Patch Color (P)", true, 10, 30, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_COLOR, 'P'); - g_hud->AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 50, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'M'); - g_hud->AddCheckBox("Freeze (spc)", false, 10, 70, callbackCheckBox, kHUD_CB_FREEZE, ' '); - g_hud->AddCheckBox("Screen space LOD (V)", g_screenSpaceTess != 0, 10, 110, callbackCheckBox, kHUD_CB_VIEW_LOD, 'V'); - g_hud->AddCheckBox("Fractional spacing (T)", g_fractionalSpacing != 0, 10, 130, callbackCheckBox, kHUD_CB_FRACTIONAL_SPACING, 'T'); - g_hud->AddCheckBox("Frustum Patch Culling (B)", g_patchCull != 0, 10, 150, callbackCheckBox, kHUD_CB_PATCH_CULL, 'B'); + g_hud->AddCheckBox("Patch CVs (L)", false, 10, 50, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_CVs, 'L'); + g_hud->AddCheckBox("Patch Color (P)", true, 10, 70, callbackCheckBox, kHUD_CB_DISPLAY_PATCH_COLOR, 'P'); + g_hud->AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 110, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'M'); + g_hud->AddCheckBox("Freeze (spc)", false, 10, 130, callbackCheckBox, kHUD_CB_FREEZE, ' '); + g_hud->AddCheckBox("Screen space LOD (V)", g_screenSpaceTess != 0, 10, 150, callbackCheckBox, kHUD_CB_VIEW_LOD, 'V'); + g_hud->AddCheckBox("Fractional spacing (T)", g_fractionalSpacing != 0, 10, 170, callbackCheckBox, kHUD_CB_FRACTIONAL_SPACING, 'T'); + g_hud->AddCheckBox("Frustum Patch Culling (B)", g_patchCull != 0, 10, 190, callbackCheckBox, kHUD_CB_PATCH_CULL, 'B'); - g_hud->AddCheckBox("Adaptive (`)", true, 10, 190, callbackAdaptive, 0, '`'); - g_hud->AddCheckBox("Single Crease Patch (S)", g_singleCreasePatch!=0, 10, 210, callbackSingleCreasePatch, 0, 'S'); + g_hud->AddCheckBox("Adaptive (`)", true, 10, 230, callbackAdaptive, 0, '`'); + g_hud->AddCheckBox("Single Crease Patch (S)", g_singleCreasePatch!=0, 10, 250, callbackSingleCreasePatch, 0, 'S'); int endcap_pulldown = g_hud->AddPullDown( - "End cap (E)", 10, 230, 200, callbackEndCap, 'E'); + "End cap (E)", 10, 270, 200, callbackEndCap, 'E'); g_hud->AddPullDownButton(endcap_pulldown,"None", kEndCapNone, g_endCap == kEndCapNone); @@ -1194,7 +1189,7 @@ initHUD() { for (int i = 1; i < 11; ++i) { char level[16]; sprintf(level, "Lv. %d", i); - g_hud->AddRadioButton(3, level, i==2, 10, 230+i*20, callbackLevel, i, '0'+(i%10)); + g_hud->AddRadioButton(3, level, i==2, 10, 290+i*20, callbackLevel, i, '0'+(i%10)); } int shapes_pulldown = g_hud->AddPullDown("Shape (N)", -300, 10, 300, callbackModel, 'n'); @@ -1318,6 +1313,9 @@ initD3D11(HWND hWnd) { g_pd3dDevice->CreateDepthStencilState(&depthStencilDesc, &g_pDepthStencilState); assert(g_pDepthStencilState); + // initialize control mesh display + g_controlMeshDisplay = new D3D11ControlMeshDisplay(g_pd3dDeviceContext); + return true; } diff --git a/examples/dxViewer/init_shapes.h b/examples/dxViewer/init_shapes.h index aa9583ee..288832e3 100644 --- a/examples/dxViewer/init_shapes.h +++ b/examples/dxViewer/init_shapes.h @@ -27,76 +27,97 @@ struct ShapeDesc { - ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme) : - name(iname), data(idata), scheme(ischeme) { } + ShapeDesc(char const * iname, std::string const & idata, Scheme ischeme, + bool iIsLeftHanded = false) : + name(iname), data(idata), scheme(ischeme), isLeftHanded(iIsLeftHanded) { } std::string name, - data; + data; Scheme scheme; + bool isLeftHanded; }; static std::vector g_defaultShapes; //------------------------------------------------------------------------------ static void initShapes() { -// g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear) ); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube_creases2", catmark_cube_creases2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_cube", catmark_cube, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_fan", catmark_fan, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_flap", catmark_flap, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_flap2", catmark_flap2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound0", catmark_fvar_bound0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound1", catmark_fvar_bound1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_fvar_bound2", catmark_fvar_bound2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test0", catmark_gregory_test0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_hole_test3", catmark_hole_test3, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_hole_test4", catmark_hole_test4, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_lefthanded", catmark_lefthanded, kCatmark, true /*isLeftHanded*/)); + g_defaultShapes.push_back(ShapeDesc("catmark_righthanded", catmark_righthanded, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pole8", catmark_pole8, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pole64", catmark_pole64, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pole360", catmark_pole360, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole8", catmark_nonman_quadpole8, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole64", catmark_nonman_quadpole64, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_nonman_quadpole360", catmark_nonman_quadpole360, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_tent_creases1", catmark_tent_creases1, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_tent", catmark_tent, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_torus", catmark_torus, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_single_crease", catmark_single_crease, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris0", catmark_smoothtris0, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_smoothtris1", catmark_smoothtris1, kCatmark)); + // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) ); + // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) ); + // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) ); + // g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) ); + g_defaultShapes.push_back(ShapeDesc("catmark_bishop", catmark_bishop, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_car", catmark_car, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_helmet", catmark_helmet, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_pawn", catmark_pawn, kCatmark)); + g_defaultShapes.push_back(ShapeDesc("catmark_rook", catmark_rook, kCatmark)); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner0", catmark_cube_corner0, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner1", catmark_cube_corner1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner2", catmark_cube_corner2, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner3", catmark_cube_corner3, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_corner4", catmark_cube_corner4, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases0", catmark_cube_creases0, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube_creases1", catmark_cube_creases1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_cube", catmark_cube, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgecorner", catmark_dart_edgecorner, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_dart_edgeonly", catmark_dart_edgeonly, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_edgecorner", catmark_edgecorner, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_edgeonly", catmark_edgeonly, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_chaikin0", catmark_chaikin0, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_chaikin1", catmark_chaikin1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_chaikin2", catmark_chaikin2, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_fan", catmark_fan, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_flap", catmark_flap, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_flap2", catmark_flap2, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test1", catmark_gregory_test1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test2", catmark_gregory_test2, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test3", catmark_gregory_test3, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test4", catmark_gregory_test4, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test5", catmark_gregory_test5, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test6", catmark_gregory_test6, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_gregory_test7", catmark_gregory_test7, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_hole_test1", catmark_hole_test1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_hole_test2", catmark_hole_test2, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases0", catmark_pyramid_creases0, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_pyramid_creases1", catmark_pyramid_creases1, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_pyramid", catmark_pyramid, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases0", catmark_tent_creases0, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_tent_creases1", catmark_tent_creases1 , kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_tent", catmark_tent, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_torus", catmark_torus, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_torus_creases0", catmark_torus_creases0, kCatmark ) ); -// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit0", catmark_square_hedit0, kCatmark ) ); -// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit1", catmark_square_hedit1, kCatmark ) ); -// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit2", catmark_square_hedit2, kCatmark ) ); -// g_defaultShapes.push_back( ShapeDesc("catmark_square_hedit3", catmark_square_hedit3, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_bishop", catmark_bishop, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_car", catmark_car, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_helmet", catmark_helmet, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_pawn", catmark_pawn, kCatmark ) ); - g_defaultShapes.push_back( ShapeDesc("catmark_rook", catmark_rook, kCatmark ) ); + g_defaultShapes.push_back(ShapeDesc("bilinear_cube", bilinear_cube, kBilinear)); -// g_defaultShapes.push_back( ShapeDesc("bilinear_cube", bilinear_cube, kBilinear ) ); - -// g_defaultShapes.push_back( ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_cube", loop_cube, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop ) ); -// g_defaultShapes.push_back( ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop ) ); + g_defaultShapes.push_back(ShapeDesc("loop_cube_creases0", loop_cube_creases0, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_cube_creases1", loop_cube_creases1, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_cube", loop_cube, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_icosahedron", loop_icosahedron, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgecorner", loop_saddle_edgecorner, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_saddle_edgeonly", loop_saddle_edgeonly, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgecorner", loop_triangle_edgecorner, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_triangle_edgeonly", loop_triangle_edgeonly, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_chaikin0", loop_chaikin0, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_chaikin1", loop_chaikin1, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_pole8", loop_pole8, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_pole64", loop_pole64, kLoop)); + g_defaultShapes.push_back(ShapeDesc("loop_pole360", loop_pole360, kLoop)); + } -//------------------------------------------------------------------------------ diff --git a/examples/glEvalLimit/glEvalLimit.cpp b/examples/glEvalLimit/glEvalLimit.cpp index bee6eb8d..8a7289cc 100644 --- a/examples/glEvalLimit/glEvalLimit.cpp +++ b/examples/glEvalLimit/glEvalLimit.cpp @@ -82,6 +82,7 @@ GLFWmonitor* g_primary=0; #include "../../regression/common/far_utils.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" +#include "../common/glControlMeshDisplay.h" #include "../common/glHud.h" #include "init_shapes.h" @@ -108,6 +109,13 @@ enum KernelType { kCPU = 0, enum EndCap { kEndCapBSplineBasis, kEndCapGregoryBasis }; +enum HudCheckBox { kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, + kHUD_CB_ANIMATE_VERTICES, + kHUD_CB_ANIMATE_PARTICLES, + kHUD_CB_RANDOM_START, + kHUD_CB_FREEZE }; + enum DrawMode { kUV, kVARYING, kNORMAL, @@ -124,16 +132,10 @@ int g_currentShape = 0, g_endCap = kEndCapBSplineBasis, g_numElements = 3; -std::vector g_coarseEdges; -std::vector g_coarseEdgeSharpness; -std::vector g_coarseVertexSharpness; - int g_running = 1, g_width = 1024, g_height = 1024, g_fullscreen = 0, - g_drawCageEdges = 1, - g_drawCageVertices = 1, g_drawMode = kUV, g_prev_x = 0, g_prev_y = 0, @@ -162,20 +164,20 @@ struct Transform { // performance float g_evalTime = 0; float g_computeTime = 0; +float g_prevTime = 0; +float g_currentTime = 0; Stopwatch g_fpsTimer; //------------------------------------------------------------------------------ int g_nParticles = 65536; bool g_randomStart = true;//false; +bool g_animParticles = true; -GLuint g_cageEdgeVAO = 0, - g_cageEdgeVBO = 0, - g_cageVertexVAO = 0, - g_cageVertexVBO = 0, - g_samplesVAO=0; +GLuint g_samplesVAO=0; GLhud g_hud; +GLControlMeshDisplay g_controlMeshDisplay; //------------------------------------------------------------------------------ struct Program { @@ -204,38 +206,6 @@ createRandomColors(int nverts, int stride, float * colors) { } } -//------------------------------------------------------------------------------ -static void -createCoarseMesh(OpenSubdiv::Far::TopologyRefiner const & refiner) { - - typedef OpenSubdiv::Far::ConstIndexArray IndexArray; - - // save coarse topology (used for coarse mesh drawing) - OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner.GetLevel(0); - - int nedges = refBaseLevel.GetNumEdges(), - nverts = refBaseLevel.GetNumVertices(); - - g_coarseEdges.resize(nedges*2); - g_coarseEdgeSharpness.resize(nedges); - g_coarseVertexSharpness.resize(nverts); - - for(int i=0; iBindVBO(); + } virtual GLuint BindVertexData() const { return _vertexData->BindVBO(); } @@ -416,7 +390,6 @@ private: }; EvalOutputBase *g_evalOutput = NULL; - STParticles * g_particles=0; //------------------------------------------------------------------------------ @@ -426,7 +399,7 @@ updateGeom() { const float *p = &g_orgPositions[0]; - float r = sin(g_frame*0.001f) * g_moveScale; + float r = sin(g_frame*0.1f) * g_moveScale; for (int i = 0; i < nverts; ++i) { //float move = 0.05f*cosf(p[0]*20+g_frame*0.01f); @@ -465,7 +438,9 @@ updateGeom() { // Apply 'dynamics' update assert(g_particles); - g_particles->Update(g_evalTime); // XXXX g_evalTime is not really elapsed time... + float elapsed = g_currentTime - g_prevTime; + g_particles->Update(elapsed); + g_prevTime = g_currentTime; std::vector const &patchCoords = g_particles->GetPatchCoords(); @@ -497,7 +472,6 @@ updateGeom() { static void createOsdMesh(ShapeDesc const & shapeDesc, int level) { - Shape * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme); // create Far mesh (topology) @@ -515,7 +489,15 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) { float speed = g_particles ? g_particles->GetSpeed() : 0.2f; - createCoarseMesh(*topologyRefiner); + // save coarse topology (used for coarse mesh drawing) + g_controlMeshDisplay.SetTopology(topologyRefiner->GetLevel(0)); + + // create random varying color + { + int numCoarseVerts = topologyRefiner->GetLevel(0).GetNumVertices(); + g_varyingColors.resize(numCoarseVerts*3); + createRandomColors(numCoarseVerts, 3, &g_varyingColors[0]); + } Far::StencilTable const * vertexStencils = NULL; Far::StencilTable const * varyingStencils = NULL; @@ -584,9 +566,16 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level) { // note that for patch eval we need coarse+refined combined buffer. int nCoarseVertices = topologyRefiner->GetLevel(0).GetNumVertices(); + // In following template instantiations, same type of vertex buffers are + // used for both source and destination (first and second template + // parameters), since we'd like to draw control mesh wireframe too in + // this example viewer. + // If we don't need to draw the coarse control mesh, the src buffer doesn't + // have to be interoperable to GL (it can be CpuVertexBuffer etc). + delete g_evalOutput; if (g_kernel == kCPU) { - g_evalOutput = new EvalOutput clEvaluatorCache; - g_evalOutput = new EvalOutputGetNumParticles(); g_particles->SetSpeed(speed); + g_prevTime = -1; + g_currentTime = 0; + updateGeom(); delete topologyRefiner; @@ -767,126 +759,6 @@ linkDefaultProgram() { return true; } -//------------------------------------------------------------------------------ -static inline void -setSharpnessColor(float s, float *r, float *g, float *b) { - // 0.0 2.0 4.0 - // green --- yellow --- red - *r = std::min(1.0f, s * 0.5f); - *g = std::min(1.0f, 2.0f - s*0.5f); - *b = 0; -} - -//------------------------------------------------------------------------------ -static void -drawCageEdges() { - - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix, - 1, GL_FALSE, g_transformData.ModelViewMatrix); - glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix, - 1, GL_FALSE, g_transformData.ProjectionMatrix); - glUniform1i(g_defaultProgram.uniformDrawMode, 0); - - std::vector vbo; - vbo.reserve(g_coarseEdges.size() * 6); - float r, g, b; - for (int i = 0; i < (int)g_coarseEdges.size(); i+=2) { - setSharpnessColor(g_coarseEdgeSharpness[i/2], &r, &g, &b); - for (int j = 0; j < 2; ++j) { - vbo.push_back(g_positions[g_coarseEdges[i+j]*3]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+1]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - } - - glBindVertexArray(g_cageEdgeVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageEdgeVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glDisableVertexAttribArray(g_defaultProgram.attrTangentU); - glDisableVertexAttribArray(g_defaultProgram.attrTangentV); - glDisableVertexAttribArray(g_defaultProgram.attrPatchCoord); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (void*)12); - - glDrawArrays(GL_LINES, 0, (int)g_coarseEdges.size()); - - glBindVertexArray(0); - glUseProgram(0); -} - -//------------------------------------------------------------------------------ -static void -drawCageVertices() { - - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewMatrix, - 1, GL_FALSE, g_transformData.ModelViewMatrix); - glUniformMatrix4fv(g_defaultProgram.uniformProjectionMatrix, - 1, GL_FALSE, g_transformData.ProjectionMatrix); - glUniform1i(g_defaultProgram.uniformDrawMode, 0); - - int numPoints = (int)g_positions.size()/3; - std::vector vbo; - vbo.reserve(numPoints*6); - float r, g, b; - for (int i = 0; i < numPoints; ++i) { - - switch (g_drawMode) { - - case kVARYING : { r=g_varyingColors[i*3+0]; - g=g_varyingColors[i*3+1]; - b=g_varyingColors[i*3+2]; - } break; - - case kUV : { setSharpnessColor(g_coarseVertexSharpness[i], &r, &g, &b); - } break; - - default : break; - } - - vbo.push_back(g_positions[i*3+0]); - vbo.push_back(g_positions[i*3+1]); - vbo.push_back(g_positions[i*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - - glBindVertexArray(g_cageVertexVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageVertexVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glDisableVertexAttribArray(g_defaultProgram.attrTangentU); - glDisableVertexAttribArray(g_defaultProgram.attrTangentV); - glDisableVertexAttribArray(g_defaultProgram.attrPatchCoord); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (void*)12); - - glPointSize(10.0f); - glDrawArrays(GL_POINTS, 0, numPoints); - glPointSize(1.0f); - - glBindVertexArray(0); - glUseProgram(0); -} - //------------------------------------------------------------------------------ static void drawSamples() { @@ -976,18 +848,19 @@ display() { drawSamples(); - if (g_drawCageEdges) - drawCageEdges(); - - if (g_drawCageVertices) - drawCageVertices(); + // draw the control mesh + g_controlMeshDisplay.Draw( + g_evalOutput->BindSourceData(), 3*sizeof(float), + g_transformData.ModelViewProjectionMatrix); g_hud.GetFrameBuffer()->ApplyImageShader(); if (g_hud.IsVisible()) { g_fpsTimer.Stop(); - double fps = 1.0/g_fpsTimer.GetElapsed(); + double elapsed = g_fpsTimer.GetElapsed(); g_fpsTimer.Start(); + double fps = 1.0/elapsed; + if (g_animParticles) g_currentTime += (float)elapsed; int nPatchCoords = (int)g_particles->GetPatchCoords().size(); @@ -1180,44 +1053,37 @@ callbackLevel(int l) { createOsdMesh(g_defaultShapes[g_currentShape], g_level); } -//------------------------------------------------------------------------------ -static void -callbackAnimate(bool checked, int /* m */) { - g_moveScale = checked * 3.0f; -} - -//------------------------------------------------------------------------------ -static void -callbackFreeze(bool checked, int /* f */) { - g_freeze = checked; -} - -//------------------------------------------------------------------------------ -static void -callbackCentered(bool checked, int /* f */) { - g_randomStart = checked; - createOsdMesh(g_defaultShapes[g_currentShape], g_level); -} - -//------------------------------------------------------------------------------ -static void -callbackDisplayCageVertices(bool checked, int /* d */) { - g_drawCageVertices = checked; -} - -//------------------------------------------------------------------------------ -static void -callbackDisplayCageEdges(bool checked, int /* d */) { - g_drawCageEdges = checked; -} - //------------------------------------------------------------------------------ static void callbackDisplayVaryingColors(int mode) { g_drawMode = mode; - createOsdMesh(g_defaultShapes[g_currentShape], g_level); } +//------------------------------------------------------------------------------ +static void +callbackCheckBox(bool checked, int button) { + switch (button) { + case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES: + g_controlMeshDisplay.SetEdgesDisplay(checked); + break; + case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS: + g_controlMeshDisplay.SetVerticesDisplay(checked); + break; + case kHUD_CB_ANIMATE_VERTICES: + g_moveScale = checked; + break; + case kHUD_CB_ANIMATE_PARTICLES: + g_animParticles = checked; + break; + case kHUD_CB_RANDOM_START: + g_randomStart = checked; + createOsdMesh(g_defaultShapes[g_currentShape], g_level); + break; + case kHUD_CB_FREEZE: + g_freeze = checked; + break; + } +} //------------------------------------------------------------------------------ static void @@ -1233,12 +1099,23 @@ initHUD() { g_hud.SetFrameBuffer(new GLFrameBuffer); - g_hud.AddCheckBox("Cage Edges (H)", true, 10, 10, callbackDisplayCageEdges, 0, 'h'); - g_hud.AddCheckBox("Cage Verts (J)", true, 10, 30, callbackDisplayCageVertices, 0, 'j'); - g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 50, callbackAnimate, 0, 'm'); - g_hud.AddCheckBox("Freeze (spc)", false, 10, 70, callbackFreeze, 0, ' '); + g_hud.AddCheckBox("Control edges (H)", + g_controlMeshDisplay.GetEdgesDisplay(), + 10, 10, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h'); + g_hud.AddCheckBox("Control vertices (J)", + g_controlMeshDisplay.GetVerticesDisplay(), + 10, 30, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j'); + g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, + 10, 50, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'm'); + g_hud.AddCheckBox("Animate particles (P)", g_animParticles != 0, + 10, 70, callbackCheckBox, kHUD_CB_ANIMATE_PARTICLES, 'p'); + g_hud.AddCheckBox("Freeze (spc)", g_freeze != 0, + 10, 90, callbackCheckBox, kHUD_CB_FREEZE, ' '); - g_hud.AddCheckBox("Random Start", g_randomStart, 10, 120, callbackCentered, 0); + g_hud.AddCheckBox("Random Start", g_randomStart, + 10, 110, callbackCheckBox, kHUD_CB_RANDOM_START); int compute_pulldown = g_hud.AddPullDown("Compute (K)", 475, 10, 300, callbackKernel, 'k'); @@ -1303,22 +1180,12 @@ initGL() { glDepthFunc(GL_LEQUAL); glCullFace(GL_BACK); glEnable(GL_CULL_FACE); - - glGenVertexArrays(1, &g_cageVertexVAO); - glGenVertexArrays(1, &g_cageEdgeVAO); glGenVertexArrays(1, &g_samplesVAO); - glGenBuffers(1, &g_cageVertexVBO); - glGenBuffers(1, &g_cageEdgeVBO); } //------------------------------------------------------------------------------ static void uninitGL() { - - glDeleteBuffers(1, &g_cageVertexVBO); - glDeleteBuffers(1, &g_cageEdgeVBO); - glDeleteVertexArrays(1, &g_cageVertexVAO); - glDeleteVertexArrays(1, &g_cageEdgeVAO); glDeleteVertexArrays(1, &g_samplesVAO); } @@ -1431,6 +1298,8 @@ int main(int argc, char **argv) { initHUD(); callbackModel(g_currentShape); + g_fpsTimer.Start(); + while (g_running) { idle(); display(); diff --git a/examples/glEvalLimit/particles.cpp b/examples/glEvalLimit/particles.cpp index b81ca24f..72676a6c 100644 --- a/examples/glEvalLimit/particles.cpp +++ b/examples/glEvalLimit/particles.cpp @@ -271,7 +271,7 @@ STParticles::~STParticles() { void STParticles::Update(float deltaTime) { - if (fabs(GetSpeed()) < 0.001f) return; + if (deltaTime == 0) return; float speed = GetSpeed() * std::max(0.001f, std::min(deltaTime, 0.5f)); _patchCoords.clear(); diff --git a/examples/glFVarViewer/glFVarViewer.cpp b/examples/glFVarViewer/glFVarViewer.cpp index d52070c9..dd988cba 100644 --- a/examples/glFVarViewer/glFVarViewer.cpp +++ b/examples/glFVarViewer/glFVarViewer.cpp @@ -37,6 +37,7 @@ OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL; #include "../../regression/common/far_utils.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" +#include "../common/glControlMeshDisplay.h" #include "../common/glHud.h" #include "../common/glShaderCache.h" @@ -95,6 +96,7 @@ int g_width = 1600, g_height = 800; GLhud g_hud; +GLControlMeshDisplay g_controlMeshDisplay; // geometry std::vector g_orgPositions, @@ -121,10 +123,6 @@ struct Transform { } g_transformData; GLuint g_vao = 0; -GLuint g_cageEdgeVAO = 0, - g_cageEdgeVBO = 0, - g_cageVertexVAO = 0, - g_cageVertexVBO = 0; std::vector g_coarseEdges; std::vector g_coarseEdgeSharpness; @@ -335,9 +333,10 @@ updateGeom() { //------------------------------------------------------------------------------ static void -createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark) { - - typedef OpenSubdiv::Far::ConstIndexArray IndexArray; +rebuildMesh() { + ShapeDesc const &shapeDesc = g_defaultShapes[g_currentShape]; + int level = g_level; + Scheme scheme = g_defaultShapes[g_currentShape].scheme; Shape * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme); @@ -352,24 +351,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, Scheme scheme = kCatmark) OpenSubdiv::Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); - int nedges = refBaseLevel.GetNumEdges(), - nverts = refBaseLevel.GetNumVertices(); - - g_coarseEdges.resize(nedges*2); - g_coarseEdgeSharpness.resize(nedges); - g_coarseVertexSharpness.resize(nverts); - - for(int i=0; iGetLevel(0)); g_orgPositions=shape->verts; g_normals.resize(g_orgPositions.size(), 0.0f); @@ -450,100 +432,6 @@ fitFrame() { g_uvScale = 1.0; } -//------------------------------------------------------------------------------ -static inline void -setSharpnessColor(float s, float *r, float *g, float *b) { - - // 0.0 2.0 4.0 - // green --- yellow --- red - *r = std::min(1.0f, s * 0.5f); - *g = std::min(1.0f, 2.0f - s*0.5f); - *b = 0; -} - -static void -drawCageEdges() { - - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); - - std::vector vbo; - vbo.reserve(g_coarseEdges.size() * 6); - float r, g, b; - for (int i = 0; i < (int)g_coarseEdges.size(); i+=2) { - setSharpnessColor(g_coarseEdgeSharpness[i/2], &r, &g, &b); - for (int j = 0; j < 2; ++j) { - vbo.push_back(g_positions[g_coarseEdges[i+j]*3]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+1]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - } - - glBindVertexArray(g_cageEdgeVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageEdgeVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (void*)12); - - glDrawArrays(GL_LINES, 0, (int)g_coarseEdges.size()); - - glBindVertexArray(0); - glUseProgram(0); -} - -static void -drawCageVertices() { - - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); - - int numPoints = (int)g_positions.size()/3; - std::vector vbo; - vbo.reserve(numPoints*6); - float r, g, b; - for (int i = 0; i < numPoints; ++i) { - setSharpnessColor(g_coarseVertexSharpness[i], &r, &g, &b); - vbo.push_back(g_positions[i*3+0]); - vbo.push_back(g_positions[i*3+1]); - vbo.push_back(g_positions[i*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - - glBindVertexArray(g_cageVertexVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageVertexVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (void*)12); - - glPointSize(10.0f); - glDrawArrays(GL_POINTS, 0, numPoints); - glPointSize(1.0f); - - glBindVertexArray(0); - glUseProgram(0); -} - //------------------------------------------------------------------------------ union Effect { @@ -851,7 +739,7 @@ display() { glEnable(GL_DEPTH_TEST); // make sure that the vertex buffer is interoped back as a GL resources. - g_mesh->BindVertexBuffer(); + GLuint vbo = g_mesh->BindVertexBuffer(); glBindVertexArray(g_vao); @@ -882,8 +770,9 @@ display() { glBindVertexArray(0); glUseProgram(0); - drawCageEdges(); - drawCageVertices(); + // draw the control mesh + g_controlMeshDisplay.Draw(vbo, 3*sizeof(float), + g_transformData.ModelViewProjectionMatrix); // --------------------------------------------- // uv viewport @@ -981,12 +870,7 @@ mouse(GLFWwindow *, int button, int state, int /* mods */) { static void uninitGL() { - glDeleteBuffers(1, &g_cageVertexVBO); - glDeleteBuffers(1, &g_cageEdgeVBO); glDeleteVertexArrays(1, &g_vao); - glDeleteVertexArrays(1, &g_cageVertexVAO); - glDeleteVertexArrays(1, &g_cageEdgeVAO); - if (g_mesh) delete g_mesh; } @@ -1037,14 +921,6 @@ keyboard(GLFWwindow *, int key, int /* scancode */, int event, int /* mods */) { } //------------------------------------------------------------------------------ -static void -rebuildOsdMesh() { - - createOsdMesh(g_defaultShapes[g_currentShape], - g_level, - g_defaultShapes[g_currentShape].scheme); -} - static void callbackDisplayStyle(int b) { @@ -1055,7 +931,7 @@ static void callbackLevel(int l) { g_level = l; - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1063,7 +939,7 @@ callbackModel(int m) { int maxShapes = static_cast(g_defaultShapes.size()); g_currentShape = std::max(0, std::min(m, maxShapes-1)); - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1071,7 +947,7 @@ callbackAdaptive(bool checked, int /* a */) { if (GLUtils::SupportsAdaptiveTessellation()) { g_adaptive = checked; - rebuildOsdMesh(); + rebuildMesh(); } } @@ -1101,7 +977,7 @@ callbackBoundary(int b) { g_fvarBoundary = SdcOptions::FVAR_LINEAR_ALL; break; } - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1166,10 +1042,6 @@ initGL() { glEnable(GL_CULL_FACE); glGenVertexArrays(1, &g_vao); - glGenVertexArrays(1, &g_cageVertexVAO); - glGenVertexArrays(1, &g_cageEdgeVAO); - glGenBuffers(1, &g_cageVertexVBO); - glGenBuffers(1, &g_cageEdgeVBO); } //------------------------------------------------------------------------------ @@ -1297,7 +1169,7 @@ int main(int argc, char ** argv) { glfwSwapInterval(0); initHUD(); - rebuildOsdMesh(); + rebuildMesh(); while (g_running) { idle(); diff --git a/examples/glPtexViewer/glPtexViewer.cpp b/examples/glPtexViewer/glPtexViewer.cpp index e91251a9..db475e06 100644 --- a/examples/glPtexViewer/glPtexViewer.cpp +++ b/examples/glPtexViewer/glPtexViewer.cpp @@ -95,6 +95,7 @@ OpenSubdiv::Osd::GLMeshInterface *g_mesh; #include "../../regression/common/far_utils.h" #include "../common/stopwatch.h" #include "../common/simple_math.h" +#include "../common/glControlMeshDisplay.h" #include "../common/glHud.h" #include "../common/glUtils.h" #include "../common/hdr_reader.h" @@ -127,7 +128,7 @@ enum HudCheckBox { HUD_CB_ADAPTIVE, HUD_CB_DISPLAY_OCCLUSION, HUD_CB_DISPLAY_NORMALMAP, HUD_CB_DISPLAY_SPECULAR, - HUD_CB_CAGE_EDGES, + HUD_CB_CONTROL_MESH_EDGES, HUD_CB_ANIMATE_VERTICES, HUD_CB_VIEW_LOD, HUD_CB_FRACTIONAL_SPACING, @@ -178,7 +179,6 @@ int g_frame = 0, int g_fullscreen = 0, g_wire = DISPLAY_SHADED, g_drawNormals = 0, - g_drawCageEdges = 0, g_mbutton[3] = {0, 0, 0}, g_level = 1, g_tessLevel = 2, @@ -219,6 +219,7 @@ float g_rotate[2] = {0, 0}, g_pan[2] = {0, 0}, g_center[3] = {0, 0, 0}, g_size = 0; +float g_modelViewProjection[16]; int g_prev_x = 0, g_prev_y = 0; @@ -228,6 +229,7 @@ int g_width = 1024, g_height = 1024; GLhud g_hud; +GLControlMeshDisplay g_controlMeshDisplay; // performance float g_cpuTime = 0; @@ -246,10 +248,8 @@ std::vector > g_animPositions; GLuint g_queries[2] = {0, 0}; GLuint g_vao = 0; -GLuint g_cageEdgeVAO = 0; GLuint g_skyVAO = 0; GLuint g_edgeIndexBuffer = 0; -GLuint g_numCageEdges = 0; GLuint g_diffuseEnvironmentMap = 0; GLuint g_specularEnvironmentMap = 0; @@ -886,8 +886,6 @@ createOsdMesh(int level, int kernel) { g_positions=shape->verts; - typedef OpenSubdiv::Far::ConstIndexArray IndexArray; - // create Far mesh (topology) OpenSubdiv::Sdc::SchemeType sdctype = GetSdcType(*shape); OpenSubdiv::Sdc::Options sdcoptions = GetSdcOptions(*shape); @@ -897,17 +895,7 @@ createOsdMesh(int level, int kernel) { OpenSubdiv::Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - - // create cage edge index - OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); - - int nedges = refBaseLevel.GetNumEdges(); - std::vector edgeIndices(nedges*2); - for(int i=0; iGetLevel(0)); delete shape; @@ -1036,24 +1024,6 @@ createOsdMesh(int level, int kernel) { } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_mesh->GetPatchTable()->GetPatchIndexBuffer()); - // ------ Cage VAO - glBindVertexArray(g_cageEdgeVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_mesh->BindVertexBuffer()); - - if (g_adaptive) { - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); - } else { - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0); - } - if (not g_edgeIndexBuffer) glGenBuffers(1, &g_edgeIndexBuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_edgeIndexBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*edgeIndices.size(), - &edgeIndices[0], GL_STATIC_DRAW); - g_numCageEdges = (int)edgeIndices.size(); - glBindVertexArray(0); } @@ -1148,6 +1118,9 @@ updateConstantUniformBlock() { constantData.ProjectionMatrix); inverseMatrix(constantData.ModelViewInverseMatrix, constantData.ModelViewMatrix); + // save mvp for the control mesh drawing + memcpy(g_modelViewProjection, constantData.ModelViewProjectionMatrix, + 16*sizeof(float)); // lighs Constant::Light light0 = { { 0.6f, 1.0f, 0.6f, 0.0f }, @@ -1362,34 +1335,6 @@ drawSky() { //------------------------------------------------------------------------------ -void -drawCageEdges() { - - g_mesh->BindVertexBuffer(); - - glBindVertexArray(g_cageEdgeVAO); - - Effect effect; - effect.value = 0; - - EffectDesc effectDesc( - OpenSubdiv::Far::PatchDescriptor( - OpenSubdiv::Far::PatchDescriptor::LINES), effect); - - GLDrawConfig *config = g_shaderCache.GetDrawConfig(effectDesc); - if (!config) return; - - glUseProgram(config->GetProgram()); - glDrawElements(GL_LINES, g_numCageEdges, GL_UNSIGNED_INT, 0); - - glBindVertexArray(0); - glUseProgram(0); - - GLUtils::CheckGLErrors("draw cage edges"); -} - -//------------------------------------------------------------------------------ - void display() { @@ -1427,8 +1372,13 @@ display() { glEndQuery(GL_TIME_ELAPSED); #endif - if (g_drawCageEdges) - drawCageEdges(); + // draw the control mesh + { + GLuint vbo = g_mesh->BindVertexBuffer(); + int stride = g_adaptive ? 3 : 6; + g_controlMeshDisplay.Draw(vbo, stride*sizeof(float), + g_modelViewProjection); + } if (g_wire == DISPLAY_WIRE) { glEnable(GL_CULL_FACE); @@ -1544,7 +1494,6 @@ void uninitGL() { glDeleteQueries(2, g_queries); glDeleteVertexArrays(1, &g_vao); - glDeleteVertexArrays(1, &g_cageEdgeVAO); glDeleteVertexArrays(1, &g_skyVAO); if (g_mesh) @@ -1627,8 +1576,8 @@ callbackCheckBox(bool checked, int button) { case HUD_CB_DISPLAY_SPECULAR: g_specular = checked; break; - case HUD_CB_CAGE_EDGES: - g_drawCageEdges = checked; + case HUD_CB_CONTROL_MESH_EDGES: + g_controlMeshDisplay.SetEdgesDisplay(checked); break; case HUD_CB_ANIMATE_VERTICES: g_moveScale = checked ? 1.0f : 0.0f; @@ -1739,7 +1688,6 @@ initGL() { glGenQueries(2, g_queries); glGenVertexArrays(1, &g_vao); - glGenVertexArrays(1, &g_cageEdgeVAO); glGenVertexArrays(1, &g_skyVAO); glBindTexture(GL_TEXTURE_2D, 0); @@ -1918,6 +1866,8 @@ int main(int argc, char ** argv) { g_hud.SetFrameBuffer(new GLFrameBuffer); + g_controlMeshDisplay.SetEdgesDisplay(false); + if (occlusionFilename != NULL) { g_hud.AddCheckBox("Ambient Occlusion (A)", g_occlusion, -200, 570, callbackCheckBox, HUD_CB_DISPLAY_OCCLUSION, 'a'); @@ -1931,8 +1881,10 @@ int main(int argc, char ** argv) { -200, 610, callbackCheckBox, HUD_CB_IBL, 'i'); } - g_hud.AddCheckBox("Cage Edges (H)", g_drawCageEdges != 0, - 10, 10, callbackCheckBox, HUD_CB_CAGE_EDGES, 'h'); + g_hud.AddCheckBox("Control edges (H)", + g_controlMeshDisplay.GetEdgesDisplay(), + 10, 10, callbackCheckBox, + HUD_CB_CONTROL_MESH_EDGES, 'h'); g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0.0, 10, 30, callbackCheckBox, HUD_CB_ANIMATE_VERTICES, 'm'); g_hud.AddCheckBox("Screen space LOD (V)", g_screenSpaceTess, diff --git a/examples/glStencilViewer/glStencilViewer.cpp b/examples/glStencilViewer/glStencilViewer.cpp index 60dadc91..84e2df26 100644 --- a/examples/glStencilViewer/glStencilViewer.cpp +++ b/examples/glStencilViewer/glStencilViewer.cpp @@ -32,6 +32,7 @@ GLFWmonitor* g_primary=0; #include "../common/stopwatch.h" #include "../common/simple_math.h" #include "../common/glHud.h" +#include "../common/glControlMeshDisplay.h" #include #include @@ -97,6 +98,12 @@ enum KernelType { kCPU = 0, kGLXFB, kGLCompute }; +enum HudCheckBox { kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, + kHUD_CB_ANIMATE_VERTICES, + kHUD_CB_FREEZE, + kHUD_CB_BILINEAR }; + int g_kernel = kCPU, g_isolationLevel = 5; // max level of extraordinary feature isolation @@ -104,8 +111,6 @@ int g_running = 1, g_width = 1024, g_height = 1024, g_fullscreen = 0, - g_drawCageEdges = 1, - g_drawCageVertices = 1, g_prev_x = 0, g_prev_y = 0, g_mbutton[3] = {0, 0, 0}, @@ -136,21 +141,13 @@ Stopwatch g_fpsTimer; std::vector g_orgPositions; std::vector g_positions; -std::vector g_coarseEdges; -std::vector g_coarseEdgeSharpness; -std::vector g_coarseVertexSharpness; - int g_nsamples=2000, g_nsamplesDrawn=0; -GLuint g_cageEdgeVAO = 0, - g_cageEdgeVBO = 0, - g_cageVertexVAO = 0, - g_cageVertexVBO = 0, - g_stencilsVAO = 0; +GLuint g_stencilsVAO = 0; GLhud g_hud; - +GLControlMeshDisplay g_controlMeshDisplay; //------------------------------------------------------------------------------ @@ -166,6 +163,7 @@ public: virtual ~StencilOutputBase() {} virtual void UpdateData(const float *src, int startVertex, int numVertices) = 0; virtual void EvalStencils() = 0; + virtual GLuint BindSrcBuffer() = 0; virtual GLuint BindDstBuffer() = 0; virtual int GetNumStencils() const = 0; }; @@ -223,6 +221,9 @@ public: evalInstance, _deviceContext); } + virtual GLuint BindSrcBuffer() { + return _srcData->BindVBO(); + } virtual GLuint BindDstBuffer() { return _dstData->BindVBO(); } @@ -288,7 +289,6 @@ updateGeom() { static void createMesh(ShapeDesc const & shapeDesc, int level) { - typedef Far::ConstIndexArray IndexArray; typedef Far::LimitStencilTableFactory::LocationArray LocationArray; Shape const * shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme); @@ -304,25 +304,11 @@ createMesh(ShapeDesc const & shapeDesc, int level) { // save coarse topology (used for coarse mesh drawing) OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); - int nedges = refBaseLevel.GetNumEdges(), - nverts = refBaseLevel.GetNumVertices(); + g_controlMeshDisplay.SetTopology(refBaseLevel); + int nverts = refBaseLevel.GetNumVertices(); - g_coarseEdges.resize(nedges*2); - g_coarseEdgeSharpness.resize(nedges); - g_coarseVertexSharpness.resize(nverts); - - for(int i=0; iverts; + // save rest pose + g_orgPositions = shape->verts; if (g_bilinear) { Far::TopologyRefiner::UniformOptions options(level); @@ -370,14 +356,14 @@ createMesh(ShapeDesc const & shapeDesc, int level) { delete g_stencilOutput; if (g_kernel == kCPU) { - g_stencilOutput = new StencilOutput( g_controlStencils, nverts); #ifdef OPENSUBDIV_HAS_OPENMP } else if (g_kernel == kOPENMP) { - g_stencilOutput = new StencilOutput( @@ -385,7 +371,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) { #endif #ifdef OPENSUBDIV_HAS_TBB } else if (g_kernel == kTBB) { - g_stencilOutput = new StencilOutput( @@ -393,7 +379,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) { #endif #ifdef OPENSUBDIV_HAS_CUDA } else if (g_kernel == kCUDA) { - g_stencilOutput = new StencilOutput( @@ -402,7 +388,7 @@ createMesh(ShapeDesc const & shapeDesc, int level) { #ifdef OPENSUBDIV_HAS_OPENCL } else if (g_kernel == kCL) { static Osd::EvaluatorCacheT clEvaluatorCache; - g_stencilOutput = new StencilOutput vbo; - vbo.reserve(g_coarseEdges.size() * 6); - - float r, g, b; - for (int i = 0; i < (int)g_coarseEdges.size(); i+=2) { - setSharpnessColor(g_coarseEdgeSharpness[i/2], &r, &g, &b); - for (int j = 0; j < 2; ++j) { - vbo.push_back(g_positions[g_coarseEdges[i+j]*3]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+1]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - } - - glBindVertexArray(g_cageEdgeVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageEdgeVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - g_cageProgram.EnableVertexAttributes(); - - glDrawArrays(GL_LINES, 0, (int)g_coarseEdges.size()); - - glBindVertexArray(0); - glUseProgram(0); -} - -//------------------------------------------------------------------------------ -static void -drawCageVertices() { - - g_cageProgram.Use( ); - - glUniformMatrix4fv(g_cageProgram.GetUniformModelViewProjectionMatrix(), - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); - - int numPoints = (int)g_positions.size()/3; - std::vector vbo; - vbo.reserve(numPoints*6); - - float r, g, b; - for (int i = 0; i < numPoints; ++i) { - - setSharpnessColor(g_coarseVertexSharpness[i], &r, &g, &b); - - vbo.push_back(g_positions[i*3+0]); - vbo.push_back(g_positions[i*3+1]); - vbo.push_back(g_positions[i*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - - glBindVertexArray(g_cageVertexVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageVertexVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - g_cageProgram.EnableVertexAttributes(); - - glPointSize(10.0f); - glDrawArrays(GL_POINTS, 0, numPoints); - glPointSize(1.0f); - - glBindVertexArray(0); - glUseProgram(0); -} //------------------------------------------------------------------------------ static void @@ -801,9 +666,6 @@ drawStencils() { glBindVertexArray(g_stencilsVAO); -// int numEdges = g_controlStencils->GetNumStencils() * 3; -// g_samplesProgram.EnableVertexAttributes(); - glBindBuffer(GL_ARRAY_BUFFER, g_stencilOutput->BindDstBuffer()); glEnableVertexAttribArray(0); @@ -813,8 +675,6 @@ drawStencils() { glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*9, (void*)(sizeof(GLfloat)*3)); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*9, (void*)(sizeof(GLfloat)*6)); -// g_samplesProgram.EnableVertexAttributes(); - glDrawArrays(GL_POINTS, 0, g_stencilOutput->GetNumStencils()); glDisableVertexAttribArray(0); @@ -854,13 +714,12 @@ display() { glEnable(GL_DEPTH_TEST); - if (g_drawCageEdges) - drawCageEdges(); - - if (g_drawCageVertices) - drawCageVertices(); - drawStencils(); + + // draw the control mesh + g_controlMeshDisplay.Draw(g_stencilOutput->BindSrcBuffer(), 3*sizeof(float), + g_transformData.ModelViewProjectionMatrix); + s.Stop(); float drawCpuTime = float(s.GetElapsed() * 1000.0f); s.Start(); @@ -1028,41 +887,6 @@ callbackLevel(int l) { rebuildMesh(); } - -//------------------------------------------------------------------------------ -static void -callbackAnimate(bool checked, int /* m */) { - - g_moveScale = checked; -} - -//------------------------------------------------------------------------------ -static void -callbackFreeze(bool checked, int /* f */) { - - g_freeze = checked; -} - -//------------------------------------------------------------------------------ -static void -callbackDisplayCageVertices(bool checked, int /* d */) { - - g_drawCageVertices = checked; -} - -//------------------------------------------------------------------------------ -static void -callbackDisplayCageEdges(bool checked, int /* d */) { - g_drawCageEdges = checked; -} - -static void -callbackBilinear(bool checked, int /* a */) { - g_bilinear = checked; - rebuildMesh(); -} - - //------------------------------------------------------------------------------ static void callbackModel(int m) { @@ -1078,6 +902,28 @@ callbackModel(int m) { rebuildMesh(); } +//------------------------------------------------------------------------------ +static void +callbackCheckBox(bool checked, int button) { + switch (button) { + case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES: + g_controlMeshDisplay.SetEdgesDisplay(checked); + break; + case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS: + g_controlMeshDisplay.SetVerticesDisplay(checked); + break; + case kHUD_CB_ANIMATE_VERTICES: + g_moveScale = checked; + break; + case kHUD_CB_FREEZE: + g_freeze = checked; + break; + case kHUD_CB_BILINEAR: + g_bilinear = checked; + rebuildMesh(); + } +} + //------------------------------------------------------------------------------ static void initHUD() { @@ -1093,12 +939,20 @@ initHUD() { g_hud.SetFrameBuffer(new GLFrameBuffer); - g_hud.AddCheckBox("Cage Edges (H)", true, 10, 10, callbackDisplayCageEdges, 0, 'h'); - g_hud.AddCheckBox("Cage Verts (J)", true, 10, 30, callbackDisplayCageVertices, 0, 'j'); - g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 50, callbackAnimate, 0, 'm'); - g_hud.AddCheckBox("Freeze (spc)", false, 10, 70, callbackFreeze, 0, ' '); - - g_hud.AddCheckBox("Bilinear Stencils (`)", g_bilinear!=0, 10, 190, callbackBilinear, 0, '`'); + g_hud.AddCheckBox("Control edges (H)", + g_controlMeshDisplay.GetEdgesDisplay(), + 10, 10, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h'); + g_hud.AddCheckBox("Control vertices (J)", + g_controlMeshDisplay.GetVerticesDisplay(), + 10, 30, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j'); + g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, + 10, 50, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'm'); + g_hud.AddCheckBox("Freeze (spc)", g_freeze != 0, + 10, 70, callbackCheckBox, kHUD_CB_FREEZE, ' '); + g_hud.AddCheckBox("Bilinear Stencils (`)", g_bilinear != 0, + 10, 190, callbackCheckBox, kHUD_CB_BILINEAR, '`'); int compute_pulldown = g_hud.AddPullDown("Compute (K)", 250, 10, 300, callbackKernel, 'k'); g_hud.AddPullDownButton(compute_pulldown, "CPU", kCPU); @@ -1145,23 +999,12 @@ initGL() { glCullFace(GL_BACK); glEnable(GL_CULL_FACE); - glGenVertexArrays(1, &g_cageVertexVAO); - glGenVertexArrays(1, &g_cageEdgeVAO); glGenVertexArrays(1, &g_stencilsVAO); - - glGenBuffers(1, &g_cageVertexVBO); - glGenBuffers(1, &g_cageEdgeVBO); } //------------------------------------------------------------------------------ static void uninitGL() { - - glDeleteBuffers(1, &g_cageVertexVBO); - glDeleteBuffers(1, &g_cageEdgeVBO); - - glDeleteVertexArrays(1, &g_cageVertexVAO); - glDeleteVertexArrays(1, &g_cageEdgeVAO); glDeleteVertexArrays(1, &g_stencilsVAO); } diff --git a/examples/glViewer/glViewer.cpp b/examples/glViewer/glViewer.cpp index d0e83c55..405062a8 100644 --- a/examples/glViewer/glViewer.cpp +++ b/examples/glViewer/glViewer.cpp @@ -73,15 +73,18 @@ OpenSubdiv::Osd::GLMeshInterface *g_mesh = NULL; OpenSubdiv::Osd::GLLegacyGregoryPatchTable *g_legacyGregoryPatchTable = NULL; #include "../../regression/common/far_utils.h" -#include "../common/stopwatch.h" -#include "../common/simple_math.h" #include "../common/glHud.h" +#include "../common/glUtils.h" +#include "../common/glControlMeshDisplay.h" +#include "../common/glShaderCache.h" #include "../common/objAnim.h" #include "../common/patchColors.h" -#include "../common/glShaderCache.h" +#include "../common/simple_math.h" +#include "../common/stopwatch.h" #include + /* 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 @@ -145,8 +148,8 @@ enum EndCap { kEndCapNone = 0, kEndCapGregoryBasis, kEndCapLegacyGregory }; -enum HudCheckBox { kHUD_CB_DISPLAY_CAGE_EDGES, - kHUD_CB_DISPLAY_CAGE_VERTS, +enum HudCheckBox { kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, kHUD_CB_ANIMATE_VERTICES, kHUD_CB_DISPLAY_PATCH_COLOR, kHUD_CB_VIEW_LOD, @@ -174,8 +177,6 @@ int g_fullscreen = 0, g_adaptive = 1, g_endCap = kEndCapBSplineBasis, g_singleCreasePatch = 1, - g_drawCageEdges = 1, - g_drawCageVertices = 0, g_mbutton[3] = {0, 0, 0}, g_running = 1; @@ -198,6 +199,7 @@ int g_width = 1024, g_height = 1024; GLhud g_hud; +GLControlMeshDisplay g_controlMeshDisplay; // performance float g_cpuTime = 0; @@ -205,10 +207,7 @@ float g_gpuTime = 0; Stopwatch g_fpsTimer; // geometry -std::vector g_orgPositions, - g_positions; - -Scheme g_scheme; +std::vector g_orgPositions; int g_level = 2; int g_tessLevel = 1; @@ -232,23 +231,6 @@ struct Transform { } g_transformData; GLuint g_vao = 0; -GLuint g_cageEdgeVAO = 0, - g_cageEdgeVBO = 0, - g_cageVertexVAO = 0, - g_cageVertexVBO = 0; - -std::vector g_coarseEdges; -std::vector g_coarseEdgeSharpness; -std::vector g_coarseVertexSharpness; - -struct Program -{ - GLuint program; - GLuint uniformModelViewProjectionMatrix; - GLuint attrPosition; - GLuint attrColor; -} g_defaultProgram; - // XXX: // this struct meant to be used as a stopgap entity until we fully implement @@ -300,62 +282,6 @@ struct FVarData GLuint textureBuffer; } g_fvarData; -static bool -linkDefaultProgram() { - - const std::string glsl_version = GLUtils::GetShaderVersionInclude(); - - - static const std::string vsSrc = - glsl_version + - "in vec3 position;\n" - "in vec3 color;\n" - "out vec4 fragColor;\n" - "uniform mat4 ModelViewProjectionMatrix;\n" - "void main() {\n" - " fragColor = vec4(color, 1);\n" - " gl_Position = ModelViewProjectionMatrix * " - " vec4(position, 1);\n" - "}\n"; - - static const std::string fsSrc = - glsl_version + - "in vec4 fragColor;\n" - "out vec4 color;\n" - "void main() {\n" - " color = fragColor;\n" - "}\n"; - - GLuint program = glCreateProgram(); - GLuint vertexShader = GLUtils::CompileShader(GL_VERTEX_SHADER, vsSrc.c_str()); - GLuint fragmentShader = GLUtils::CompileShader(GL_FRAGMENT_SHADER, fsSrc.c_str()); - - glAttachShader(program, vertexShader); - glAttachShader(program, fragmentShader); - - glLinkProgram(program); - - GLint status; - glGetProgramiv(program, GL_LINK_STATUS, &status); - if (status == GL_FALSE) { - GLint infoLogLength; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); - char *infoLog = new char[infoLogLength]; - glGetProgramInfoLog(program, infoLogLength, NULL, infoLog); - printf("%s\n", infoLog); - delete[] infoLog; - exit(1); - } - - g_defaultProgram.program = program; - g_defaultProgram.uniformModelViewProjectionMatrix = - glGetUniformLocation(program, "ModelViewProjectionMatrix"); - g_defaultProgram.attrPosition = glGetAttribLocation(program, "position"); - g_defaultProgram.attrColor = glGetAttribLocation(program, "color"); - - return true; -} - //------------------------------------------------------------------------------ #include "init_shapes.h" @@ -380,16 +306,6 @@ updateGeom() { g_objAnim->InterpolatePositions(g_animTime, &vertex[0], stride); - if (g_drawCageEdges or g_drawCageVertices) { - g_positions.resize(nverts*3); - for (int i=0; iGetShape(); } else { - shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme, shapeDesc.isLeftHanded); + shape = Shape::parseObj(shapeDesc.data.c_str(), shapeDesc.scheme, + shapeDesc.isLeftHanded); } // create Far mesh (topology) @@ -526,39 +430,17 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= Far::TopologyRefinerFactory::Options(sdctype, sdcoptions)); // save coarse topology (used for coarse mesh drawing) - OpenSubdiv::Far::TopologyLevel const & refBaseLevel = refiner->GetLevel(0); + g_controlMeshDisplay.SetTopology(refiner->GetLevel(0)); - int nedges = refBaseLevel.GetNumEdges(), - nverts = refBaseLevel.GetNumVertices(); - - g_coarseEdges.resize(nedges*2); - g_coarseEdgeSharpness.resize(nedges); - g_coarseVertexSharpness.resize(nverts); - - for(int i=0; iverts; - - g_positions.resize(g_orgPositions.size(),0.0f); + g_orgPositions = shape->verts; delete g_mesh; g_mesh = NULL; - g_scheme = scheme; - // Adaptive refinement currently supported only for catmull-clark scheme - bool doAdaptive = (g_adaptive!=0 and g_scheme==kCatmark), + bool doAdaptive = (g_adaptive!=0 and scheme==kCatmark), interleaveVarying = g_displayStyle == kInterleavedVaryingColor, - doSingleCreasePatch = (g_singleCreasePatch!=0 and g_scheme==kCatmark); + doSingleCreasePatch = (g_singleCreasePatch!=0 and scheme==kCatmark); Osd::MeshBitset bits; bits.set(Osd::MeshAdaptive, doAdaptive); @@ -573,6 +455,7 @@ createOsdMesh(ShapeDesc const & shapeDesc, int level, int kernel, Scheme scheme= int numVaryingElements = (g_displayStyle == kVaryingColor or interleaveVarying) ? 4 : 0; + if (kernel == kCPU) { g_mesh = new Osd::Mesh vbo; - vbo.reserve(g_coarseEdges.size() * 6); - float r, g, b; - for (int i = 0; i < (int)g_coarseEdges.size(); i+=2) { - setSharpnessColor(g_coarseEdgeSharpness[i/2], &r, &g, &b); - for (int j = 0; j < 2; ++j) { - vbo.push_back(g_positions[g_coarseEdges[i+j]*3]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+1]); - vbo.push_back(g_positions[g_coarseEdges[i+j]*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - } - - glBindVertexArray(g_cageEdgeVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageEdgeVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (void*)12); - - glDrawArrays(GL_LINES, 0, (int)g_coarseEdges.size()); - - glBindVertexArray(0); - glUseProgram(0); -} - -static void -drawCageVertices() { - - glUseProgram(g_defaultProgram.program); - glUniformMatrix4fv(g_defaultProgram.uniformModelViewProjectionMatrix, - 1, GL_FALSE, g_transformData.ModelViewProjectionMatrix); - - int numPoints = (int)g_positions.size()/3; - std::vector vbo; - vbo.reserve(numPoints*6); - float r, g, b; - for (int i = 0; i < numPoints; ++i) { - setSharpnessColor(g_coarseVertexSharpness[i], &r, &g, &b); - vbo.push_back(g_positions[i*3+0]); - vbo.push_back(g_positions[i*3+1]); - vbo.push_back(g_positions[i*3+2]); - vbo.push_back(r); - vbo.push_back(g); - vbo.push_back(b); - } - - glBindVertexArray(g_cageVertexVAO); - - glBindBuffer(GL_ARRAY_BUFFER, g_cageVertexVBO); - glBufferData(GL_ARRAY_BUFFER, (int)vbo.size() * sizeof(float), &vbo[0], - GL_STATIC_DRAW); - - glEnableVertexAttribArray(g_defaultProgram.attrPosition); - glEnableVertexAttribArray(g_defaultProgram.attrColor); - glVertexAttribPointer(g_defaultProgram.attrPosition, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, 0); - glVertexAttribPointer(g_defaultProgram.attrColor, - 3, GL_FLOAT, GL_FALSE, sizeof (GLfloat) * 6, (void*)12); - - glPointSize(10.0f); - glDrawArrays(GL_POINTS, 0, numPoints); - glPointSize(1.0f); - - glBindVertexArray(0); - glUseProgram(0); -} - //------------------------------------------------------------------------------ union Effect { @@ -902,7 +692,6 @@ public: // compile shader program - GLDrawConfig *config = new GLDrawConfig(GLUtils::GetShaderVersionInclude().c_str()); Far::PatchDescriptor::Type type = effectDesc.desc.GetType(); @@ -1339,11 +1128,12 @@ display() { if (g_displayStyle == kWire) glEnable(GL_CULL_FACE); - if (g_drawCageEdges) - drawCageEdges(); + // draw the control mesh + int stride = g_displayStyle == kInterleavedVaryingColor ? 7 : 3; + g_controlMeshDisplay.Draw(vbo, stride*sizeof(float), + g_transformData.ModelViewProjectionMatrix); - if (g_drawCageVertices) - drawCageVertices(); + glBindBuffer(GL_ARRAY_BUFFER, 0); fb->ApplyImageShader(); @@ -1390,19 +1180,18 @@ display() { 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, "Scheme : %s", g_scheme==kBilinear ? "BILINEAR" : (g_scheme == kLoop ? "LOOP" : "CATMARK")); y+= 20; g_hud.DrawString(10, y, "GPU Kernel : %.3f ms", g_gpuTime); y+= 20; - 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; + 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; g_hud.Flush(); } glFinish(); - //checkGLErrors("display leave"); + GLUtils::CheckGLErrors("display leave\n"); } //------------------------------------------------------------------------------ @@ -1453,12 +1242,7 @@ static void uninitGL() { glDeleteQueries(2, g_queries); - - glDeleteBuffers(1, &g_cageVertexVBO); - glDeleteBuffers(1, &g_cageEdgeVBO); glDeleteVertexArrays(1, &g_vao); - glDeleteVertexArrays(1, &g_cageVertexVAO); - glDeleteVertexArrays(1, &g_cageEdgeVAO); if (g_mesh) delete g_mesh; @@ -1514,11 +1298,6 @@ keyboard(GLFWwindow *, int key, int /* scancode */, int event, int /* mods */) { } //------------------------------------------------------------------------------ -static void -rebuildOsdMesh() { - createOsdMesh( g_defaultShapes[ g_currentShape ], g_level, g_kernel, g_defaultShapes[ g_currentShape ].scheme ); -} - static void callbackDisplayStyle(int b) { if (g_displayStyle == kVaryingColor or b == kVaryingColor or @@ -1526,7 +1305,7 @@ callbackDisplayStyle(int b) { g_displayStyle == kFaceVaryingColor or b == kFaceVaryingColor) { // need to rebuild for varying reconstruct g_displayStyle = b; - rebuildOsdMesh(); + rebuildMesh(); return; } g_displayStyle = b; @@ -1535,7 +1314,7 @@ callbackDisplayStyle(int b) { static void callbackEndCap(int endCap) { g_endCap = endCap; - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1559,13 +1338,13 @@ callbackKernel(int k) { } #endif - rebuildOsdMesh(); + rebuildMesh(); } static void callbackLevel(int l) { g_level = l; - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1577,7 +1356,7 @@ callbackModel(int m) { m = (int)g_defaultShapes.size() - 1; g_currentShape = m; - rebuildOsdMesh(); + rebuildMesh(); } static void @@ -1587,11 +1366,11 @@ callbackCheckBox(bool checked, int button) { switch(button) { case kHUD_CB_ADAPTIVE: g_adaptive = checked; - rebuildOsdMesh(); + rebuildMesh(); return; case kHUD_CB_SINGLE_CREASE_PATCH: g_singleCreasePatch = checked; - rebuildOsdMesh(); + rebuildMesh(); return; default: break; @@ -1599,11 +1378,11 @@ callbackCheckBox(bool checked, int button) { } switch (button) { - case kHUD_CB_DISPLAY_CAGE_EDGES: - g_drawCageEdges = checked; + case kHUD_CB_DISPLAY_CONTROL_MESH_EDGES: + g_controlMeshDisplay.SetEdgesDisplay(checked); break; - case kHUD_CB_DISPLAY_CAGE_VERTS: - g_drawCageVertices = checked; + case kHUD_CB_DISPLAY_CONTROL_MESH_VERTS: + g_controlMeshDisplay.SetVerticesDisplay(checked); break; case kHUD_CB_ANIMATE_VERTICES: g_moveScale = checked; @@ -1642,10 +1421,14 @@ initHUD() { g_hud.SetFrameBuffer(new SSAOGLFrameBuffer); - g_hud.AddCheckBox("Cage Edges (H)", g_drawCageEdges != 0, - 10, 10, callbackCheckBox, kHUD_CB_DISPLAY_CAGE_EDGES, 'h'); - g_hud.AddCheckBox("Cage Verts (J)", g_drawCageVertices != 0, - 10, 30, callbackCheckBox, kHUD_CB_DISPLAY_CAGE_VERTS, 'j'); + g_hud.AddCheckBox("Control edges (H)", + g_controlMeshDisplay.GetEdgesDisplay(), + 10, 10, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_EDGES, 'h'); + g_hud.AddCheckBox("Control vertices (J)", + g_controlMeshDisplay.GetVerticesDisplay(), + 10, 30, callbackCheckBox, + kHUD_CB_DISPLAY_CONTROL_MESH_VERTS, 'j'); g_hud.AddCheckBox("Animate vertices (M)", g_moveScale != 0, 10, 50, callbackCheckBox, kHUD_CB_ANIMATE_VERTICES, 'm'); g_hud.AddCheckBox("Patch Color (P)", g_displayPatchColor != 0, @@ -1741,10 +1524,6 @@ initGL() { glGenQueries(2, g_queries); glGenVertexArrays(1, &g_vao); - glGenVertexArrays(1, &g_cageVertexVAO); - glGenVertexArrays(1, &g_cageEdgeVAO); - glGenBuffers(1, &g_cageVertexVBO); - glGenBuffers(1, &g_cageEdgeVBO); } //------------------------------------------------------------------------------ @@ -1892,12 +1671,11 @@ int main(int argc, char ** argv) { g_adaptive = GLUtils::SupportsAdaptiveTessellation(); initGL(); - linkDefaultProgram(); glfwSwapInterval(0); initHUD(); - rebuildOsdMesh(); + rebuildMesh(); while (g_running) { idle();