Panda3D WebGL Port!

I successfully compiled the WebGL port, but get this error when trying to run the music box program. abort(To use dlopen, you need to use Emscripten’s linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking).

Hi, you would need to use “-s MAIN_MODULE=1” to activate dlfcn support, but note that emsdk upstream (clang 10) version does not actually support that but is the version that will replace fastcomp sooner or later.

So be sure to have selected “fastcomp” branch

Meanwhile you may want to watch https://github.com/emscripten-core/emscripten/issues/9516 about when webgl port will be able to use upstream emscripten. or you can modify makepanda to statically link everything and call initializer yourself via C ( eg after python init )

Thanks for the info. Where do I put the “-s MAIN_MODULE=1”? I am using freezify.py from this zip file http://rdb.name/webgl-music-box.zip.

Sorry that’s a long time i did not use freezify, it was first used with python2. i’ve switched to python 3.7/3.8, web assembly and a more generic approach for cross compiling both android and emscripten.

maybe try linkExe with “-s MAIN_MODULE=1 -s EXPORT_ALL=1 -ldl” ?

sidenote libpython is ready as can be seen there https://pmp-p.github.io/python-next/test.html
but panda3d libraries are more exigeant and will need few months work to run (they already build) with emscripten upstream.

now it works fine https://pmp-p.github.io/panda3d-next/py3/

maybe help try porting some demos with https://github.com/pmp-p/pydk-applications

I am getting this error. error: Linking globals named ‘Py_FrozenMain’: symbol multiply defined!
shared:ERROR: Failed to run llvm optimizations:

I updated this archive to contain a build of Python 3.8 instead of the deprecated Python 2.7:
http://rdb.name/webgl-editor-and-dependencies.zip
It also includes the patch and command I used to build it. The Roaming Ralph sample and build script are included.

I also committed WebGL 2 support to the webgl-port branch, and I updated the online editor demo to use Python 3.8, WebAssembly and WebGL 2:
http://rdb.name/panda3d-webgl/editor.html

3 Likes

Some updates: I have created two modules, emscripten and browser, that enable more interoperability with the browser and the JavaScript runtime.

With these modules, it’s now possible to make a call to any JavaScript or Web API directly from Python. It’s even possible to use Python functions as callbacks, but it’s not possible to store any other Python objects inside the JavaScript runtime, or access Python objects from JS.

I updated my editor.html link with a few extra samples showing how this is used. For example, you can use the browser’s XMLHttpRequest API or the newer Fetch API to download resources (although note that the emscripten module provides a more convenient and efficient, albeit less powerful, interface for downloading files).

To use these modules, download these files:
http://rdb.name/panda3d-webgl/browsermodule.c
http://rdb.name/panda3d-webgl/emscriptenmodule.c
… and add them to your build. It’s easiest to just add these two lines to the top of your frozenMainCode:

#include "emscriptenmodule.c"
#include "browsermodule.c"

… and adding them to sys.modules, after initializing the Python interpreter:

    PyObject *sys_modules = PySys_GetObject("modules");
    PyDict_SetItemString(sys_modules, "emscripten", PyInit_emscripten());
    PyDict_SetItemString(sys_modules, "browser", PyInit_browser());

I may decide to bundle these with the Python distribution, since they’re not Panda-specific.

1 Like

I would like to embed Panda3D in a Jupiter notebook cell. Do you think it is doable ? And if so, do you think it is a lot of working to get pre-compiled binaries with cross-platform compatibility ?

I don’t know anything about how Jupyter works, sorry.

Hello, I want to use Enscriptem to compile a Panda example to html and Js so I can run it on localhost. I’m not sure what the steps are to do this. Any help would be appreciated!

I’ve updated the WebGL branch with a new feature: the HTTPClient and HTTPChannel APIs are now supported in the browser. As a consequence, we can use Panda’s HTTP mount system to mount web folders to the virtual file system. By default, Panda will mount the current web root to the root of the virtual file system.

This means it is no longer necessary to add files to the preload bundle. You can just load a texture or model and if the file is not present in the preload bundle, it will be automatically downloaded relative to the current directory on the server!

I have also updated https://rdb.name/webgl-editor-and-dependencies.zip, updated for the latest emscripten version and the Python version is now updated to 3.8.10.

I have also created some documentation that explains how to compile the WebGL port and how to build an application for the web:
https://rdb.name/panda3d-webgl.md.html

4 Likes

Thanks @rdb for pushing up the changes and adding docs! This is super exciting stuff.

I tried running through the WebGL compilation guide but am getting stuck at step 1.3:

cd editor
python3.8 -OO freezify.py

I edited my freezify.py to point to the correct directories. When I run it, emscripten complains:

