Fix various MuJoCo Studio build issues on Windows, MacOS and Linux
PiperOrigin-RevId: 833313973 Change-Id: I7ec181374e0bb49c32420d025044c31f6fc3c657
This commit is contained in:
committed by
Copybara-Service
parent
a66cf303f8
commit
8eca9926dc
@@ -276,7 +276,7 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MUJOCO_BUILD_TESTS)
|
||||
if(MUJOCO_BUILD_TESTS OR MUJOCO_BUILD_STUDIO OR MUJOCO_USE_FILAMENT)
|
||||
set(ABSL_PROPAGATE_CXX_STD ON)
|
||||
|
||||
# This specific version of Abseil does not have the following variable. We need to work with BUILD_TESTING
|
||||
@@ -307,6 +307,9 @@ if(MUJOCO_BUILD_TESTS)
|
||||
${BUILD_TESTING_OLD}
|
||||
CACHE BOOL "Build tests." FORCE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(MUJOCO_BUILD_TESTS)
|
||||
|
||||
# Avoid linking errors on Windows by dynamically linking to the C runtime.
|
||||
set(gtest_force_shared_crt
|
||||
|
||||
@@ -28,10 +28,14 @@ set(FILAMENT_SKIP_SDL2 ON)
|
||||
set(FILAMENT_USE_EXTERNAL_ABSL ON)
|
||||
set(FILAMENT_USE_EXTERNAL_BENCHMARK ON)
|
||||
set(FILAMENT_USE_EXTERNAL_GTEST ON)
|
||||
if(WIN32)
|
||||
set(USE_STATIC_CRT OFF)
|
||||
endif()
|
||||
|
||||
fetchpackage(
|
||||
PACKAGE_NAME filament
|
||||
GIT_REPO https://github.com/google/filament.git
|
||||
GIT_TAG ${MUJOCO_DEP_VERSION_filament}
|
||||
)
|
||||
|
||||
set(BUILD_SHARED_LIBS BUILD_SHARED_LIBS_OLD)
|
||||
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_OLD})
|
||||
|
||||
@@ -17,6 +17,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||
set(MUJOCO_FILAMENT_TARGET_NAME mujoco_filament)
|
||||
|
||||
add_library(${MUJOCO_FILAMENT_TARGET_NAME} STATIC)
|
||||
target_compile_definitions(${MUJOCO_FILAMENT_TARGET_NAME} PRIVATE MJ_STATIC)
|
||||
|
||||
target_sources(${MUJOCO_FILAMENT_TARGET_NAME}
|
||||
PUBLIC
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <numbers>
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/Engine.h>
|
||||
@@ -310,7 +311,7 @@ class TubeBuilder {
|
||||
}
|
||||
|
||||
void GenerateVertices(VertexType* ptr, size_t num) const {
|
||||
const float delta_angle = 2.f * M_PI / (float)num_slices_;
|
||||
const float delta_angle = 2.f * std::numbers::pi / (float)num_slices_;
|
||||
const float delta_stack = 2.f / static_cast<float>(num_stacks_);
|
||||
|
||||
int idx = 0;
|
||||
@@ -370,7 +371,8 @@ class ConeBuilder {
|
||||
}
|
||||
void GenerateVertices(VertexType* ptr, std::size_t num) const {
|
||||
// pole: use triangles
|
||||
const float delta_angle = 2.0 * M_PI / static_cast<float>(num_slices_);
|
||||
const float delta_angle =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
const float delta_radius = 1.0f / static_cast<float>(num_stacks_);
|
||||
|
||||
int idx = 0;
|
||||
@@ -460,7 +462,8 @@ class DiskBuilder {
|
||||
}
|
||||
|
||||
void GenerateVertices(VertexType* ptr, std::size_t num) const {
|
||||
const float delta_angle = 2.0 * M_PI / static_cast<float>(num_slices_);
|
||||
const float delta_angle =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
|
||||
int idx = 0;
|
||||
ptr[idx++] = VertexType(float3{0, 0, 0}, orientation_);
|
||||
@@ -514,8 +517,10 @@ class SphereBuilder {
|
||||
}
|
||||
|
||||
void GenerateVertices(VertexType* ptr, size_t num) const {
|
||||
const float lat_angle_delta = M_PI / static_cast<float>(num_stacks_ + 1);
|
||||
const float lon_angle_delta = 2.0 * M_PI / static_cast<float>(num_slices_);
|
||||
const float lat_angle_delta =
|
||||
std::numbers::pi / static_cast<float>(num_stacks_ + 1);
|
||||
const float lon_angle_delta =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
|
||||
// Add the north and south poles.
|
||||
int idx = 0;
|
||||
@@ -621,31 +626,33 @@ class DomeBuilder {
|
||||
}
|
||||
|
||||
void GenerateVertices(VertexType* ptr, size_t num) const {
|
||||
const float lat_angle_delta = 0.5 * M_PI / static_cast<float>(num_stacks_);
|
||||
const float lon_angle_delta = 2.0 * M_PI / static_cast<float>(num_slices_);
|
||||
const float lat_angle_delta =
|
||||
0.5 * std::numbers::pi / static_cast<float>(num_stacks_);
|
||||
const float lon_angle_delta =
|
||||
2.0 * std::numbers::pi / static_cast<float>(num_slices_);
|
||||
|
||||
// Add the pole.
|
||||
int idx = 0;
|
||||
ptr[idx++] = MakeVert(0, 0, 1);
|
||||
// Add the pole.
|
||||
int idx = 0;
|
||||
ptr[idx++] = MakeVert(0, 0, 1);
|
||||
|
||||
// Vertices by latitude.
|
||||
for (int lat = 0; lat < num_stacks_; ++lat) {
|
||||
// +1 because we handle the north pole (which would be at a lat angle of
|
||||
// 0-degrees) explicitly.
|
||||
const float lat_angle = static_cast<float>(lat + 1) * lat_angle_delta;
|
||||
const float cos_lat_angle = std::cos(lat_angle);
|
||||
const float sin_lat_angle = std::sin(lat_angle);
|
||||
const float z = cos_lat_angle;
|
||||
// Vertices by latitude.
|
||||
for (int lat = 0; lat < num_stacks_; ++lat) {
|
||||
// +1 because we handle the north pole (which would be at a lat angle of
|
||||
// 0-degrees) explicitly.
|
||||
const float lat_angle = static_cast<float>(lat + 1) * lat_angle_delta;
|
||||
const float cos_lat_angle = std::cos(lat_angle);
|
||||
const float sin_lat_angle = std::sin(lat_angle);
|
||||
const float z = cos_lat_angle;
|
||||
|
||||
for (int lon = 0; lon < num_slices_; ++lon) {
|
||||
const float lon_angle = static_cast<float>(lon) * lon_angle_delta;
|
||||
const float cos_lon_angle = std::cos(lon_angle);
|
||||
const float sin_lon_angle = std::sin(lon_angle);
|
||||
for (int lon = 0; lon < num_slices_; ++lon) {
|
||||
const float lon_angle = static_cast<float>(lon) * lon_angle_delta;
|
||||
const float cos_lon_angle = std::cos(lon_angle);
|
||||
const float sin_lon_angle = std::sin(lon_angle);
|
||||
|
||||
const float x = sin_lat_angle * cos_lon_angle;
|
||||
const float y = sin_lat_angle * sin_lon_angle;
|
||||
ptr[idx++] = MakeVert(x, y, z);
|
||||
}
|
||||
const float x = sin_lat_angle * cos_lon_angle;
|
||||
const float y = sin_lat_angle * sin_lon_angle;
|
||||
ptr[idx++] = MakeVert(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <numbers>
|
||||
#include <utility>
|
||||
|
||||
#include <filament/Material.h>
|
||||
@@ -201,7 +202,7 @@ void Drawable::SetTransform(const mjvGeom& geom) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, size.z});
|
||||
} else if (j == kCylinderBottomDisk) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, -size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
}
|
||||
} else if (geom.type == mjGEOM_CAPSULE) {
|
||||
// Capsules are a tube with two domes at the ends. We apply an inverse
|
||||
@@ -213,7 +214,7 @@ void Drawable::SetTransform(const mjvGeom& geom) {
|
||||
entity_transform *= mat4::scaling(float3{1, 1, xz_size / size.z});
|
||||
} else if (j == kCapsuleBottomDome) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, -size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
entity_transform *= mat4::scaling(float3{1, 1, xz_size / size.z});
|
||||
}
|
||||
} else if (geom.type == mjGEOM_ARROW) {
|
||||
@@ -229,12 +230,12 @@ void Drawable::SetTransform(const mjvGeom& geom) {
|
||||
mat4::scaling(float3{kArrowHeadSize, kArrowHeadSize, 1.0f});
|
||||
} else if (j == kArrow0ConeDisk) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
entity_transform *=
|
||||
mat4::scaling(float3{kArrowHeadSize, kArrowHeadSize, 1.0f});
|
||||
} else if (j == kArrow0BottomDisk) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, -size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
}
|
||||
} else if (geom.type == mjGEOM_ARROW1) {
|
||||
// An arrow1 is a tube with a cone at the end and a disk cap at the other
|
||||
@@ -245,7 +246,7 @@ void Drawable::SetTransform(const mjvGeom& geom) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, size.z});
|
||||
} else if (j == kArrow1BottomDisk) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, -size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
}
|
||||
} else if (geom.type == mjGEOM_ARROW2) {
|
||||
// An arrow2 is a tube with a cone at both ends. Like the standard arrow,
|
||||
@@ -258,12 +259,12 @@ void Drawable::SetTransform(const mjvGeom& geom) {
|
||||
mat4::scaling(float3{kArrowHeadSize, kArrowHeadSize, 1.0f});
|
||||
} else if (j == kArrow2BottomCone) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, -size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
entity_transform *=
|
||||
mat4::scaling(float3{kArrowHeadSize, kArrowHeadSize, 1.0f});
|
||||
} else if (j == kArrow2TopConeDisk) {
|
||||
entity_transform *= mat4::translation(float3{0, 0, size.z});
|
||||
entity_transform *= mat4::rotation(M_PI, float3{1, 0, 0});
|
||||
entity_transform *= mat4::rotation(std::numbers::pi, float3{1, 0, 0});
|
||||
entity_transform *=
|
||||
mat4::scaling(float3{kArrowHeadSize, kArrowHeadSize, 1.0f});
|
||||
} else if (j == kArrow2BottomConeDisk) {
|
||||
|
||||
@@ -141,9 +141,10 @@ bool GuiView::PrepareRenderable() {
|
||||
}
|
||||
std::memcpy(dst, cmds->IdxBuffer.Data, size);
|
||||
};
|
||||
const mujoco::FilamentBuffers& buffer = buffers_.emplace_back(
|
||||
CreateIndexBuffer<uint16_t>(engine_, cmds->IdxBuffer.Size, ifill),
|
||||
CreateVertexBuffer<GuiVertex>(engine_, cmds->VtxBuffer.Size, vfill));
|
||||
buffers_.push_back(
|
||||
{CreateIndexBuffer<uint16_t>(engine_, cmds->IdxBuffer.Size, ifill),
|
||||
CreateVertexBuffer<GuiVertex>(engine_, cmds->VtxBuffer.Size, vfill)});
|
||||
const mujoco::FilamentBuffers& buffer = buffers_.back();
|
||||
|
||||
int index_offset = 0;
|
||||
for (const ImDrawCmd& command : cmds->CmdBuffer) {
|
||||
@@ -164,7 +165,7 @@ bool GuiView::PrepareRenderable() {
|
||||
clip_height = height;
|
||||
}
|
||||
|
||||
mjrRect clip_rect(clip_left, clip_bottom, clip_width, clip_height);
|
||||
mjrRect clip_rect{clip_left, clip_bottom, clip_width, clip_height};
|
||||
builder.material(drawable_index, GetMaterialInstance(clip_rect));
|
||||
builder.geometry(drawable_index, kTriangles, buffer.vertex_buffer,
|
||||
buffer.index_buffer, index_offset,
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <filament/ColorGrading.h>
|
||||
@@ -96,6 +97,10 @@ struct UiOpts {
|
||||
std::optional<T> fstep;
|
||||
};
|
||||
|
||||
// This is a workaround to fix compilation on gcc <= 12 and clang <= 16
|
||||
template <typename T>
|
||||
struct dependent_false : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
bool Ui(std::string_view label, T* value, UiOpts<T> opts = {}) {
|
||||
bool changed = false;
|
||||
@@ -134,7 +139,7 @@ bool Ui(std::string_view label, T* value, UiOpts<T> opts = {}) {
|
||||
} else if constexpr (std::is_same_v<T, float4>) {
|
||||
changed = ImGui::InputFloat4(label.data(), &value->x);
|
||||
} else {
|
||||
static_assert(false, "Unsupported type");
|
||||
static_assert(dependent_false<T>::value, "Unsupported type");
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "experimental/filament/filament/light.h"
|
||||
|
||||
#include <numbers>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/LightManager.h>
|
||||
#include <filament/Scene.h>
|
||||
@@ -55,9 +57,10 @@ Light::Light(ObjectManager* object_mgr, const Params& params)
|
||||
builder.castShadows(params.castshadow);
|
||||
if (type == filament::LightManager::Type::FOCUSED_SPOT) {
|
||||
if (params.headlight) {
|
||||
builder.spotLightCone(0, M_PI / 2.0f);
|
||||
builder.spotLightCone(0, std::numbers::pi / 2.0f);
|
||||
} else {
|
||||
builder.spotLightCone(0, params.spot_cone_angle * M_PI / 180.0f);
|
||||
builder.spotLightCone(0,
|
||||
params.spot_cone_angle * std::numbers::pi / 180.0f);
|
||||
}
|
||||
}
|
||||
if (type != filament::LightManager::Type::DIRECTIONAL) {
|
||||
|
||||
@@ -132,13 +132,13 @@ void mjr_setBuffer(int framebuffer, mjrContext* con) {
|
||||
}
|
||||
|
||||
void mjr_readPixels(unsigned char* rgb, float* depth, mjrRect viewport,
|
||||
const mjrContext* con) {
|
||||
const mjrContext* con) {
|
||||
CheckFilamentContext();
|
||||
g_filament_context->ReadPixels(viewport, rgb, depth);
|
||||
}
|
||||
|
||||
void mjr_uploadFont(unsigned char* pixels, int width, int height, int bpp,
|
||||
int id, const mjrContext* con) {
|
||||
int id, const mjrContext* con) {
|
||||
CheckFilamentContext();
|
||||
if (bpp != 4) {
|
||||
mju_error("Only 4bpp fonts are supported, got %d", bpp);
|
||||
|
||||
@@ -58,25 +58,25 @@ void mjr_defaultFilamentConfig(mjrFilamentConfig* config);
|
||||
void mjr_makeFilamentContext(const mjModel* m, mjrContext* con,
|
||||
const mjrFilamentConfig* config);
|
||||
|
||||
void mjr_defaultContext(mjrContext* con);
|
||||
MJAPI void mjr_defaultContext(mjrContext* con);
|
||||
|
||||
void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale);
|
||||
MJAPI void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale);
|
||||
|
||||
void mjr_freeContext(mjrContext* con);
|
||||
MJAPI void mjr_freeContext(mjrContext* con);
|
||||
|
||||
void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con);
|
||||
MJAPI void mjr_render(mjrRect viewport, mjvScene* scn, const mjrContext* con);
|
||||
|
||||
void mjr_uploadMesh(const mjModel* m, const mjrContext* con, int meshid);
|
||||
MJAPI void mjr_uploadMesh(const mjModel* m, const mjrContext* con, int meshid);
|
||||
|
||||
void mjr_uploadTexture(const mjModel* m, const mjrContext* con, int texid);
|
||||
MJAPI void mjr_uploadTexture(const mjModel* m, const mjrContext* con, int texid);
|
||||
|
||||
void mjr_uploadFont(unsigned char* pixels, int width, int height, int bpp,
|
||||
int id, const mjrContext* con);
|
||||
|
||||
void mjr_setBuffer(int framebuffer, mjrContext* con);
|
||||
MJAPI void mjr_setBuffer(int framebuffer, mjrContext* con);
|
||||
|
||||
void mjr_readPixels(unsigned char* rgb, float* depth, mjrRect viewport,
|
||||
const mjrContext* con);
|
||||
MJAPI void mjr_readPixels(unsigned char* rgb, float* depth, mjrRect viewport,
|
||||
const mjrContext* con);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
|
||||
@@ -63,9 +63,7 @@ void mjr_label(mjrRect viewport, int font, const char* txt, float r, float g,
|
||||
void mjr_figure(mjrRect viewport, mjvFigure* fig, const mjrContext* con) {
|
||||
mju_error("mjr_figure not implemented.");
|
||||
}
|
||||
void mjr_finish() {
|
||||
mju_error("mjr_finish not implemented.");
|
||||
}
|
||||
void mjr_finish() { mju_error("mjr_finish not implemented."); }
|
||||
int mjr_getError() {
|
||||
mju_error("mjr_getError not implemented.");
|
||||
return 0;
|
||||
|
||||
@@ -47,6 +47,13 @@ target_compile_definitions(${MUJOCO_STUDIO_TARGET_NAME}
|
||||
-D${MUJOCO_STUDIO_RENDER_CONFIG}
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
target_compile_definitions(${MUJOCO_STUDIO_TARGET_NAME}
|
||||
PRIVATE
|
||||
-D_USE_MATH_DEFINES
|
||||
)
|
||||
endif()
|
||||
|
||||
include(third_party_deps/dear_imgui)
|
||||
include(third_party_deps/implot)
|
||||
target_link_libraries(${MUJOCO_STUDIO_TARGET_NAME}
|
||||
@@ -63,13 +70,18 @@ target_link_libraries(${MUJOCO_STUDIO_TARGET_NAME}
|
||||
|
||||
# Filament backend requires additional files to be copied into an "assets" folder.
|
||||
if(MUJOCO_USE_FILAMENT)
|
||||
if(WIN32)
|
||||
# Copy to work around lack of symlink permissions on Windows.
|
||||
set(COPY_COMMAND copy_directory)
|
||||
else()
|
||||
set(COPY_COMMAND create_symlink)
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET ${MUJOCO_STUDIO_TARGET_NAME}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-E create_symlink
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../src/experimental/filament/assets
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets
|
||||
COMMAND ${CMAKE_COMMAND} -E ${COPY_COMMAND}
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../src/experimental/filament/assets
|
||||
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/assets
|
||||
COMMENT "Copying Filament assets to build directory"
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -176,8 +176,8 @@ void App::OnModelLoaded(std::string_view model_file) {
|
||||
window_->SetTitle("MuJoCo Studio : " + std::string(model_file));
|
||||
tmp_.last_load_file = std::string(model_file_);
|
||||
std::filesystem::path path(model_file_);
|
||||
base_path = std::string(path.parent_path()) + "/";
|
||||
model_name = std::string(path.stem());
|
||||
base_path = path.parent_path().string() + "/";
|
||||
model_name = path.stem().string();
|
||||
} else {
|
||||
window_->SetTitle("MuJoCo Studio");
|
||||
tmp_.last_load_file = base_path;
|
||||
|
||||
@@ -171,6 +171,10 @@ struct ImGuiOpts {
|
||||
const char* format = std::is_floating_point_v<T> ? "%.3g" : "%d";
|
||||
};
|
||||
|
||||
// This is a workaround to fix compilation on gcc <= 12 and clang <= 16
|
||||
template <typename T>
|
||||
struct dependent_false : std::false_type {};
|
||||
|
||||
// A compile-time wrapper around ImGui::InputScalarN. This is useful because
|
||||
// MuJoCo uses an `mjtNum` type which is an alias for float or double.
|
||||
//
|
||||
@@ -207,7 +211,7 @@ bool ImGui_InputN(const char* name, T* value, int num, ImGuiOpts<T> opts = {}) {
|
||||
res = ImGui::InputScalarN(name, ImGuiDataType_Double, value, num, pstep,
|
||||
pstep_fast, format);
|
||||
} else {
|
||||
static_assert(false, "Unsupported type");
|
||||
static_assert(dependent_false<T>::value, "Unsupported type");
|
||||
}
|
||||
|
||||
if (opts.min.has_value()) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <numbers>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -2155,7 +2156,7 @@ class ModelWriter {
|
||||
2 * znear *
|
||||
(use_intrinsic ? 1.0f / cam_intrinsic[1] *
|
||||
(cam_sensorsize[1] / 2.f - cam_intrinsic[3])
|
||||
: mju_tan((fovy / 2) * (M_PI / 180.0)));
|
||||
: mju_tan((fovy / 2) * (std::numbers::pi / 180.0)));
|
||||
float horizontal_aperture =
|
||||
use_intrinsic ? 2 * znear / cam_intrinsic[0] *
|
||||
(cam_sensorsize[0] / 2.f - cam_intrinsic[2])
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <numbers>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -1837,8 +1838,8 @@ void ParseUsdPhysicsJoint(mjSpec* spec, const pxr::UsdPrim& prim, mjsBody* body,
|
||||
mj_joint->range[0] = lower;
|
||||
mj_joint->range[1] = upper;
|
||||
} else {
|
||||
mj_joint->range[0] = lower * M_PI / 180.0;
|
||||
mj_joint->range[1] = upper * M_PI / 180.0;
|
||||
mj_joint->range[0] = lower * std::numbers::pi / 180.0;
|
||||
mj_joint->range[1] = upper * std::numbers::pi / 180.0;
|
||||
}
|
||||
}
|
||||
} else if (prim.IsA<pxr::UsdPhysicsPrismaticJoint>()) {
|
||||
@@ -2129,7 +2130,7 @@ mjSpec* mj_parseUSDStage(const pxr::UsdStageRefPtr stage) {
|
||||
return spec;
|
||||
}
|
||||
|
||||
MJAPI mjSpec* mj_parseUSD(const char* identifier, const mjVFS* vfs, char* error,
|
||||
mjSpec* mj_parseUSD(const char* identifier, const mjVFS* vfs, char* error,
|
||||
int error_sz) {
|
||||
auto stage = pxr::UsdStage::Open(identifier);
|
||||
return mj_parseUSDStage(stage);
|
||||
|
||||
Reference in New Issue
Block a user