Cross-platform C++17 port of the popular Javascript 3D library three.js r129.
Most of the core library has been ported, including advanced rendering capabilities, however much remains to be done..
- Line, Points, Mesh, InstancedMesh
- Geometries [Box, Sphere, Plane, Cylindrical, Capsule, Tube, ++]
- Lights [Ambient, Directional, Point, Spot, Hemi]
- Raycasting [Mesh, Line, Points]
- 2D/3D Textures, 3D text, Sprites, RenderTarget
- Transparency, Shadows
- Morphtargets, Bones
- OrbitControls, FlyControls
- Water and Sky shaders
- Loaders [Binary STL, OBJ/MTL, SVG]
- Basic Audio support using miniaudio
- Generic model loader based on Assimp
- Easy integration with Dear ImGui
Builds on Windows, Linux, MacOS, MinGW and with Emscripten.
Because fun.
threepp
is easiest built in conjunction with vcpkg.
Call CMake with -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake
Add optional features by listing them with -DVCPKG_MANIFEST_FEATURES=feature1;feature2
See vcpkg.json for available features.
Under MinGW you'll need to specify the vcpkg triplet:
-DVCPKG_TARGET_TRIPLET=x64-mingw-[static|dynamic] # choose either `static` or `dynamic`.
-DVCPKG_HOST_TRIPLET=x64-mingw-[static|dynamic] # <-- needed only if MSVC cannot be found.
Additionally pass:
-DVCPKG_CHAINLOAD_TOOLCHAIN_FILE="[path to emscripten]\emsdk\upstream\emscripten\cmake\Modules\Platform\Emscripten.cmake"
to CMake. This will generate .html versions of a subset of the examples to be loaded in a browser.
When consuming threepp
in your own application,
some headers will require additional dependencies in order to compile.
Header | Dependency | Description |
---|---|---|
AssimpLoader | assimp | Import a wide variety of different 3D formats |
SVGLoader | pugixml | Import SVG files |
ImguiContext | imgui | ImGUI utility |
Audio* | miniaudio | Audio playback |
In general, you'll find that math classes are value types, while threepp
expect smart pointers for other types.
For convenience, geometries, materials etc. has a static ::create
function that returns a std::shared_ptr
.
Thus, you don't necessarily need to handle memory explicitly using threepp
.
Furthermore, materials, geometries and textures are automatically disposed when they go out of scope.
Yay!
#include "threepp/threepp.hpp"
using namespace threepp;
auto createBox(const Vector3& pos, const Color& color) {
auto geometry = BoxGeometry::create();
auto material = MeshPhongMaterial::create();
material->color = color;
auto box = Mesh::create(geometry, material);
box->position.copy(pos);
return box;
}
auto createPlane() {
auto planeGeometry = PlaneGeometry::create(5, 5);
auto planeMaterial = MeshLambertMaterial::create();
planeMaterial->color = Color::gray;
planeMaterial->side = Side::Double;
auto plane = Mesh::create(planeGeometry, planeMaterial);
plane->position.y = -1;
plane->rotateX(math::degToRad(90));
return plane;
}
int main() {
Canvas canvas("Demo");
GLRenderer renderer{canvas.size()};
auto scene = Scene::create();
auto camera = PerspectiveCamera::create(75, canvas.aspect(), 0.1f, 100);
camera->position.z = 5;
OrbitControls controls{*camera, canvas};
auto light = HemisphereLight::create();
scene->add(light);
auto plane = createPlane();
scene->add(plane);
auto group = Group::create();
group->add(createBox({-1, 0, 0}, Color::green));
group->add(createBox({1, 0, 0}, Color::red));
scene->add(group);
canvas.onWindowResize([&](WindowSize size) {
camera->aspect = size.aspect();
camera->updateProjectionMatrix();
renderer.setSize(size);
});
Clock clock;
canvas.animate([&]() {
float dt = clock.getDelta();
group->rotation.y += 1.f * dt;
renderer.render(*scene, *camera);
});
}
See here for an example of how threepp
may be consumed
as a library in a separate project using vcpkg
.