emcc: error: /home/.../panda3d/built/lib/libp3openal_audio.a: No such file or directory
("/home/.../panda3d/built/lib/libp3openal_audio.a" was expected to be an input file,
based on the commandline arguments provided)

I’m not sure where to get this static library file libp3openal_audio.a. FWIW, I’ve attempted to build third party dependencies using makepanda.py --everything on both master and webgl-port.

I do have libp3openal_audio.so instead. However if I disable the PANDA_STATIC flag in order to use dynamic libs, emscripten complains with something different:

emcc: error: /home/.../panda3d/built/panda3d/core.o: No such file or directory
("/home/.../panda3d/built/panda3d/core.o" was expected to be an input file,
based on the commandline arguments provided)

I’m not sure how to emit this core.o object file.

If anyone could provide some pointers on how to get one or both of libp3openal_audio.a or core.o it would be greatly appreciated :slight_smile:

Are you following these instructions? They include a makepanda command for building the WebGL port, which includes the --static flag (along with some other required flags, like --target emscripten). That’s what I recommend that since that’s what I use and it works well.

I am not sure exactly how the Python modules like core.o are emitted by makepanda in a non-static build—do they simply have the .so extension? Please take a look in the built/panda3d directory to see if they were built at all or what they were called.

If they weren’t built at all, look at the output of the makepanda command in the webgl-port branch, it may give some clues.

Ah my bad, looks like in my debugging I cleared the built folder and never ended up rerunning makepanda.py with the right flags. Everything’s working now, appreciate the help (and this awesome update)!

I built the webgl port, though I am having issues when I try to run the Roaming Ralph sample. I get these errors:

