The article shows how to create a simple vtk render window project and show it in the web browser. We need emscripten tool and the visualization toolkit installed.
emscripten : https://emscripten.org/docs/getting_started/downloads.html
VTK: https://vtk.org/
Build the VTK source to get JS library before our coding.
This example uses C plus plus programming language to create and show a cone in the 3D world.
CMakeLists.txt
project(wasmTester)
if (VTK_VERSION VERSION_LESS "8.9") #"9.0.3"
find_package( VTK REQUIRED )
else ()
find_package( VTK COMPONENTS vtkCommonCore vtkRenderingCore
vtkInteractionStyle vtkRenderingOpenGL2 vtkFiltersSources
vtkRenderingFreeType IOGeometry )
endif()
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
)
if(EMSCRIPTEN)
set(emscripten_options)
list(APPEND emscripten_options
"--bind"
"-O3"
"-g"
"-DLOG_OFF"
"SHELL:-s USE_SDL=2"
"SHELL:-s EXPORTED_RUNTIME_METHODS=['allocate,stringToUTF8,UTF8ToString,FS,intArrayFromString']"
"SHELL:-s EXTRA_EXPORTED_RUNTIME_METHODS=['ALLOC_NORMAL']"
"SHELL:-s -fdebug-compilation-dir=."
"SHELL:-s EXPORT_NAME=tester"
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
"SHELL:-s DEMANGLE_SUPPORT=1"
"SHELL:-s EMULATE_FUNCTION_POINTER_CASTS=0"
"SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=0"
"SHELL:-s MODULARIZE=1"
"SHELL:-s WASM=1"
"SHELL:-s --no-heap-copy"
"SHELL:-s INITIAL_MEMORY=200MB"
"SHELL:-s MAXIMUM_MEMORY=512MB"
"SHELL:-s ASSERTIONS=2"
"SHELL:-s TOTAL_MEMORY=512MB"
"SHELL:-s DISABLE_EXCEPTION_CATCHING=0"
)
message("Configuring data directory for wasm..........")
endif()
set( cpps
main.cpp
)
add_executable(${PROJECT_NAME} ${cpps})
if (VTK_VERSION VERSION_LESS "8.9")
# old system
include(${VTK_USE_FILE})
else ()
# vtk_module_autoinit is needed
message("autoinit module for higher version vtk")
vtk_module_autoinit(
TARGETS ${PROJECT_NAME}
MODULES ${VTK_LIBRARIES}
)
endif ()
target_compile_options(${PROJECT_NAME}
PUBLIC
${emscripten_options}
)
target_link_options(${PROJECT_NAME}
PUBLIC
${emscripten_options}
)
target_link_libraries( ${PROJECT_NAME} ${VTK_LIBRARIES} ${LINK_FLAGS} )
# -----------------------------------------------------------------------------
# Copy HTML to build directory
# -----------------------------------------------------------------------------
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND
${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/index.html"
$<TARGET_FILE_DIR:wasmTester>
)
main.cpp
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#ifdef __EMSCRIPTEN__
#include "vtkSDL2OpenGLRenderWindow.h"
#include "vtkSDL2RenderWindowInteractor.h"
#endif // __EMSCRIPTEN__
#define vtkSPtr vtkSmartPointer
#define vtkSPtrNew(Var, Type) vtkSPtr<Type> Var = vtkSPtr<Type>::New();
using namespace std;
int main()
{
vtkSPtrNew( cone, vtkConeSource );
vtkSPtrNew( mapper, vtkPolyDataMapper );
mapper->SetInputConnection( cone->GetOutputPort() );
vtkSPtrNew( actor, vtkActor );
actor->SetMapper( mapper );
vtkSPtrNew( renderer, vtkRenderer );
renderer->AddActor(actor);
renderer->SetBackground( 0, 0, 0 );
#ifdef __EMSCRIPTEN__
vtkSPtrNew(renderWindow, vtkSDL2OpenGLRenderWindow);
#else
vtkSPtrNew(renderWindow, vtkRenderWindow);
#endif
renderWindow->AddRenderer( renderer );
#ifdef __EMSCRIPTEN__
vtkSPtrNew(renderWindowInteractor, vtkSDL2RenderWindowInteractor);
#else
vtkSPtrNew(renderWindowInteractor, vtkRenderWindowInteractor);
#endif
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
index.html
<html>
<head>
<!-- Load WebAssembly module -->
<script type="text/javascript" src="wasmTester.js"></script>
</head>
<body>
<canvas id="canvas" style="position: absolute; left: 0; top: 0; width:100%; height:100%"></canvas>
<script>
var Module = {
canvas: (function() {
var canvas = document.getElementById('canvas');
canvas.addEventListener(
"webglcontextlost",
function(e) {
console.error('WebGL context lost. You will need to reload the page.');
e.preventDefault();
},
false
);
return canvas;
})(),
onRuntimeInitialized: function() {
console.log('initialized');
},
};
var app = tester(Module);
console.log('App created');
</script>
</body>
</html>
After cmake and make, we can set up a simple http service to watch the result.
python3 -m http.server 4000
The code files tree:
how can I generate wasm file with js file? I used emcmake, but it didn’t generate them..
Just `emcmake cmake` to generate Makefile, then use `make` to build project, there will be JS and WASM files.
Thank you for your useful shares.
I’m trying to integrate vtk-wasm into a Reactjs project but getting a lot of errors. Can you make a sample?
Yep, I’m busy with other task these days, please wait for me to publish a new post about it.