../samples/qt/AndroidQt/ReadMe.md
../samples/java/jniviewer/ReadMe.md
../samples/ios/UIKitSample/ReadMe.md
+../samples/webgl/ReadMe.md
tutorial/tutorial.md
| Linux | GNU gcc 4.3+ <br> LLVM CLang 3.6+ |
| OS X / macOS | XCode 6 or newer |
| Android | NDK r10, GNU gcc 4.8 or newer |
+| Web | Emscripten SDK 1.39 or newer (CLang) |
1) VC++ 141 64-bit is used for regular testing and for building binary package of official release of OCCT on Windows.
@figure{/overview/images/sample_ios_uikit.png}
See \subpage occt_samples_ios_uikit "iOS sample Readme" for details.
+
+@subsubsection OCCT_OVW_SECTION_7_3_6 Web
+
+WebGL Viewer sample demonstrating usage of OCCT 3D Viewer in Web browser with Emscripten SDK can be found in `samples/webgl`.
+
+@figure{/overview/images/sample_webgl.png}
+
+See \subpage occt_samples_webgl "WebGL sample Readme" for details.
--- /dev/null
+/build
+/work
--- /dev/null
+cmake_minimum_required(VERSION 3.2)
+
+project(occt-webgl-sample)
+
+set(CMAKE_CXX_STANDARD 11)
+set(APP_VERSION_MAJOR 1)
+set(APP_VERSION_MINOR 0)
+set(APP_TARGET occt-webgl-sample)
+
+# customize build
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_WEBGL2=1")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ALLOW_MEMORY_GROWTH=1")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s SAFE_HEAP=1")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s NO_EXIT_RUNTIME=1")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s TOTAL_MEMORY=16MB")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s ABORTING_MALLOC=0")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s FORCE_FILESYSTEM=1")
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --preload-file myFile")
+
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR})
+file(GLOB SOURCES
+ *.h
+ *.cpp
+)
+source_group ("Headers" FILES
+ WasmOcctView.h)
+source_group ("Sources" FILES
+ WasmOcctView.cpp
+ main.cpp)
+
+# FreeType
+find_package(freetype REQUIRED NO_DEFAULT_PATH)
+if(freetype_FOUND)
+ message (STATUS "Using FreeType from \"${freetype_DIR}\"" )
+else()
+ message(WARNING "Could not find FreeType, please set freetype_DIR variable." )
+endif()
+
+# Open CASCADE Technology
+find_package(OpenCASCADE REQUIRED NO_DEFAULT_PATH)
+if(OpenCASCADE_FOUND)
+ message (STATUS "Using OpenCASCADE from \"${OpenCASCADE_DIR}\"" )
+ INCLUDE_DIRECTORIES(${OpenCASCADE_INCLUDE_DIR})
+ LINK_DIRECTORIES(${OpenCASCADE_LIBRARY_DIR})
+else()
+ message(WARNING "Could not find OpenCASCADE, please set OpenCASCADE_DIR variable." )
+ set(OCCT_LIBRARY_DIR)
+ set(OCCT_BIN_DIR)
+endif()
+
+set(OpenCASCADE_LIBS TKRWMesh TKBinXCAF TKBin TKBinL TKOpenGl TKXCAF TKVCAF TKCAF TKV3d TKHLR TKMesh TKService TKShHealing TKPrim TKTopAlgo TKGeomAlgo TKBRep TKGeomBase TKG3d TKG2d TKMath TKLCAF TKCDF TKernel)
+
+add_executable(${APP_TARGET} ${SOURCES})
+target_link_libraries(
+ ${APP_TARGET}
+ ${OpenCASCADE_LIBS}
+ freetype
+)
+set_target_properties(${APP_TARGET} PROPERTIES LINK_FLAGS "-s EXPORTED_FUNCTIONS=['_main','_onFileDataRead'] -s EXTRA_EXPORTED_RUNTIME_METHODS=['ccall','cwrap']")
+
+install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}")
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.wasm DESTINATION ${CMAKE_INSTALL_PREFIX})
+install(FILES occt-webgl-sample.html DESTINATION ${CMAKE_INSTALL_PREFIX})
+install(FILES ${OpenCASCADE_RESOURCE_DIR}/DrawResources/OCC_logo.png DESTINATION ${CMAKE_INSTALL_PREFIX})
+install(FILES ${OpenCASCADE_RESOURCE_DIR}/DrawResources/lamp.ico DESTINATION ${CMAKE_INSTALL_PREFIX})
--- /dev/null
+OCCT WebGL Viewer sample {#occt_samples_webgl}
+==================
+
+This sample demonstrates simple way of using OCCT libraries in Web application written in C++ and translated into WebAssembly module using Emscripten SDK (emsdk):
+https://emscripten.org/
+
+Sample consists of the Open CASCADE 3D Viewer with a button for opening a model in BREP format.
+The sample requires a WebGL 2.0 capable browser supporting WebAssembly 1.0 (Wasm).
+
+Installation and configuration:
+ 1. Install Emscripten SDK and activate minimal configuration (Python, Java and CLang) following *emsdk* documentation. Activate also MinGW when building sample on Windows host.
+ 2. Build (using *emsdk*) or download FreeType static library.
+ 3. Configure CMake for building Open CASCADE Technology (OCCT) static libraries (BUILD_LIBRARY_TYPE="Static").
+ For this, activate *emsdk* command prompt, configure CMake for building OCCT using cross-compilation toolchain, disable *BUILD_MODULE_Draw*.
+ 4. Perform building and installation steps.
+~~~~~
+ > ${EMSDK}/fastcomp/emscripten/cmake/Modules/Platform/Emscripten.cmake
+~~~~~
+ 5. Configure CMake for building this WebGL sample using *emsdk* with paths to OCCT and FreeType. Perform building and installation steps.
+ 6. Copy data/occ/Ball.brep from OCCT into "samples" folder within WebGL sample installation path.
+ 7. Navigate to installation folder and start web server from it; Python coming with *emsdk* can be used for this purpose:
+~~~~~
+ > python -m SimpleHTTPServer 8080
+~~~~~
+ 8. Open compatible browser and enter path taking into account your web server settings:
+~~~~~
+ > http://localhost:8080/occt-webgl-sample.html
+~~~~~
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
+
+#include "WasmOcctView.h"
+
+#include "WasmVKeys.h"
+
+#include <AIS_Shape.hxx>
+#include <AIS_ViewCube.hxx>
+#include <Aspect_Handle.hxx>
+#include <Aspect_DisplayConnection.hxx>
+#include <Aspect_NeutralWindow.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <OpenGl_GraphicDriver.hxx>
+#include <Prs3d_DatumAspect.hxx>
+
+#include <iostream>
+
+#define THE_CANVAS_ID "canvas"
+
+namespace
+{
+ EM_JS(int, jsCanvasGetWidth, (), {
+ return canvas.width;
+ });
+
+ EM_JS(int, jsCanvasGetHeight, (), {
+ return canvas.height;
+ });
+
+ EM_JS(float, jsDevicePixelRatio, (), {
+ var aDevicePixelRatio = window.devicePixelRatio || 1;
+ return aDevicePixelRatio;
+ });
+
+ //! Return cavas size in pixels.
+ static Graphic3d_Vec2i jsCanvasSize()
+ {
+ return Graphic3d_Vec2i (jsCanvasGetWidth(), jsCanvasGetHeight());
+ }
+}
+
+// ================================================================
+// Function : WasmOcctView
+// Purpose :
+// ================================================================
+WasmOcctView::WasmOcctView()
+: myDevicePixelRatio (1.0f),
+ myUpdateRequests (0)
+{
+}
+
+// ================================================================
+// Function : ~WasmOcctView
+// Purpose :
+// ================================================================
+WasmOcctView::~WasmOcctView()
+{
+}
+
+// ================================================================
+// Function : run
+// Purpose :
+// ================================================================
+void WasmOcctView::run()
+{
+ initWindow();
+ initViewer();
+ initDemoScene();
+ if (myView.IsNull())
+ {
+ return;
+ }
+
+ myView->MustBeResized();
+ myView->Redraw();
+
+ // There is no inifinite message loop, main() will return from here immediately.
+ // Tell that our Module should be left loaded and handle events through callbacks.
+ //emscripten_set_main_loop (redrawView, 60, 1);
+ //emscripten_set_main_loop (redrawView, -1, 1);
+ EM_ASM(Module['noExitRuntime'] = true);
+}
+
+// ================================================================
+// Function : initWindow
+// Purpose :
+// ================================================================
+void WasmOcctView::initWindow()
+{
+ myDevicePixelRatio = jsDevicePixelRatio();
+ myCanvasId = THE_CANVAS_ID;
+ const char* aTargetId = !myCanvasId.IsEmpty() ? myCanvasId.ToCString() : NULL;
+ const EM_BOOL toUseCapture = EM_TRUE;
+ emscripten_set_resize_callback (NULL, this, toUseCapture, onResizeCallback);
+
+ emscripten_set_mousedown_callback (NULL, this, toUseCapture, onMouseCallback);
+ emscripten_set_mouseup_callback (NULL, this, toUseCapture, onMouseCallback);
+ emscripten_set_mousemove_callback (NULL, this, toUseCapture, onMouseCallback);
+ emscripten_set_dblclick_callback (aTargetId, this, toUseCapture, onMouseCallback);
+ emscripten_set_click_callback (aTargetId, this, toUseCapture, onMouseCallback);
+ emscripten_set_mouseenter_callback (aTargetId, this, toUseCapture, onMouseCallback);
+ emscripten_set_mouseleave_callback (aTargetId, this, toUseCapture, onMouseCallback);
+ emscripten_set_wheel_callback (aTargetId, this, toUseCapture, onWheelCallback);
+
+ emscripten_set_touchstart_callback (aTargetId, this, toUseCapture, onTouchCallback);
+ emscripten_set_touchend_callback (aTargetId, this, toUseCapture, onTouchCallback);
+ emscripten_set_touchmove_callback (aTargetId, this, toUseCapture, onTouchCallback);
+ emscripten_set_touchcancel_callback(aTargetId, this, toUseCapture, onTouchCallback);
+
+ //emscripten_set_keypress_callback (NULL, this, toUseCapture, onKeyCallback);
+ emscripten_set_keydown_callback (NULL, this, toUseCapture, onKeyDownCallback);
+ emscripten_set_keyup_callback (NULL, this, toUseCapture, onKeyUpCallback);
+}
+
+// ================================================================
+// Function : dumpGlInfo
+// Purpose :
+// ================================================================
+void WasmOcctView::dumpGlInfo (bool theIsBasic)
+{
+ TColStd_IndexedDataMapOfStringString aGlCapsDict;
+ myView->DiagnosticInformation (aGlCapsDict, theIsBasic ? Graphic3d_DiagnosticInfo_Basic : Graphic3d_DiagnosticInfo_Complete);
+ if (theIsBasic)
+ {
+ TCollection_AsciiString aViewport;
+ aGlCapsDict.FindFromKey ("Viewport", aViewport);
+ aGlCapsDict.Clear();
+ aGlCapsDict.Add ("Viewport", aViewport);
+ }
+ aGlCapsDict.Add ("Display scale", TCollection_AsciiString(myDevicePixelRatio));
+
+ // beautify output
+ {
+ TCollection_AsciiString* aGlVer = aGlCapsDict.ChangeSeek ("GLversion");
+ TCollection_AsciiString* aGlslVer = aGlCapsDict.ChangeSeek ("GLSLversion");
+ if (aGlVer != NULL
+ && aGlslVer != NULL)
+ {
+ *aGlVer = *aGlVer + " [GLSL: " + *aGlslVer + "]";
+ aGlslVer->Clear();
+ }
+ }
+
+ TCollection_AsciiString anInfo;
+ for (TColStd_IndexedDataMapOfStringString::Iterator aValueIter (aGlCapsDict); aValueIter.More(); aValueIter.Next())
+ {
+ if (!aValueIter.Value().IsEmpty())
+ {
+ if (!anInfo.IsEmpty())
+ {
+ anInfo += "\n";
+ }
+ anInfo += aValueIter.Key() + ": " + aValueIter.Value();
+ }
+ }
+
+ ::Message::DefaultMessenger()->Send (anInfo, Message_Warning);
+}
+
+// ================================================================
+// Function : initPixelScaleRatio
+// Purpose :
+// ================================================================
+void WasmOcctView::initPixelScaleRatio()
+{
+ SetTouchToleranceScale (myDevicePixelRatio);
+ if (!myView.IsNull())
+ {
+ myView->ChangeRenderingParams().Resolution = (unsigned int )(96.0 * myDevicePixelRatio + 0.5);
+ }
+ if (!myContext.IsNull())
+ {
+ myContext->SetPixelTolerance (int(myDevicePixelRatio * 6.0));
+ if (!myViewCube.IsNull())
+ {
+ static const double THE_CUBE_SIZE = 60.0;
+ myViewCube->SetSize (myDevicePixelRatio * THE_CUBE_SIZE, false);
+ myViewCube->SetBoxFacetExtension (myViewCube->Size() * 0.15);
+ myViewCube->SetAxesPadding (myViewCube->Size() * 0.10);
+ myViewCube->SetFontHeight (THE_CUBE_SIZE * 0.16);
+ if (myViewCube->HasInteractiveContext())
+ {
+ myContext->Redisplay (myViewCube, false);
+ }
+ }
+ }
+}
+
+// ================================================================
+// Function : initViewer
+// Purpose :
+// ================================================================
+bool WasmOcctView::initViewer()
+{
+ // Build with "--preload-file MyFontFile.ttf" option
+ // and register font in Font Manager to use custom font(s).
+ /*const char* aFontPath = "MyFontFile.ttf";
+ if (Handle(Font_SystemFont) aFont = Font_FontMgr::GetInstance()->CheckFont (aFontPath))
+ {
+ Font_FontMgr::GetInstance()->RegisterFont (aFont, true);
+ }
+ else
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: font '") + aFontPath + "' is not found", Message_Fail);
+ }*/
+
+ Handle(Aspect_DisplayConnection) aDisp;
+ Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (aDisp, false);
+ aDriver->ChangeOptions().buffersNoSwap = true; // swap has no effect in WebGL
+ if (!aDriver->InitContext())
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: EGL initialization failed"), Message_Fail);
+ return false;
+ }
+
+ Handle(V3d_Viewer) aViewer = new V3d_Viewer (aDriver);
+ aViewer->SetComputedMode (false);
+ aViewer->SetDefaultShadingModel (Graphic3d_TOSM_FRAGMENT);
+ aViewer->SetDefaultLights();
+ aViewer->SetLightOn();
+
+ Handle(Aspect_NeutralWindow) aWindow = new Aspect_NeutralWindow();
+ Graphic3d_Vec2i aWinSize = jsCanvasSize();
+ if (aWinSize.x() < 10 || aWinSize.y() < 10)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Warning: invalid canvas size"), Message_Warning);
+ }
+ aWindow->SetSize (aWinSize.x(), aWinSize.y());
+
+ myTextStyle = new Prs3d_TextAspect();
+ myTextStyle->SetFont (Font_NOF_ASCII_MONO);
+ myTextStyle->SetHeight (12);
+ myTextStyle->Aspect()->SetColor (Quantity_NOC_GRAY95);
+ myTextStyle->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
+ myTextStyle->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
+ myTextStyle->Aspect()->SetTextFontAspect (Font_FA_Bold);
+ myTextStyle->Aspect()->SetTextZoomable (false);
+ myTextStyle->SetHorizontalJustification (Graphic3d_HTA_LEFT);
+ myTextStyle->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
+
+ myView = new V3d_View (aViewer);
+ myView->SetImmediateUpdate (false);
+ myView->ChangeRenderingParams().Resolution = (unsigned int )(96.0 * myDevicePixelRatio + 0.5);
+ myView->ChangeRenderingParams().ToShowStats = true;
+ myView->ChangeRenderingParams().StatsTextAspect = myTextStyle->Aspect();
+ myView->ChangeRenderingParams().StatsTextHeight = (int )myTextStyle->Height();
+ myView->SetWindow (aWindow);
+ dumpGlInfo (false);
+
+ myContext = new AIS_InteractiveContext (aViewer);
+ initPixelScaleRatio();
+ return true;
+}
+
+// ================================================================
+// Function : initDemoScene
+// Purpose :
+// ================================================================
+void WasmOcctView::initDemoScene()
+{
+ if (myContext.IsNull())
+ {
+ return;
+ }
+
+ //myView->TriedronDisplay (Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_WIREFRAME);
+
+ myViewCube = new AIS_ViewCube();
+ // presentation parameters
+ initPixelScaleRatio();
+ myViewCube->SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_RIGHT_LOWER, Graphic3d_Vec2i (100, 100)));
+ myViewCube->Attributes()->SetDatumAspect (new Prs3d_DatumAspect());
+ myViewCube->Attributes()->DatumAspect()->SetTextAspect (myTextStyle);
+ // animation parameters
+ myViewCube->SetViewAnimation (myViewAnimation);
+ myViewCube->SetFixedAnimationLoop (false);
+ myViewCube->SetAutoStartAnimation (true);
+ myContext->Display (myViewCube, false);
+
+ // Build with "--preload-file MySampleFile.brep" option to load some shapes here.
+}
+
+
+// ================================================================
+// Function : updateView
+// Purpose :
+// ================================================================
+void WasmOcctView::updateView()
+{
+ if (!myView.IsNull())
+ {
+ if (++myUpdateRequests == 1)
+ {
+ emscripten_async_call (onRedrawView, this, 0);
+ }
+ }
+}
+
+// ================================================================
+// Function : redrawView
+// Purpose :
+// ================================================================
+void WasmOcctView::redrawView()
+{
+ if (!myView.IsNull())
+ {
+ FlushViewEvents (myContext, myView, true);
+ }
+}
+
+// ================================================================
+// Function : handleViewRedraw
+// Purpose :
+// ================================================================
+void WasmOcctView::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView)
+{
+ myUpdateRequests = 0;
+ AIS_ViewController::handleViewRedraw (theCtx, theView);
+ if (myToAskNextFrame)
+ {
+ // ask more frames
+ ++myUpdateRequests;
+ emscripten_async_call (onRedrawView, this, 0);
+ }
+}
+
+// ================================================================
+// Function : onResizeEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onResizeEvent (int theEventType, const EmscriptenUiEvent* theEvent)
+{
+ (void )theEventType; // EMSCRIPTEN_EVENT_RESIZE or EMSCRIPTEN_EVENT_CANVASRESIZED
+ (void )theEvent;
+ if (myView.IsNull())
+ {
+ return EM_FALSE;
+ }
+
+ Handle(Aspect_NeutralWindow) aWindow = Handle(Aspect_NeutralWindow)::DownCast (myView->Window());
+ Graphic3d_Vec2i aWinSizeOld, aWinSizeNew (jsCanvasSize());
+ if (aWinSizeNew.x() < 10 || aWinSizeNew.y() < 10)
+ {
+ Message::DefaultMessenger()->Send (TCollection_AsciiString ("Warning: invalid canvas size"), Message_Warning);
+ }
+ aWindow->Size (aWinSizeOld.x(), aWinSizeOld.y());
+ const float aPixelRatio = jsDevicePixelRatio();
+ if (aWinSizeNew != aWinSizeOld
+ || aPixelRatio != myDevicePixelRatio)
+ {
+ if (myDevicePixelRatio != aPixelRatio)
+ {
+ myDevicePixelRatio = aPixelRatio;
+ initPixelScaleRatio();
+ }
+ aWindow->SetSize (aWinSizeNew.x(), aWinSizeNew.y());
+ myView->MustBeResized();
+ myView->Invalidate();
+ myView->Redraw();
+ dumpGlInfo (true);
+ }
+ return EM_TRUE;
+}
+
+// ================================================================
+// Function : onMouseEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onMouseEvent (int theEventType, const EmscriptenMouseEvent* theEvent)
+{
+ if (myView.IsNull())
+ {
+ return EM_FALSE;
+ }
+
+ Graphic3d_Vec2i aWinSize;
+ myView->Window()->Size (aWinSize.x(), aWinSize.y());
+ const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (theEvent->canvasX, theEvent->canvasY));
+ Aspect_VKeyFlags aFlags = 0;
+ if (theEvent->ctrlKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_CTRL; }
+ if (theEvent->shiftKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_SHIFT; }
+ if (theEvent->altKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_ALT; }
+ if (theEvent->metaKey == EM_TRUE) { aFlags |= Aspect_VKeyFlags_META; }
+
+ const bool isEmulated = false;
+ const Aspect_VKeyMouse aButtons = WasmVKeys_MouseButtonsFromNative (theEvent->buttons);
+ switch (theEventType)
+ {
+ case EMSCRIPTEN_EVENT_MOUSEMOVE:
+ {
+ if ((aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
+ || aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
+ && PressedMouseButtons() == Aspect_VKeyMouse_NONE)
+ {
+ return EM_FALSE;
+ }
+ if (UpdateMousePosition (aNewPos, aButtons, aFlags, isEmulated))
+ {
+ updateView();
+ }
+ break;
+ }
+ case EMSCRIPTEN_EVENT_MOUSEDOWN:
+ case EMSCRIPTEN_EVENT_MOUSEUP:
+ {
+ if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
+ || aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
+ {
+ return EM_FALSE;
+ }
+ if (UpdateMouseButtons (aNewPos, aButtons, aFlags, isEmulated))
+ {
+ updateView();
+ }
+ break;
+ }
+ case EMSCRIPTEN_EVENT_CLICK:
+ case EMSCRIPTEN_EVENT_DBLCLICK:
+ {
+ if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
+ || aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
+ {
+ return EM_FALSE;
+ }
+ break;
+ }
+ case EMSCRIPTEN_EVENT_MOUSEENTER:
+ {
+ break;
+ }
+ case EMSCRIPTEN_EVENT_MOUSELEAVE:
+ {
+ // there is no SetCapture() support, so that mouse unclick events outside canvas will not arrive,
+ // so we have to forget current state...
+ if (UpdateMouseButtons (aNewPos, Aspect_VKeyMouse_NONE, aFlags, isEmulated))
+ {
+ updateView();
+ }
+ break;
+ }
+ }
+ return EM_TRUE;
+}
+
+// ================================================================
+// Function : onWheelEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onWheelEvent (int theEventType, const EmscriptenWheelEvent* theEvent)
+{
+ if (myView.IsNull()
+ || theEventType != EMSCRIPTEN_EVENT_WHEEL)
+ {
+ return EM_FALSE;
+ }
+
+ Graphic3d_Vec2i aWinSize;
+ myView->Window()->Size (aWinSize.x(), aWinSize.y());
+ const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (theEvent->mouse.canvasX, theEvent->mouse.canvasY));
+ if (aNewPos.x() < 0 || aNewPos.x() > aWinSize.x()
+ || aNewPos.y() < 0 || aNewPos.y() > aWinSize.y())
+ {
+ return EM_FALSE;
+ }
+
+ double aDelta = 0.0;
+ switch (theEvent->deltaMode)
+ {
+ case DOM_DELTA_PIXEL:
+ {
+ aDelta = theEvent->deltaY / (5.0 * myDevicePixelRatio);
+ break;
+ }
+ case DOM_DELTA_LINE:
+ {
+ aDelta = theEvent->deltaY * 8.0;
+ break;
+ }
+ case DOM_DELTA_PAGE:
+ {
+ aDelta = theEvent->deltaY >= 0.0 ? 24.0 : -24.0;
+ break;
+ }
+ }
+
+ if (UpdateZoom (Aspect_ScrollDelta (aNewPos, -aDelta)))
+ {
+ updateView();
+ }
+ return EM_TRUE;
+}
+
+// ================================================================
+// Function : onTouchEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onTouchEvent (int theEventType, const EmscriptenTouchEvent* theEvent)
+{
+ const double aClickTolerance = 5.0;
+ if (myView.IsNull())
+ {
+ return EM_FALSE;
+ }
+
+ Graphic3d_Vec2i aWinSize;
+ myView->Window()->Size (aWinSize.x(), aWinSize.y());
+ bool hasUpdates = false;
+ for (int aTouchIter = 0; aTouchIter < theEvent->numTouches; ++aTouchIter)
+ {
+ const EmscriptenTouchPoint& aTouch = theEvent->touches[aTouchIter];
+ if (!aTouch.isChanged)
+ {
+ continue;
+ }
+
+ const Standard_Size aTouchId = (Standard_Size )aTouch.identifier;
+ const Graphic3d_Vec2i aNewPos = convertPointToBacking (Graphic3d_Vec2i (aTouch.canvasX, aTouch.canvasY));
+ switch (theEventType)
+ {
+ case EMSCRIPTEN_EVENT_TOUCHSTART:
+ {
+ if (aNewPos.x() >= 0 && aNewPos.x() < aWinSize.x()
+ && aNewPos.y() >= 0 && aNewPos.y() < aWinSize.y())
+ {
+ hasUpdates = true;
+ AddTouchPoint (aTouchId, Graphic3d_Vec2d (aNewPos));
+ myClickTouch.From.SetValues (-1.0, -1.0);
+ if (myTouchPoints.Extent() == 1)
+ {
+ myClickTouch.From = Graphic3d_Vec2d (aNewPos);
+ }
+ }
+ break;
+ }
+ case EMSCRIPTEN_EVENT_TOUCHMOVE:
+ {
+ const int anOldIndex = myTouchPoints.FindIndex (aTouchId);
+ if (anOldIndex != 0)
+ {
+ hasUpdates = true;
+ UpdateTouchPoint (aTouchId, Graphic3d_Vec2d (aNewPos));
+ if (myTouchPoints.Extent() == 1
+ && (myClickTouch.From - Graphic3d_Vec2d (aNewPos)).cwiseAbs().maxComp() > aClickTolerance)
+ {
+ myClickTouch.From.SetValues (-1.0, -1.0);
+ }
+ }
+ break;
+ }
+ case EMSCRIPTEN_EVENT_TOUCHEND:
+ case EMSCRIPTEN_EVENT_TOUCHCANCEL:
+ {
+ if (RemoveTouchPoint (aTouchId))
+ {
+ if (myTouchPoints.IsEmpty()
+ && myClickTouch.From.minComp() >= 0.0)
+ {
+ if (myDoubleTapTimer.IsStarted()
+ && myDoubleTapTimer.ElapsedTime() <= myMouseDoubleClickInt)
+ {
+ myView->FitAll (0.01, false);
+ myView->Invalidate();
+ }
+ else
+ {
+ myDoubleTapTimer.Stop();
+ myDoubleTapTimer.Reset();
+ myDoubleTapTimer.Start();
+ SelectInViewer (Graphic3d_Vec2i (myClickTouch.From), false);
+ }
+ }
+ hasUpdates = true;
+ }
+ break;
+ }
+ }
+ }
+ if (hasUpdates)
+ {
+ updateView();
+ }
+ return hasUpdates || !myTouchPoints.IsEmpty() ? EM_TRUE : EM_FALSE;
+}
+
+// ================================================================
+// Function : onKeyDownEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onKeyDownEvent (int theEventType, const EmscriptenKeyboardEvent* theEvent)
+{
+ if (myView.IsNull()
+ || theEventType != EMSCRIPTEN_EVENT_KEYDOWN) // EMSCRIPTEN_EVENT_KEYPRESS
+ {
+ return EM_FALSE;
+ }
+
+ const double aTimeStamp = EventTime();
+ const Aspect_VKey aVKey = WasmVKeys_VirtualKeyFromNative (theEvent->keyCode);
+ if (aVKey == Aspect_VKey_UNKNOWN)
+ {
+ return EM_FALSE;
+ }
+
+ if (theEvent->repeat == EM_FALSE)
+ {
+ myKeys.KeyDown (aVKey, aTimeStamp);
+ }
+
+ if (Aspect_VKey2Modifier (aVKey) == 0)
+ {
+ // normal key
+ }
+ return EM_FALSE;
+}
+
+// ================================================================
+// Function : onKeyUpEvent
+// Purpose :
+// ================================================================
+EM_BOOL WasmOcctView::onKeyUpEvent (int theEventType, const EmscriptenKeyboardEvent* theEvent)
+{
+ if (myView.IsNull()
+ || theEventType != EMSCRIPTEN_EVENT_KEYUP)
+ {
+ return EM_FALSE;
+ }
+
+ const double aTimeStamp = EventTime();
+ const Aspect_VKey aVKey = WasmVKeys_VirtualKeyFromNative (theEvent->keyCode);
+ if (aVKey == Aspect_VKey_UNKNOWN)
+ {
+ return EM_FALSE;
+ }
+
+ if (theEvent->repeat == EM_TRUE)
+ {
+ return EM_FALSE;
+ }
+
+ const unsigned int aModif = myKeys.Modifiers();
+ myKeys.KeyUp (aVKey, aTimeStamp);
+ if (Aspect_VKey2Modifier (aVKey) == 0)
+ {
+ // normal key released
+ switch (aVKey | aModif)
+ {
+ case Aspect_VKey_F:
+ {
+ myView->FitAll (0.01, false);
+ myView->Invalidate();
+ updateView();
+ return EM_TRUE;
+ }
+ }
+ }
+ return EM_FALSE;
+}
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
+
+#ifndef _WasmOcctView_HeaderFile
+#define _WasmOcctView_HeaderFile
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_ViewController.hxx>
+#include <V3d_View.hxx>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+class AIS_ViewCube;
+
+//! Sample class creating 3D Viewer within Emscripten canvas.
+class WasmOcctView : protected AIS_ViewController
+{
+public:
+ //! Default constructor.
+ WasmOcctView();
+
+ //! Destructor.
+ virtual ~WasmOcctView();
+
+ //! Main application entry point.
+ void run();
+
+ //! Return interactive context.
+ const Handle(AIS_InteractiveContext)& Context() const { return myContext; }
+
+ //! Return view.
+ const Handle(V3d_View)& View() const { return myView; }
+
+ //! Return device pixel ratio for handling high DPI displays.
+ float DevicePixelRatio() const { return myDevicePixelRatio; }
+
+private:
+
+ //! Create window.
+ void initWindow();
+
+ //! Create 3D Viewer.
+ bool initViewer();
+
+ //! Fill 3D Viewer with a DEMO items.
+ void initDemoScene();
+
+ //! Application event loop.
+ void mainloop();
+
+ //! Request view redrawing.
+ void updateView();
+
+ //! Flush events and redraw view.
+ void redrawView();
+
+ //! Handle view redraw.
+ virtual void handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
+ const Handle(V3d_View)& theView) override;
+
+ //! Dump WebGL context information.
+ void dumpGlInfo (bool theIsBasic);
+
+ //! Initialize pixel scale ratio.
+ void initPixelScaleRatio();
+
+ //! Return point from logical units to backing store.
+ Graphic3d_Vec2d convertPointToBacking (const Graphic3d_Vec2d& thePnt) const
+ {
+ return thePnt * myDevicePixelRatio;
+ }
+
+ //! Return point from logical units to backing store.
+ Graphic3d_Vec2i convertPointToBacking (const Graphic3d_Vec2i& thePnt) const
+ {
+ Graphic3d_Vec2d aPnt = Graphic3d_Vec2d (thePnt) * myDevicePixelRatio + Graphic3d_Vec2d (0.5);
+ return Graphic3d_Vec2i (aPnt);
+ }
+
+//! @name Emscripten callbacks
+private:
+ //! Window resize event.
+ EM_BOOL onResizeEvent (int theEventType, const EmscriptenUiEvent* theEvent);
+
+ //! Mouse event.
+ EM_BOOL onMouseEvent (int theEventType, const EmscriptenMouseEvent* theEvent);
+
+ //! Scroll event.
+ EM_BOOL onWheelEvent (int theEventType, const EmscriptenWheelEvent* theEvent);
+
+ //! Touch event.
+ EM_BOOL onTouchEvent (int theEventType, const EmscriptenTouchEvent* theEvent);
+
+ //! Key down event.
+ EM_BOOL onKeyDownEvent (int theEventType, const EmscriptenKeyboardEvent* theEvent);
+
+ //! Key up event.
+ EM_BOOL onKeyUpEvent (int theEventType, const EmscriptenKeyboardEvent* theEvent);
+
+//! @name Emscripten callbacks (static functions)
+private:
+
+ static EM_BOOL onResizeCallback (int theEventType, const EmscriptenUiEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onResizeEvent (theEventType, theEvent); }
+
+ static void onRedrawView (void* theView)
+ { return ((WasmOcctView* )theView)->redrawView(); }
+
+ static EM_BOOL onMouseCallback (int theEventType, const EmscriptenMouseEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onMouseEvent (theEventType, theEvent); }
+
+ static EM_BOOL onWheelCallback (int theEventType, const EmscriptenWheelEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onWheelEvent (theEventType, theEvent); }
+
+ static EM_BOOL onTouchCallback (int theEventType, const EmscriptenTouchEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onTouchEvent (theEventType, theEvent); }
+
+ static EM_BOOL onKeyDownCallback (int theEventType, const EmscriptenKeyboardEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onKeyDownEvent (theEventType, theEvent); }
+
+ static EM_BOOL onKeyUpCallback (int theEventType, const EmscriptenKeyboardEvent* theEvent, void* theView)
+ { return ((WasmOcctView* )theView)->onKeyUpEvent (theEventType, theEvent); }
+
+private:
+
+ Handle(AIS_InteractiveContext) myContext; //!< interactive context
+ Handle(V3d_View) myView; //!< 3D view
+ Handle(Prs3d_TextAspect) myTextStyle; //!< text style for OSD elements
+ Handle(AIS_ViewCube) myViewCube; //!< view cube object
+ TCollection_AsciiString myCanvasId; //!< canvas element id on HTML page
+ Aspect_Touch myClickTouch; //!< single touch position for handling clicks
+ OSD_Timer myDoubleTapTimer; //!< timer for handling double tap
+ float myDevicePixelRatio; //!< device pixel ratio for handling high DPI displays
+ unsigned int myUpdateRequests; //!< counter for unhandled update requests
+
+};
+
+#endif // _WasmOcctView_HeaderFile
--- /dev/null
+// Copyright (c) 2019 OPEN CASCADE SAS
+//
+// This file is part of the examples of the Open CASCADE Technology software library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
+
+#ifndef _WasmVKeys_HeaderFile
+#define _WasmVKeys_HeaderFile
+
+#include <Aspect_VKey.hxx>
+
+#include <emscripten/key_codes.h>
+
+//! Convert Emscripten mouse buttons into Aspect_VKeyMouse.
+inline Aspect_VKeyMouse WasmVKeys_MouseButtonsFromNative (unsigned short theButtons)
+{
+ Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
+ if ((theButtons & 0x1) != 0)
+ {
+ aButtons |= Aspect_VKeyMouse_LeftButton;
+ }
+ if ((theButtons & 0x2) != 0)
+ {
+ aButtons |= Aspect_VKeyMouse_RightButton;
+ }
+ if ((theButtons & 0x4) != 0)
+ {
+ aButtons |= Aspect_VKeyMouse_MiddleButton;
+ }
+ return aButtons;
+}
+
+//! Convert DOM virtual key into Aspect_VKey.
+inline Aspect_VKey WasmVKeys_VirtualKeyFromNative (Standard_Integer theKey)
+{
+ if (theKey >= DOM_VK_0
+ && theKey <= DOM_VK_9)
+ {
+ // numpad keys
+ return Aspect_VKey((theKey - DOM_VK_0) + Aspect_VKey_0);
+ }
+ if (theKey >= DOM_VK_A
+ && theKey <= DOM_VK_Z)
+ {
+ // main latin alphabet keys
+ return Aspect_VKey((theKey - DOM_VK_A) + Aspect_VKey_A);
+ }
+ if (theKey >= DOM_VK_F1
+ && theKey <= DOM_VK_F24)
+ {
+ // special keys
+ if (theKey <= DOM_VK_F12)
+ {
+ return Aspect_VKey((theKey - DOM_VK_F1) + Aspect_VKey_F1);
+ }
+ return Aspect_VKey_UNKNOWN;
+ }
+ if (theKey >= DOM_VK_NUMPAD0
+ && theKey <= DOM_VK_NUMPAD9)
+ {
+ // numpad keys
+ return Aspect_VKey((theKey - DOM_VK_NUMPAD0) + Aspect_VKey_Numpad0);
+ }
+
+ switch (theKey)
+ {
+ case DOM_VK_CANCEL:
+ case DOM_VK_HELP:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_BACK_SPACE:
+ return Aspect_VKey_Backspace;
+ case DOM_VK_TAB:
+ return Aspect_VKey_Tab;
+ case DOM_VK_CLEAR:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_RETURN:
+ case DOM_VK_ENTER:
+ return Aspect_VKey_Enter;
+ case DOM_VK_SHIFT:
+ return Aspect_VKey_Shift;
+ case DOM_VK_CONTROL:
+ return Aspect_VKey_Control;
+ case DOM_VK_ALT:
+ return Aspect_VKey_Alt;
+ case DOM_VK_PAUSE:
+ case DOM_VK_CAPS_LOCK:
+ case DOM_VK_KANA:
+ //case DOM_VK_HANGUL:
+ case DOM_VK_EISU:
+ case DOM_VK_JUNJA:
+ case DOM_VK_FINAL:
+ case DOM_VK_HANJA:
+ //case DOM_VK_KANJI:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_ESCAPE:
+ return Aspect_VKey_Escape;
+ case DOM_VK_CONVERT:
+ case DOM_VK_NONCONVERT:
+ case DOM_VK_ACCEPT:
+ case DOM_VK_MODECHANGE:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_SPACE:
+ return Aspect_VKey_Space;
+ case DOM_VK_PAGE_UP:
+ return Aspect_VKey_PageUp;
+ case DOM_VK_PAGE_DOWN:
+ return Aspect_VKey_PageDown;
+ case DOM_VK_END:
+ return Aspect_VKey_End;
+ case DOM_VK_HOME:
+ return Aspect_VKey_Home;
+ case DOM_VK_LEFT:
+ return Aspect_VKey_Left;
+ case DOM_VK_UP:
+ return Aspect_VKey_Up;
+ case DOM_VK_RIGHT:
+ return Aspect_VKey_Right;
+ case DOM_VK_DOWN:
+ return Aspect_VKey_Down;
+ case DOM_VK_SELECT:
+ case DOM_VK_PRINT:
+ case DOM_VK_EXECUTE:
+ case DOM_VK_PRINTSCREEN:
+ case DOM_VK_INSERT:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_DELETE:
+ return Aspect_VKey_Delete;
+ case DOM_VK_COLON:
+ return Aspect_VKey_Comma;
+ case DOM_VK_SEMICOLON:
+ return Aspect_VKey_Semicolon;
+ case DOM_VK_LESS_THAN:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_EQUALS:
+ return Aspect_VKey_Equal;
+ case DOM_VK_GREATER_THAN:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_QUESTION_MARK:
+ return Aspect_VKey_Slash;
+ case DOM_VK_AT: // @ key
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_WIN:
+ return Aspect_VKey_Meta;
+ case DOM_VK_CONTEXT_MENU:
+ case DOM_VK_SLEEP:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_MULTIPLY:
+ return Aspect_VKey_NumpadMultiply;
+ case DOM_VK_ADD:
+ return Aspect_VKey_NumpadAdd;
+ case DOM_VK_SEPARATOR:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_SUBTRACT:
+ return Aspect_VKey_NumpadSubtract;
+ case DOM_VK_DECIMAL:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_DIVIDE:
+ return Aspect_VKey_NumpadDivide;
+ case DOM_VK_NUM_LOCK:
+ return Aspect_VKey_Numlock;
+ case DOM_VK_SCROLL_LOCK:
+ return Aspect_VKey_Scroll;
+ case DOM_VK_WIN_OEM_FJ_JISHO:
+ case DOM_VK_WIN_OEM_FJ_MASSHOU:
+ case DOM_VK_WIN_OEM_FJ_TOUROKU:
+ case DOM_VK_WIN_OEM_FJ_LOYA:
+ case DOM_VK_WIN_OEM_FJ_ROYA:
+ case DOM_VK_CIRCUMFLEX:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_EXCLAMATION:
+ case DOM_VK_DOUBLE_QUOTE:
+ //case DOM_VK_HASH:
+ case DOM_VK_DOLLAR:
+ case DOM_VK_PERCENT:
+ case DOM_VK_AMPERSAND:
+ case DOM_VK_UNDERSCORE:
+ case DOM_VK_OPEN_PAREN:
+ case DOM_VK_CLOSE_PAREN:
+ case DOM_VK_ASTERISK:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_PLUS:
+ return Aspect_VKey_Plus;
+ case DOM_VK_PIPE:
+ case DOM_VK_HYPHEN_MINUS:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_OPEN_CURLY_BRACKET:
+ return Aspect_VKey_BracketLeft;
+ case DOM_VK_CLOSE_CURLY_BRACKET:
+ return Aspect_VKey_BracketRight;
+ case DOM_VK_TILDE:
+ return Aspect_VKey_Tilde;
+ case DOM_VK_VOLUME_MUTE:
+ return Aspect_VKey_VolumeMute;
+ case DOM_VK_VOLUME_DOWN:
+ return Aspect_VKey_VolumeDown;
+ case DOM_VK_VOLUME_UP:
+ return Aspect_VKey_VolumeUp;
+ case DOM_VK_COMMA:
+ return Aspect_VKey_Comma;
+ case DOM_VK_PERIOD:
+ return Aspect_VKey_Period;
+ case DOM_VK_SLASH:
+ return Aspect_VKey_Slash;
+ case DOM_VK_BACK_QUOTE:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_OPEN_BRACKET:
+ return Aspect_VKey_BracketLeft;
+ case DOM_VK_BACK_SLASH:
+ return Aspect_VKey_Backslash;
+ case DOM_VK_CLOSE_BRACKET:
+ return Aspect_VKey_BracketRight;
+ case DOM_VK_QUOTE:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_META:
+ return Aspect_VKey_Meta;
+ case DOM_VK_ALTGR:
+ return Aspect_VKey_Alt;
+ case DOM_VK_WIN_ICO_HELP:
+ case DOM_VK_WIN_ICO_00:
+ case DOM_VK_WIN_ICO_CLEAR:
+ case DOM_VK_WIN_OEM_RESET:
+ case DOM_VK_WIN_OEM_JUMP:
+ case DOM_VK_WIN_OEM_PA1:
+ case DOM_VK_WIN_OEM_PA2:
+ case DOM_VK_WIN_OEM_PA3:
+ case DOM_VK_WIN_OEM_WSCTRL:
+ case DOM_VK_WIN_OEM_CUSEL:
+ case DOM_VK_WIN_OEM_ATTN:
+ case DOM_VK_WIN_OEM_FINISH:
+ case DOM_VK_WIN_OEM_COPY:
+ case DOM_VK_WIN_OEM_AUTO:
+ case DOM_VK_WIN_OEM_ENLW:
+ case DOM_VK_WIN_OEM_BACKTAB:
+ case DOM_VK_ATTN:
+ case DOM_VK_CRSEL:
+ case DOM_VK_EXSEL:
+ case DOM_VK_EREOF:
+ return Aspect_VKey_UNKNOWN;
+ case DOM_VK_PLAY:
+ return Aspect_VKey_MediaPlayPause;
+ case DOM_VK_ZOOM:
+ case DOM_VK_PA1:
+ case DOM_VK_WIN_OEM_CLEAR:
+ return Aspect_VKey_UNKNOWN;
+ }
+ return Aspect_VKey_UNKNOWN;
+}
+
+#endif // _WasmVKeys_HeaderFile
--- /dev/null
+#include <iostream>
+
+#include "WasmOcctView.h"
+
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <OSD_MemInfo.hxx>
+#include <OSD_Parallel.hxx>
+
+#include <AIS_Shape.hxx>
+#include <BRepTools.hxx>
+#include <BRep_Builder.hxx>
+#include <Standard_ArrayStreamBuffer.hxx>
+
+#include <emscripten.h>
+#include <emscripten/html5.h>
+
+//! Global viewer instance.
+static WasmOcctView aViewer;
+
+//! File data read event.
+extern "C" void onFileDataRead (void* theOpaque, void* theBuffer, int theDataLen)
+{
+ const char* aName = theOpaque != NULL ? (const char* )theOpaque : "";
+ {
+ AIS_ListOfInteractive aShapes;
+ aViewer.Context()->DisplayedObjects (AIS_KOI_Shape, -1, aShapes);
+ for (AIS_ListOfInteractive::Iterator aShapeIter (aShapes); aShapeIter.More(); aShapeIter.Next())
+ {
+ aViewer.Context()->Remove (aShapeIter.Value(), false);
+ }
+ }
+
+ Standard_ArrayStreamBuffer aStreamBuffer ((const char* )theBuffer, theDataLen);
+ std::istream aStream (&aStreamBuffer);
+ TopoDS_Shape aShape;
+ BRep_Builder aBuilder;
+ BRepTools::Read (aShape, aStream, aBuilder);
+
+ Handle(AIS_Shape) aShapePrs = new AIS_Shape (aShape);
+ aShapePrs->SetMaterial (Graphic3d_NOM_SILVER);
+ aViewer.Context()->Display (aShapePrs, AIS_Shaded, 0, false);
+ aViewer.View()->FitAll (0.01, false);
+ aViewer.View()->Redraw();
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Loaded file ") + aName, Message_Info);
+ Message::DefaultMessenger()->Send (OSD_MemInfo::PrintInfo(), Message_Trace);
+}
+
+//! File read error event.
+static void onFileReadFailed (void* theOpaque)
+{
+ const char* aName = (const char* )theOpaque;
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("Error: unable to load file ") + aName, Message_Fail);
+}
+
+int main()
+{
+ Message::DefaultMessenger()->Printers().First()->SetTraceLevel (Message_Trace);
+ Message::DefaultMessenger()->Send (TCollection_AsciiString("NbLogicalProcessors: ") + OSD_Parallel::NbLogicalProcessors(), Message_Trace);
+ aViewer.run();
+ Message::DefaultMessenger()->Send (OSD_MemInfo::PrintInfo(), Message_Trace);
+
+ // load some file
+ emscripten_async_wget_data ("samples/Ball.brep", (void* )"samples/Ball.brep", onFileDataRead, onFileReadFailed);
+ return 0;
+}
--- /dev/null
+<!DOCTYPE html>\r
+<html lang=en-us>\r
+<head>\r
+<meta charset=utf-8><meta content="text/html; charset=utf-8" http-equiv=Content-Type>\r
+<link rel="shortcut icon" href="lamp.ico" type="image/x-icon" />\r
+<title>OCCT WebGL Viewer Sample</title>\r
+</head>\r
+<body>\r
+\r
+<h2>OCCT WebGL Viewer Sample</h2>\r
+<div>\r
+ <canvas id=canvas oncontextmenu=event.preventDefault() tabindex=-1 style="border:0 none;background-color:#000" width="409" height="409"></canvas>\r
+ <img id=occlogo src="OCC_logo.png" style="position: absolute; left: 20px; top: 0px; z-index: 2;" />\r
+</div>\r
+\r
+<div><label for="fileInput">Choose BREP file to upload: </label><input type="file" id="fileInput" accept=".brep"></div>\r
+<h4>Console output:</h4>\r
+<p id="output"></p>\r
+<script>\r
+//! Resize canvas to fit into window.\r
+function updateCanvasSize()\r
+{\r
+ // size of canvas in logical (density-independent) units\r
+ var aSizeX = Math.min (window.innerWidth, window.screen.availWidth);\r
+ var aSizeY = Math.min (window.innerHeight, window.screen.availHeight);\r
+ aSizeX = Math.max (300, aSizeX - 30);\r
+ aSizeY = Math.max (300, aSizeY / 2);\r
+ canvas.style.width = aSizeX + "px";\r
+ canvas.style.height = aSizeY + "px";\r
+\r
+ // drawing buffer size (aka backing store)\r
+ var aDevicePixelRatio = window.devicePixelRatio || 1;\r
+ canvas.width = aSizeX * aDevicePixelRatio;\r
+ canvas.height = aSizeY * aDevicePixelRatio;\r
+\r
+ occlogo.style.top = (aSizeY - 30) + "px";\r
+}\r
+window.onresize = updateCanvasSize;\r
+updateCanvasSize();\r
+\r
+//! Check browser support.\r
+function isWasmSupported()\r
+{\r
+ try {\r
+ if (typeof WebAssembly === "object"\r
+ && typeof WebAssembly.instantiate === "function") {\r
+ const aDummyModule = new WebAssembly.Module (Uint8Array.of (0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00));\r
+ if (aDummyModule instanceof WebAssembly.Module)\r
+ {\r
+ return new WebAssembly.Instance(aDummyModule) instanceof WebAssembly.Instance;\r
+ }\r
+ }\r
+ } catch (e) {}\r
+ return false;\r
+}\r
+if (!isWasmSupported())\r
+{\r
+ var anElement = document.getElementById('output');\r
+ anElement.innerHTML += "Browser is too old - WebAssembly support is missing!<br>Please check updates or install a modern browser.<br>";\r
+}\r
+\r
+//! Define OCCT WebGL Viewer module.\r
+var Module =\r
+{\r
+ print: (function() {\r
+ var anElement = document.getElementById('output');\r
+ return function(theText) { anElement.innerHTML += theText + "<br>"; };\r
+ })(),\r
+ printErr: function(theText) {\r
+ //var anElement = document.getElementById('output');\r
+ //anElement.innerHTML += theText + "<br>";\r
+ },\r
+ canvas: (function() {\r
+ var aCanvas = document.getElementById('canvas');\r
+ return aCanvas;\r
+ })()\r
+};\r
+\r
+//! Handle file uploading.\r
+fileInput.onchange = function()\r
+{\r
+ if (fileInput.files.length == 0) { return; }\r
+ // Warning! Entire file is pre-loaded into memory.\r
+ var aFile = fileInput.files[0];\r
+ var aReader = new FileReader();\r
+ aReader.onload = function()\r
+ {\r
+ var aDataArray = new Uint8Array (aReader.result);\r
+ var aNameArray = new Uint8Array (toUtf8Array (aFile.name));\r
+ const aDataBuffer = Module._malloc(aDataArray.length);\r
+ const aNameBuffer = Module._malloc(aNameArray.length);\r
+ Module.HEAPU8.set(aNameArray, aNameBuffer);\r
+ Module.HEAPU8.set(aDataArray, aDataBuffer);\r
+ Module.ccall('onFileDataRead', null, ['number', 'number', 'number'], [aNameBuffer, aDataBuffer, aDataArray.length]);\r
+ Module._free(aDataBuffer);\r
+ Module._free(aNameBuffer);\r
+ fileInput.value = '';\r
+ };\r
+ aReader.readAsArrayBuffer(aFile);\r
+};\r
+\r
+//! Convert string into UTF-8 array.\r
+function toUtf8Array (theText)\r
+{\r
+ var aRes = [];\r
+ for (var aCharIter = 0; aCharIter < theText.length; ++aCharIter)\r
+ {\r
+ var aCharCode = theText.charCodeAt (aCharIter);\r
+ if (aCharCode < 0x80)\r
+ {\r
+ aRes.push (aCharCode);\r
+ }\r
+ else if (aCharCode < 0x800)\r
+ {\r
+ aRes.push (0xc0 | (aCharCode >> 6), 0x80 | (aCharCode & 0x3f));\r
+ }\r
+ else if (aCharCode < 0xd800 || aCharCode >= 0xe000)\r
+ {\r
+ aRes.push (0xe0 | (aCharCode >> 12), 0x80 | ((aCharCode>>6) & 0x3f), 0x80 | (aCharCode & 0x3f));\r
+ }\r
+ else\r
+ {\r
+ ++aCharIter;\r
+ aCharCode = 0x10000 + (((aCharCode & 0x3ff)<<10) | (theText.charCodeAt (aCharIter) & 0x3ff));\r
+ aRes.push(0xf0 | (aCharCode >>18), 0x80 | ((aCharCode>>12) & 0x3f), 0x80 | ((aCharCode>>6) & 0x3f), 0x80 | (aCharCode & 0x3f));\r
+ }\r
+ }\r
+ return aRes;\r
+}\r
+</script>\r
+<script type="text/javascript" src="occt-webgl-sample.js" charset="utf-8"></script>\r
+</body>\r
+</html>\r
// =======================================================================
Aspect_DisplayConnection::Aspect_DisplayConnection()
{
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
myDisplay = NULL;
myIsOwnDisplay = false;
OSD_Environment anEnv ("DISPLAY");
// =======================================================================
Aspect_DisplayConnection::~Aspect_DisplayConnection()
{
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
if (myDisplay != NULL
&& myIsOwnDisplay)
{
#endif
}
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
// =======================================================================
// function : Aspect_DisplayConnection
// purpose :
#include <TCollection_AsciiString.hxx>
#include <NCollection_DataMap.hxx>
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <InterfaceGraphic.hxx>
#endif
//! Destructor. Close opened connection.
Standard_EXPORT ~Aspect_DisplayConnection();
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
//! Constructor. Creates connection with display specified in theDisplayName.
//! Display name should be in format "hostname:number" or "hostname:number.screen_number", where:
//! hostname - Specifies the name of the host machine on which the display is physically attached.
#ifndef _Aspect_FBConfig_HeaderFile
#define _Aspect_FBConfig_HeaderFile
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
typedef struct __GLXFBConfigRec* GLXFBConfig;
typedef GLXFBConfig Aspect_FBConfig; // GLXFBConfig* under UNIX
#else
#ifndef __Aspect_WNTXWD_HXX
# define __Aspect_WNTXWD_HXX
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
# include <X11/XWDFile.h>
# else
NULL
};
- #if !defined(__ANDROID__) && !defined(__APPLE__)
+ #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
// X11 configuration file in plain text format (obsolete - doesn't exists in modern distributives)
static Standard_CString myFontServiceConf[] = {"/etc/X11/fs/config",
"/usr/X11R6/lib/X11/fs/config",
#else
NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs;
-#if !defined(__ANDROID__) && !defined(__APPLE__)
+#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
if (FcConfig* aFcCfg = FcInitLoadConfig())
{
if (FcStrList* aFcFontDir = FcConfigGetFontDirs (aFcCfg))
for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs);
anIter.More(); anIter.Next())
{
- #if !defined(__ANDROID__) && !defined(__APPLE__)
+ #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
OSD_File aReadFile (anIter.Value() + "/fonts.dir");
if (!aReadFile.Exists())
{
}
}
- #if !defined(__ANDROID__) && !defined(__APPLE__)
+ #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
continue;
}
#undef DrawText
#endif
-#elif !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#elif !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
#include <stdio.h>
void OSD_Chronometer::GetProcessCPU (Standard_Real& theUserSeconds,
Standard_Real& theSystemSeconds)
{
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
static const long aCLK_TCK = sysconf(_SC_CLK_TCK);
#else
static const long aCLK_TCK = CLK_TCK;
myCounters[MemHeapUsage] += hinfo._size;
}
-#elif (defined(__linux__) || defined(__linux))
+#elif (defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__))
+ const struct mallinfo aMI = mallinfo();
+ myCounters[MemHeapUsage] = aMI.uordblks;
+#if defined(__EMSCRIPTEN__)
+ // /proc/%d/status is not emulated - get more info from mallinfo()
+ myCounters[MemWorkingSet] = aMI.uordblks;
+ myCounters[MemWorkingSetPeak] = aMI.usmblks;
+#endif
+
// use procfs on Linux
char aBuff[4096];
snprintf (aBuff, sizeof(aBuff), "/proc/%d/status", getpid());
}
}
aFile.close();
-
- struct mallinfo aMI = mallinfo();
- myCounters[MemHeapUsage] = aMI.uordblks;
-
#elif (defined(__APPLE__))
struct task_basic_info aTaskInfo;
mach_msg_type_number_t aTaskInfoCount = TASK_BASIC_INFO_COUNT;
return OSD_VMS;
#elif defined(__linux__) || defined(__linux)
return OSD_LinuxREDHAT;
+#elif defined(__EMSCRIPTEN__)
+ return OSD_LinuxREDHAT;
#elif defined(_AIX) || defined(AIX)
return OSD_Aix;
#else
#include <signal.h>
-#if !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <sys/signal.h>
#endif
#include <GL/glx.h> // glXGetProcAddress()
#endif
+#ifdef __EMSCRIPTEN__
+ #include <emscripten/html5.h>
+
+ //! Check if WebGL extension is available and activate it
+ //! (usage of extension without activation will generate errors).
+ static bool checkEnableWebGlExtension (const OpenGl_Context& theCtx,
+ const char* theExtName)
+ {
+ if (!theCtx.CheckExtension (theExtName))
+ {
+ return false;
+ }
+ if (EMSCRIPTEN_WEBGL_CONTEXT_HANDLE aWebGlCtx = emscripten_webgl_get_current_context())
+ {
+ if (emscripten_webgl_enable_extension (aWebGlCtx, theExtName))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+#endif
+
namespace
{
static const Handle(OpenGl_Resource) NULL_GL_RESOURCE;
extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
extPDS = IsGlGreaterEqual (3, 0)
|| CheckExtension ("GL_OES_packed_depth_stencil");
+#ifdef __EMSCRIPTEN__
+ if (!extPDS
+ && checkEnableWebGlExtension (*this, "GL_WEBGL_depth_texture"))
+ {
+ extPDS = true; // WebGL 1.0 extension (in WebGL 2.0 core)
+ }
+#endif
core11fwd = (OpenGl_GlCore11Fwd* )(&(*myFuncs));
if (IsGlGreaterEqual (2, 0))
ReadGlVersion (aDriverVer[0], aDriverVer[1]);
addInfo (theDict, "GLvendor", (const char*)::glGetString (GL_VENDOR));
addInfo (theDict, "GLdevice", (const char*)::glGetString (GL_RENDERER));
+ #ifdef __EMSCRIPTEN__
+ if (checkEnableWebGlExtension (*this, "GL_WEBGL_debug_renderer_info"))
+ {
+ if (const char* aVendor = (const char*)::glGetString (0x9245))
+ {
+ addInfo (theDict, "GLunmaskedVendor", aVendor);
+ }
+ if (const char* aDevice = (const char*)::glGetString (0x9246))
+ {
+ addInfo (theDict, "GLunmaskedDevice", aDevice);
+ }
+ }
+ #endif
+
addInfo (theDict, "GLversion", (const char*)::glGetString (GL_VERSION));
if (myGlVerMajor != aDriverVer[0]
|| myGlVerMinor != aDriverVer[1])
//! basing on ToRenderSRGB() flag.
OpenGl_Vec4 Vec4FromQuantityColor (const OpenGl_Vec4& theColor) const
{
- return ToRenderSRGB()
+ return myIsSRgbActive
? Vec4LinearFromQuantityColor(theColor)
: Vec4sRGBFromQuantityColor (theColor);
}
}
return true;
}
+
+ //! Return TRUE if GL_DEPTH_STENCIL_ATTACHMENT can be used.
+ static bool hasDepthStencilAttach (const Handle(OpenGl_Context)& theCtx)
+ {
+ #ifdef __EMSCRIPTEN__
+ // supported since WebGL 2.0,
+ // while WebGL 1.0 + GL_WEBGL_depth_texture needs GL_DEPTH_STENCIL_ATTACHMENT
+ // and NOT separate GL_DEPTH_ATTACHMENT+GL_STENCIL_ATTACHMENT calls which is different to OpenGL ES 2.0 + extension
+ return theCtx->IsGlGreaterEqual (3, 0) || theCtx->extPDS;
+ #elif defined(GL_ES_VERSION_2_0)
+ // supported since OpenGL ES 3.0,
+ // while OpenGL ES 2.0 + GL_EXT_packed_depth_stencil needs separate GL_DEPTH_ATTACHMENT+GL_STENCIL_ATTACHMENT calls
+ return theCtx->IsGlGreaterEqual (3, 0);
+ #else
+ // available on desktop since OpenGL 3.0
+ // or OpenGL 2.0 + GL_ARB_framebuffer_object (GL_EXT_framebuffer_object is unsupported by OCCT)
+ (void )theCtx;
+ return true;
+ #endif
+ }
}
// =======================================================================
}
if (myDepthStencilTexture->IsValid())
{
- #ifdef GL_DEPTH_STENCIL_ATTACHMENT
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- #else
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- #endif
+ if (hasDepthStencilAttach (theGlContext))
+ {
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ }
+ else
+ {
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ }
}
if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
}
}
+
if (myDepthStencilTexture->IsValid())
{
- #ifdef GL_DEPTH_STENCIL_ATTACHMENT
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- #else
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
- #endif
+ if (hasDepthStencilAttach (theGlContext))
+ {
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ }
+ else
+ {
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+ }
}
else if (myGlDepthRBufferId != NO_RENDERBUFFER)
{
- #ifdef GL_DEPTH_STENCIL_ATTACHMENT
- theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, myGlDepthRBufferId);
- #else
- theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, myGlDepthRBufferId);
- if (hasStencilRB)
+ if (hasDepthStencilAttach (theGlContext) && hasStencilRB)
{
- theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, myGlDepthRBufferId);
}
- #endif
+ else
+ {
+ theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, myGlDepthRBufferId);
+ if (hasStencilRB)
+ {
+ theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, myGlDepthRBufferId);
+ }
+ }
}
if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
GL_RENDERBUFFER, myGlColorRBufferId);
if (myGlDepthRBufferId != NO_RENDERBUFFER)
{
- #ifdef GL_DEPTH_STENCIL_ATTACHMENT
- theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, hasStencilRB ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, myGlDepthRBufferId);
- #else
- theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, myGlDepthRBufferId);
- if (hasStencilRB)
+ if (hasDepthStencilAttach (theGlCtx) && hasStencilRB)
{
- theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, myGlDepthRBufferId);
}
- #endif
+ else
+ {
+ theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, myGlDepthRBufferId);
+ if (hasStencilRB)
+ {
+ theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, myGlDepthRBufferId);
+ }
+ }
}
if (theGlCtx->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
#include <OpenGL/gl.h>
#endif
#define __X_GL_H // prevent chaotic gl.h inclusions to avoid compile errors
-#elif defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#elif defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
#if defined(_WIN32)
// Angle OpenGL ES headers do not define function prototypes even for core functions,
// however OCCT is expected to be linked against libGLESv2
#define GL_DEPTH_STENCIL 0x84F9
#define GL_UNSIGNED_INT_24_8 0x84FA
#define GL_DEPTH24_STENCIL8 0x88F0
+ #define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
// OpenGL ES 3.0+
#define GL_DEPTH_COMPONENT24 0x81A6
#define GL_PATCHES 0x000E
#endif
-#if !defined(HAVE_EGL) && (defined(__ANDROID__) || defined(__QNX__) || defined(HAVE_GLES2) || defined(OCCT_UWP))
+#if !defined(HAVE_EGL) && (defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(HAVE_GLES2) || defined(OCCT_UWP))
#define HAVE_EGL
#endif
#include <Xw_Window.hxx>
#endif
-#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
#include <X11/Xlib.h> // XOpenDisplay()
#endif
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
#include <EGL/egl.h>
#ifndef EGL_OPENGL_ES3_BIT
#define EGL_OPENGL_ES3_BIT 0x00000040
{
static const Handle(OpenGl_Context) TheNullGlCtx;
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
//! Wrapper over eglChooseConfig() called with preferred defaults.
static EGLConfig chooseEglSurfConfig (EGLDisplay theDisplay)
{
const Standard_Boolean theToInitialize)
: Graphic3d_GraphicDriver (theDisp),
myIsOwnContext (Standard_False),
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
myEglDisplay ((Aspect_Display )EGL_NO_DISPLAY),
myEglContext ((Aspect_RenderingContext )EGL_NO_CONTEXT),
myEglConfig (NULL),
myMapOfView (1, NCollection_BaseAllocator::CommonBaseAllocator()),
myMapOfStructure (1, NCollection_BaseAllocator::CommonBaseAllocator())
{
-#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
if (myDisplayConnection.IsNull())
{
//throw Aspect_GraphicDeviceDefinitionError("OpenGl_GraphicDriver: cannot connect to X server!");
aWindow->GetGlContext()->forcedRelease();
}
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
if (myIsOwnContext)
{
if (myEglContext != (Aspect_RenderingContext )EGL_NO_CONTEXT)
Standard_Boolean OpenGl_GraphicDriver::InitContext()
{
ReleaseContext();
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
-#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
if (myDisplayConnection.IsNull())
{
return Standard_False;
return Standard_True;
}
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
// =======================================================================
// function : InitEglContext
// purpose :
void* theEglConfig)
{
ReleaseContext();
-#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
+#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
if (myDisplayConnection.IsNull())
{
return Standard_False;
#else
NSView* TheSpecifiedWindowId = THEWindow->HView();
#endif
-#elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
+#elif defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(OCCT_UWP)
(void )AWindow;
int TheSpecifiedWindowId = -1;
#else
#else
NSView* TheWindowIdOfView = theWindow->HView();
#endif
-#elif defined(__ANDROID__) || defined(__QNX__) || defined(OCCT_UWP)
+#elif defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(OCCT_UWP)
int TheWindowIdOfView = 0;
#else
const Handle(Xw_Window) theWindow = Handle(Xw_Window)::DownCast (AspectWindow);
//! Perform initialization of default OpenGL context.
Standard_EXPORT Standard_Boolean InitContext();
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
//! Initialize default OpenGL context using existing one.
//! @param theEglDisplay EGL connection to the Display
//! @param theEglContext EGL rendering context
//! any context will be returned otherwise
Standard_EXPORT const Handle(OpenGl_Context)& GetSharedContext (bool theBound = false) const;
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
Aspect_Display getRawGlDisplay() const { return myEglDisplay; }
Aspect_RenderingContext getRawGlContext() const { return myEglContext; }
void* getRawGlConfig() const { return myEglConfig; }
protected:
Standard_Boolean myIsOwnContext; //!< indicates that shared context has been created within OpenGl_GraphicDriver
-#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__)
+#if defined(HAVE_EGL) || defined(HAVE_GLES2) || defined(OCCT_UWP) || defined(__ANDROID__) || defined(__QNX__) || defined(__EMSCRIPTEN__)
Aspect_Display myEglDisplay; //!< EGL connection to the Display : EGLDisplay
Aspect_RenderingContext myEglContext; //!< EGL rendering context : EGLContext
void* myEglConfig; //!< EGL configuration : EGLConfig
}
(void )toUseDerivates;
#else
+
+#if defined(__EMSCRIPTEN__)
+ if (myContext->IsGlGreaterEqual (3, 0))
+ {
+ // consider this is browser responsibility to provide working WebGL 2.0 implementation
+ // and black-list broken drivers (there is no OpenGL ES greater than 3.0)
+ theProgram->SetHeader ("#version 300 es");
+ }
+#endif
// prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
// and "300 es" on OpenGL ES 3.1+ devices
if (myContext->IsGlGreaterEqual (3, 1))
//throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to retrieve current surface!");
if (anEglConfig != NULL)
{
+ #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
const int aSurfAttribs[] =
{
EGL_WIDTH, myWidth,
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL is unable to create off-screen surface!");
}
+ #endif
}
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
"OpenGl_Window::CreateWindow: WARNING, a Window is created without a EGL Surface!");
#include <Quantity_ColorRGBA.hxx>
-#include <Graphic3d_Vec4.hxx>
+#include <NCollection_Vec4.hxx>
#include <Standard_Dump.hxx>
#include <algorithm>
Standard_ASSERT_RETURN (theColorComponentBase >= 2,
__FUNCTION__ ": 'theColorComponentBase' must be greater than 1.",
0.0f);
- Graphic3d_Vec4 aColor (1.0f);
+ NCollection_Vec4<float> aColor (1.0f);
if (hasAlphaComponent)
{
const Standard_ShortReal anAlphaComponent = takeColorComponentFromInteger (theColorInteger,
uniform mat4 occProjectionMatrixInverseTranspose; //!< Transpose of the inverse of the projection matrix
uniform mat4 occModelWorldMatrixInverseTranspose; //!< Transpose of the inverse of the model-world matrix
-// light type enumeration
+// light type enumeration (same as Graphic3d_TypeOfLightSource)
const int OccLightType_Direct = 1; //!< directional light source
const int OccLightType_Point = 2; //!< isotropic point light source
const int OccLightType_Spot = 3; //!< spot light source
uniform vec4 occLightAmbient; //!< Cumulative ambient color
#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)
uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sources
-int occLight_Type (in int theId); //!< Type of light source
-int occLight_IsHeadlight (in int theId); //!< Is light a headlight?
-vec4 occLight_Diffuse (in int theId); //!< Diffuse intensity for specified light source
-vec4 occLight_Specular (in int theId); //!< Specular intensity (currently - equals to diffuse intencity)
-vec4 occLight_Position (in int theId); //!< Position of specified light source
-vec4 occLight_SpotDirection (in int theId); //!< Direction of specified spot light source
-float occLight_ConstAttenuation (in int theId); //!< Const attenuation factor of positional light source
-float occLight_LinearAttenuation (in int theId); //!< Linear attenuation factor of positional light source
-float occLight_SpotCutOff (in int theId); //!< Maximum spread angle of the spot light (in radians)
-float occLight_SpotExponent (in int theId); //!< Attenuation of the spot light intensity (from 0 to 1)
+
+//! Type of light source, int (see OccLightType enum).
+#define occLight_Type(theId) occLightSourcesTypes[theId].x
+
+//! Is light a headlight, int?
+#define occLight_IsHeadlight(theId) occLightSourcesTypes[theId].y
+
+//! Specular intensity (equals to diffuse), vec4.
+#define occLight_Specular(theId) occLightSources[theId * 4 + 0]
+
+//! Position of specified light source, vec4.
+#define occLight_Position(theId) occLightSources[theId * 4 + 1]
+
+//! Direction of specified spot light source, vec4.
+#define occLight_SpotDirection(theId) occLightSources[theId * 4 + 2]
+
+//! Maximum spread angle of the spot light (in radians), float.
+#define occLight_SpotCutOff(theId) occLightSources[theId * 4 + 3].z
+
+//! Attenuation of the spot light intensity (from 0 to 1), float.
+#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w
+
+//! Diffuse intensity (equals to Specular), vec4.
+#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0]
+
+//! Const attenuation factor of positional light source, float.
+#define occLight_ConstAttenuation(theId) occLightSources[theId * 4 + 3].x
+
+//! Linear attenuation factor of positional light source, float.
+#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y
#endif
// Front material properties accessors
// arrays of light sources
uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types
uniform vec4 occLightSources[THE_MAX_LIGHTS * 4]; //!< packed light sources parameters
-
-// light source properties accessors
-int occLight_Type (in int theId) { return occLightSourcesTypes[theId].x; }
-int occLight_IsHeadlight (in int theId) { return occLightSourcesTypes[theId].y; }
-vec4 occLight_Diffuse (in int theId) { return occLightSources[theId * 4 + 0]; }
-vec4 occLight_Specular (in int theId) { return occLightSources[theId * 4 + 0]; }
-vec4 occLight_Position (in int theId) { return occLightSources[theId * 4 + 1]; }
-vec4 occLight_SpotDirection (in int theId) { return occLightSources[theId * 4 + 2]; }
-float occLight_ConstAttenuation (in int theId) { return occLightSources[theId * 4 + 3].x; }
-float occLight_LinearAttenuation (in int theId) { return occLightSources[theId * 4 + 3].y; }
-float occLight_SpotCutOff (in int theId) { return occLightSources[theId * 4 + 3].z; }
-float occLight_SpotExponent (in int theId) { return occLightSources[theId * 4 + 3].w; }
#endif
// material state
"// arrays of light sources\n"
"uniform THE_PREC_ENUM ivec2 occLightSourcesTypes[THE_MAX_LIGHTS]; //!< packed light sources types\n"
"uniform vec4 occLightSources[THE_MAX_LIGHTS * 4]; //!< packed light sources parameters\n"
- "\n"
- "// light source properties accessors\n"
- "int occLight_Type (in int theId) { return occLightSourcesTypes[theId].x; }\n"
- "int occLight_IsHeadlight (in int theId) { return occLightSourcesTypes[theId].y; }\n"
- "vec4 occLight_Diffuse (in int theId) { return occLightSources[theId * 4 + 0]; }\n"
- "vec4 occLight_Specular (in int theId) { return occLightSources[theId * 4 + 0]; }\n"
- "vec4 occLight_Position (in int theId) { return occLightSources[theId * 4 + 1]; }\n"
- "vec4 occLight_SpotDirection (in int theId) { return occLightSources[theId * 4 + 2]; }\n"
- "float occLight_ConstAttenuation (in int theId) { return occLightSources[theId * 4 + 3].x; }\n"
- "float occLight_LinearAttenuation (in int theId) { return occLightSources[theId * 4 + 3].y; }\n"
- "float occLight_SpotCutOff (in int theId) { return occLightSources[theId * 4 + 3].z; }\n"
- "float occLight_SpotExponent (in int theId) { return occLightSources[theId * 4 + 3].w; }\n"
"#endif\n"
"\n"
"// material state\n"
"uniform mat4 occProjectionMatrixInverseTranspose; //!< Transpose of the inverse of the projection matrix\n"
"uniform mat4 occModelWorldMatrixInverseTranspose; //!< Transpose of the inverse of the model-world matrix\n"
"\n"
- "// light type enumeration\n"
+ "// light type enumeration (same as Graphic3d_TypeOfLightSource)\n"
"const int OccLightType_Direct = 1; //!< directional light source\n"
"const int OccLightType_Point = 2; //!< isotropic point light source\n"
"const int OccLightType_Spot = 3; //!< spot light source\n"
"uniform vec4 occLightAmbient; //!< Cumulative ambient color\n"
"#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n"
"uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sources\n"
- "int occLight_Type (in int theId); //!< Type of light source\n"
- "int occLight_IsHeadlight (in int theId); //!< Is light a headlight?\n"
- "vec4 occLight_Diffuse (in int theId); //!< Diffuse intensity for specified light source\n"
- "vec4 occLight_Specular (in int theId); //!< Specular intensity (currently - equals to diffuse intencity)\n"
- "vec4 occLight_Position (in int theId); //!< Position of specified light source\n"
- "vec4 occLight_SpotDirection (in int theId); //!< Direction of specified spot light source\n"
- "float occLight_ConstAttenuation (in int theId); //!< Const attenuation factor of positional light source\n"
- "float occLight_LinearAttenuation (in int theId); //!< Linear attenuation factor of positional light source\n"
- "float occLight_SpotCutOff (in int theId); //!< Maximum spread angle of the spot light (in radians)\n"
- "float occLight_SpotExponent (in int theId); //!< Attenuation of the spot light intensity (from 0 to 1)\n"
+ "\n"
+ "//! Type of light source, int (see OccLightType enum).\n"
+ "#define occLight_Type(theId) occLightSourcesTypes[theId].x\n"
+ "\n"
+ "//! Is light a headlight, int?\n"
+ "#define occLight_IsHeadlight(theId) occLightSourcesTypes[theId].y\n"
+ "\n"
+ "//! Specular intensity (equals to diffuse), vec4.\n"
+ "#define occLight_Specular(theId) occLightSources[theId * 4 + 0]\n"
+ "\n"
+ "//! Position of specified light source, vec4.\n"
+ "#define occLight_Position(theId) occLightSources[theId * 4 + 1]\n"
+ "\n"
+ "//! Direction of specified spot light source, vec4.\n"
+ "#define occLight_SpotDirection(theId) occLightSources[theId * 4 + 2]\n"
+ "\n"
+ "//! Maximum spread angle of the spot light (in radians), float.\n"
+ "#define occLight_SpotCutOff(theId) occLightSources[theId * 4 + 3].z\n"
+ "\n"
+ "//! Attenuation of the spot light intensity (from 0 to 1), float.\n"
+ "#define occLight_SpotExponent(theId) occLightSources[theId * 4 + 3].w\n"
+ "\n"
+ "//! Diffuse intensity (equals to Specular), vec4.\n"
+ "#define occLight_Diffuse(theId) occLightSources[theId * 4 + 0]\n"
+ "\n"
+ "//! Const attenuation factor of positional light source, float.\n"
+ "#define occLight_ConstAttenuation(theId) occLightSources[theId * 4 + 3].x\n"
+ "\n"
+ "//! Linear attenuation factor of positional light source, float.\n"
+ "#define occLight_LinearAttenuation(theId) occLightSources[theId * 4 + 3].y\n"
"#endif\n"
"\n"
"// Front material properties accessors\n"
inline bool Standard_Atomic_CompareAndSwap (volatile int* theValue, int theOldValue, int theNewValue);
// Platform-dependent implementation
-#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__EMSCRIPTEN__)
// gcc explicitly defines the macros __GCC_HAVE_SYNC_COMPARE_AND_SWAP_*
// starting with version 4.4+, although built-in functions
// are available since 4.1.x. However unless __GCC_HAVE_SYNC_COMPARE_AND_SWAP_*
#include <Xw_Window.hxx>
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <Aspect_Convert.hxx>
#include <Aspect_WindowDefinitionError.hxx>
#ifndef _Xw_Window_H__
#define _Xw_Window_H__
-#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__)
+#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX)) && !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
#include <Aspect_Window.hxx>