Python 3.8.10 (tags/v3.8.10-dirty:3d8993a744, Nov 28 2021, 00:07:03)
[Clang 14.0.0 (GitHub - llvm/llvm-project: The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Note: the repository does not accept github pull requests at this moment. Please submit your patches at http://reviews.llvm.org. 4348cd42c385e71b63e5da7e492
Aborted(native code called abort())
RuntimeError: Aborted(native code called abort()) (evaluating ‘new WebAssembly.RuntimeError(what)’)

I’ve forgotten to mention that that issue has been fixed as of the latest version of the panda3d-webgl branch. It was happening when the html file was directly under the web root. Let me know if you are still encountering trouble.

1 Like

So will this Panda3D WebGL Live Python Editor be the place where I need to code in? Because I can’t find any way to publish it.

Or do I need to follow these instructions. https://rdb.name/panda3d-webgl.md.html

This is just a demonstration of real-time code editing in the browser.

Yes, you need to start with that.

Some time ago I tested this on Windows. I am successfully building panda with Emscripten, except for some moments.

The end of the sbrki breaks because of the command.

os.system("chmod +x " + BracketNameWithQuotes(dll))

I have made such a patch:

        # fix for emscripten, which is on windows.
        if GetHost() != "windows":
            os.system("chmod +x " + BracketNameWithQuotes(dll))

Another problem is the absence of the OpenAL library in the third-party dependencies folder, I can’t imagine where it can be taken.

Therefore, I put together an example of Ralph without a sound module, having previously set in the script.

loadPrcFileData("", "audio-library-name null")

However, when I freeze Ralph’s example, I get this console output.

D:\panda3d-webgl\roaming-ralph>call D:\emsdk\emsdk_env.bat
Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1)
Adding directories to PATH:
PATH += D:\emsdk
PATH += D:\emsdk\upstream\emscripten
PATH += D:\emsdk\node\14.18.2_64bit\bin

Setting environment variables:
PATH = D:\emsdk;D:\emsdk\upstream\emscripten;D:\emsdk\node\14.18.2_64bit\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\Git\cmd;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Users\sereg\AppData\Local\Programs\Python\Python38\Scripts\;C:\Users\sereg\AppData\Local\Programs\Python\Python38\;C:\Users\sereg\AppData\Local\Microsoft\WindowsApps;D:\Panda3D-1.10.10-x64\python;D:\Panda3D-1.10.10-x64\python\Scripts;D:\Panda3D-1.10.10-x64\bin
EMSDK = D:/emsdk
EM_CONFIG = D:\emsdk\.emscripten
EMSDK_NODE = D:\emsdk\node\14.18.2_64bit\bin\node.exe
EMSDK_PYTHON = D:\emsdk\python\3.9.2-nuget_64bit\python.exe
JAVA_HOME = D:\emsdk\java\8.152_64bit
Clearing existing environment variable: EMSDK_PY
There are some missing modules: ['__builtin__', '_posixsubprocess', 'grp', 'panda3d.core', 'panda3d.direct']
emcc -O3 -fno-exceptions -fno-rtti -c -o roaming-ralph.o roaming-ralph.c -ID:/panda3d-webgl/thirdparty/emscripten-libs/python/include/python3.8
emcc -O3 -s TOTAL_MEMORY=50331648 -s ASSERTIONS=0 -s MAX_WEBGL_VERSION=2 -s NO_EXIT_RUNTIME=1 -fno-exceptions -fno-rtti -o roaming-ralph.js roaming-ralph.o  D:/panda3d-webgl/thirdparty/emscripten-libs/python/lib/libpython3.8.a  D:/panda3d-webgl/built/lib/libpy.panda3d.core.a D:/panda3d-webgl/built/lib/libpy.panda3d.direct.a D:/panda3d-webgl/built/lib/libp3interrogatedb.a D:/panda3d-webgl/built/lib/libpanda.a D:/panda3d-webgl/built/lib/libpandaexpress.a D:/panda3d-webgl/built/lib/libp3dtool.a D:/panda3d-webgl/built/lib/libp3dtoolconfig.a D:/panda3d-webgl/built/lib/libp3webgldisplay.a D:/panda3d-webgl/built/lib/libp3direct.a -ID:/panda3d-webgl/built/include -s USE_ZLIB=1 -s USE_VORBIS=1 -s USE_LIBPNG=1 -s USE_FREETYPE=1 -s USE_HARFBUZZ=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s DISABLE_EXCEPTION_THROWING=0  --preload-file models/ground.jpg --preload-file models/hedge.jpg --preload-file models/ralph.bam --preload-file models/ralph.jpg --preload-file models/ralph-run.bam --preload-file models/ralph-walk.bam --preload-file models/rock03.jpg --preload-file models/tree.jpg --preload-file models/world.bam
wasm-ld: warning: function signature mismatch: time
>>> defined as (i32) -> i32 in D:/panda3d-webgl/thirdparty/emscripten-libs/python/lib/libpython3.8.a(timemodule.o)
>>> defined as (i32) -> i64 in D:\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libc.a(emscripten_time.o)

wasm-ld: warning: function signature mismatch: mktime
>>> defined as (i32) -> i32 in D:/panda3d-webgl/thirdparty/emscripten-libs/python/lib/libpython3.8.a(timemodule.o)
>>> defined as (i32) -> i64 in D:\emsdk\upstream\emscripten\cache\sysroot\lib\wasm32-emscripten\libc.a(emscripten_time.o)

There are warnings. And then when you try to run in the browser, nothing happens, but there are errors in the Javascript console.

roaming-ralph.html:161 Python 3.8.10 (tags/v3.8.10-dirty:3d8993a744, Nov 28 2021, 00:07:03) 
printErr @ roaming-ralph.html:161

roaming-ralph.html:161 [Clang 14.0.0 (https://github.com/llvm/llvm-project 4348cd42c385e71b63e5da7e492
printErr @ roaming-ralph.html:161

roaming-ralph.js:1 Uncaught RuntimeError: unreachable
    at roaming-ralph.wasm:0x81b88c
    at roaming-ralph.wasm:0x9c0bec
    at roaming-ralph.wasm:0x63e083
    at roaming-ralph.wasm:0x232f3c
    at roaming-ralph.wasm:0x231e7a
    at roaming-ralph.wasm:0x2fdb52
    at roaming-ralph.wasm:0x2204a2
    at roaming-ralph.wasm:0x7132db
    at roaming-ralph.wasm:0x21f33c
    at roaming-ralph.wasm:0x2fd738
1 Like

I added a debug symbol when compiling ralph, now I have this.

roaming-ralph.html:161 Python 3.8.10 (tags/v3.8.10-dirty:3d8993a744, Nov 28 2021, 00:07:03) 
printErr @ roaming-ralph.html:161

roaming-ralph.html:161 [Clang 14.0.0 (https://github.com/llvm/llvm-project 4348cd42c385e71b63e5da7e492
printErr @ roaming-ralph.html:161

roaming-ralph.js:219 Uncaught RuntimeError: unreachable
    at signature_mismatch:time (roaming-ralph.wasm:0x29c23)
    at PyInit_time (timemodule.c:1774:9)
    at _imp_create_builtin (import.c:1225:19)
    at cfunction_vectorcall_O (methodobject.c:482:24)
    at PyVectorcall_Call (call.c:200:24)
    at PyCFunction_Call (call.c:775:12)
    at _PyEval_EvalFrameDefault (ceval.c:4983:9)
    at _PyEval_EvalCodeWithName (pycore_object.h:44:41)
    at _PyFunction_Vectorcall (call.c:436:12)
    at call_function (abstract.h:127:11)