Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matcap #23

Merged
merged 23 commits into from Jan 27, 2020
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -121,7 +121,7 @@ if(WIN32)
endif()

if (EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s WASM=1 --no-heap-copy -s USE_WEBGL2=1 -s ALLOW_MEMORY_GROWTH=1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -s WASM=1 --no-heap-copy -s USE_WEBGL2=1 -s ALLOW_MEMORY_GROWTH=1 -s MINIFY_HTML=0")
set(CMAKE_EXECUTABLE_SUFFIX ".html")
endif()

Expand Down
2 changes: 1 addition & 1 deletion docs/mpview.html
@@ -1 +1 @@
<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><style>body{margin:0;padding:0;overflow:hidden}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}canvas.emscripten{border:0 none;padding:0;background-color:#fff;width:100vw;height:100vh;max-height:100vh;display:block;overflow:hidden}</style></head><body><div class=emscripten id=status>Downloading...</div><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault()></canvas><script>var statusElement=document.getElementById("status"),progressElement=document.getElementById("progress");function getUrlVars(){var o={};window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(e,t,n){o[t]=n});return o}var Module={preRun:[function(){var e=getUrlVars().model;if(e){var t=e.split("/").pop();console.log("reading "+e),Module.arguments=[t],FS.createPreloadedFile("./",t,e,!0,!1)}}],postRun:[],print:function(e){console.log(e)},printErr:function(e){console.error(e)},canvas:function(){var e=document.getElementById("canvas");return e.addEventListener("webglcontextlost",function(e){alert("WebGL context lost. You will need to reload the page."),e.preventDefault()},!1),e}(),setStatus:function(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Date.now()<30||(progressElement.hidden=t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),!1):(progressElement.value=null,!(progressElement.max=null)),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies:function(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=function(){Module.setStatus("Exception thrown, see JavaScript console"),Module.setStatus=function(e){e&&Module.printErr("[post-exception status] "+e)}}</script><script async src=mpview.js></script></body></html>
<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><style>body{margin:0;padding:0;overflow:hidden}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}canvas.emscripten{border:0 none;padding:0;background-color:#fff;width:100vw;height:100vh;max-height:100vh;display:block;overflow:hidden}</style></head><body><div class=emscripten id=status>Downloading...</div><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault()></canvas><script>var statusElement=document.getElementById("status"),progressElement=document.getElementById("progress");function getUrlVars(){var o={};window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(e,t,n){o[t]=n});return o}var Module={preRun:[function(){window.frameElement&&window.frameElement.hasAttribute("controls")&&(console.log("show gui"),Module.arguments.push("-g"));var e=getUrlVars().model;if(!e&&window.frameElement&&window.frameElement.hasAttribute("model")&&(e=window.frameElement.getAttribute("model")),e){var t=e.split("/").pop();console.log("reading "+e),Module.arguments=[t],FS.createPreloadedFile("./",t,e,!0,!1)}}],postRun:[],print:function(e){console.log(e)},printErr:function(e){console.error(e)},canvas:function(){var e=document.getElementById("canvas");return e.addEventListener("webglcontextlost",function(e){alert("WebGL context lost. You will need to reload the page."),e.preventDefault()},!1),e}(),setStatus:function(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Date.now()<30||(progressElement.hidden=t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),!1):(progressElement.value=null,!(progressElement.max=null)),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies:function(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=function(){Module.setStatus("Exception thrown, see JavaScript console"),Module.setStatus=function(e){e&&Module.printErr("[post-exception status] "+e)}}</script><script async src=mpview.js></script></body></html>
2 changes: 1 addition & 1 deletion docs/mpview.js

Large diffs are not rendered by default.

Binary file modified docs/mpview.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion src/apps/CMakeLists.txt
Expand Up @@ -19,7 +19,7 @@ if (EMSCRIPTEN)

add_executable(mpview mpview.cpp MeshProcessingViewer.cpp MeshProcessingViewer.h data/shell.html)
target_link_libraries(mpview pmp_vis)
set_target_properties(mpview PROPERTIES LINK_FLAGS "--shell-file ${CMAKE_CURRENT_SOURCE_DIR}/data/shell.html --preload-file ${PROJECT_SOURCE_DIR}/external/pmp-data/off/mario.off@input.off")
set_target_properties(mpview PROPERTIES LINK_FLAGS "--shell-file ${CMAKE_CURRENT_SOURCE_DIR}/data/shell.html --preload-file ${PROJECT_SOURCE_DIR}/external/pmp-data/off/bunny.off@input.off")

add_executable(subdiv subdiv.cpp data/shell.html)
target_link_libraries(subdiv pmp_vis)
Expand Down
84 changes: 52 additions & 32 deletions src/apps/data/shell.html
Expand Up @@ -31,55 +31,75 @@
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');

function getUrlVars()
{
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
var urlParams = new URLSearchParams(window.location.search);
var frameElem = window.frameElement;

function hasParam(name) {
if (urlParams && urlParams.has(name))
return true;
else if (frameElem && frameElem.hasAttribute(name))
return true;
return false;
}

function getParam(name) {
if (urlParams && urlParams.has(name))
return urlParams.get(name);
else if (frameElem && frameElem.hasAttribute(name))
return frameElem.getAttribute(name);
return undefined;
}

function getFile(name) {
var base = (window.location != window.parent.location) ? document.referrer : document.location.href;
var url = new URL(name, base);
var path = url.pathname;
var file = path.split('/').pop();
return [ file, path ];
}

// here we collect the command line arguments to pass to the main function
var argv = [];

var Module = {

preRun: [ function(){
// GUI controls speficied as iframe attribute?
if (window.frameElement && window.frameElement.hasAttribute("controls"))

// show imgui controls?
if (hasParam('controls'))
{
// we are in an iframe which has 'controls' property
// start with '-g', which shows gui controls
Module.arguments.push("-g");
argv.push("-g");
}

// filename specified as URI query?
var modelFileName = getUrlVars()["model"];

// filename specified as iframe attribute?
if (!modelFileName && window.frameElement && window.frameElement.hasAttribute("model"))
// model to be loaded
if (hasParam('model'))
{
modelFileName = window.frameElement.getAttribute("model");
var [filename, pathname ] = getFile(getParam('model'));
FS.createPreloadedFile('./', filename, pathname, true, false);
argv.push(filename);
}

// do we have a filename?
if ( modelFileName )
// matcap to be used
if (hasParam('material'))
{
var filename = modelFileName.split('/').pop();
Module.arguments = [filename];
FS.createPreloadedFile('./', filename, modelFileName, true, false);
var [filename, pathname] = getFile(getParam('material'));
FS.createPreloadedFile('./', filename, pathname, true, false);
argv.push("-m");
argv.push(filename);
}

// matcap specified as iframe attribute?
if (window.frameElement && window.frameElement.hasAttribute("material"))
// texture to be used
if (hasParam('texture'))
{
var matFileName = window.frameElement.getAttribute("material");
var filename = matFileName.split('/').pop();
Module.arguments.push("-m");
Module.arguments.push(filename);
FS.createPreloadedFile('./', filename, matFileName, true, false);
var [filename, pathname] = getFile(getParam('texture'));
FS.createPreloadedFile('./', filename, pathname, true, false);
argv.push("-t");
argv.push(filename);
}

}],


arguments: argv,

postRun: [],

print: function(text) {
Expand Down
17 changes: 17 additions & 0 deletions src/apps/mview.cpp
Expand Up @@ -19,6 +19,7 @@ void usage_and_exit()
<< "Options\n"
<< " -g: show GUI controls (toggle with 'g')\n"
<< " -t: specify texture image (mesh has to provide texture coordinates)\n"
<< " -m: specify matcap image\n"
<< "\n";
exit(1);
}
Expand All @@ -29,6 +30,7 @@ int main(int argc, char** argv)
{
char* input = nullptr;
char* texture = nullptr;
char* matcap = nullptr;
bool gui = false;

// parse command line parameters
Expand All @@ -46,6 +48,14 @@ int main(int argc, char** argv)
++i;
}
}
else if (std::string(argv[i]) == std::string("-m"))
{
if (i+1 < argc)
{
matcap = argv[i+1];
++i;
}
}
else if (std::string(argv[i]) == std::string("-h"))
{
usage_and_exit();
Expand All @@ -64,7 +74,14 @@ int main(int argc, char** argv)
MeshViewer viewer("MeshViewer", 800, 600, gui);
viewer.load_mesh(input);
if (texture)
{
viewer.load_texture(texture, GL_SRGB8);
}
else if (matcap)
{
viewer.load_matcap(matcap);
}

return viewer.run();
}

Expand Down
63 changes: 63 additions & 0 deletions src/pmp/visualization/MatCapShader.h
@@ -0,0 +1,63 @@
//=============================================================================
// Copyright (C) 2011-2018 The pmp-library developers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright should be bumped to 2020

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for new files or for changed files?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be updated to current year on every change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated for all files that changed

//
// This file is part of the Polygon Mesh Processing Library.
// Distributed under a MIT-style license, see LICENSE.txt for details.
//
// SPDX-License-Identifier: MIT-with-employer-disclaimer
//=============================================================================

// clang-format off

// mat-cap shader: assume view=(0,0,-1), then the tex-coord for
// spherical environment mapping is just the normal's XY
// scaled by 0.5 and shifted by 0.5.
// scale by 0.49 to avoid artifacts at gracing angles
static const char* matcap_vshader =
#ifndef __EMSCRIPTEN__
"#version 330"
#else
"#version 300 es"
#endif
R"glsl(
layout (location=0) in vec4 v_position;
layout (location=1) in vec3 v_normal;
out vec3 v2f_normal;
uniform mat4 modelview_projection_matrix;
uniform mat3 normal_matrix;

void main()
{
v2f_normal = normalize(normal_matrix * v_normal);
gl_Position = modelview_projection_matrix * v_position;
}
)glsl";


static const char* matcap_fshader =
#ifndef __EMSCRIPTEN__
"#version 330"
#else
"#version 300 es"
#endif
R"glsl(
precision mediump float;

in vec3 v2f_normal;
uniform sampler2D matcap;
uniform float alpha;
out vec4 f_color;

void main()
{
vec2 uv = normalize(v2f_normal).xy * 0.49 + 0.5;
vec4 rgba = texture(matcap, uv);
rgba.a *= alpha;
f_color = rgba;
}
)glsl";


//=============================================================================
// clang-format on
//=============================================================================
10 changes: 10 additions & 0 deletions src/pmp/visualization/MeshViewer.cpp
Expand Up @@ -84,6 +84,16 @@ bool MeshViewer::load_mesh(const char* filename)

//-----------------------------------------------------------------------------

bool MeshViewer::load_matcap(const char* filename)
{
if (!mesh_.load_matcap(filename))
return false;
set_draw_mode("Texture");
return true;
}

//-----------------------------------------------------------------------------

bool MeshViewer::load_texture(const char* filename, GLint format,
GLint min_filter, GLint mag_filter, GLint wrap)
{
Expand Down
3 changes: 3 additions & 0 deletions src/pmp/visualization/MeshViewer.h
Expand Up @@ -36,6 +36,9 @@ class MeshViewer : public TrackballViewer
//! load a mesh from file \c filename
virtual bool load_mesh(const char* filename);

//! load a matcap texture from file \c filename
bool load_matcap(const char* filename);

//! load a texture from file \c filename
bool load_texture(const char* filename, GLint format = GL_RGB,
GLint min_filter = GL_LINEAR_MIPMAP_LINEAR,
Expand Down