Loading visuals data from LuaModel, added stub for capsule mesh creation, added sample model rig
parent
caf00bc3ac
commit
d1ada7f3a4
File diff suppressed because it is too large
Load Diff
|
@ -14,6 +14,7 @@
|
|||
#include "Serializer.h"
|
||||
|
||||
#include "CharacterModule.h"
|
||||
#include "LuaTableTypes.h"
|
||||
|
||||
#include "rbdl/addons/luamodel/luatables.h"
|
||||
|
||||
|
@ -26,6 +27,8 @@ bool LuaModelReadFromTable (LuaTable &model_table, Model *model, bool verbose);
|
|||
}
|
||||
}
|
||||
|
||||
// Types needed to parse
|
||||
|
||||
using namespace std;
|
||||
using namespace RigidBodyDynamics;
|
||||
using namespace RigidBodyDynamics::Addons;
|
||||
|
@ -108,6 +111,66 @@ bool CharacterEntity::LoadRig(const char* filename) {
|
|||
gLog ("Creating rig model from %s ... %s", filename, load_result ? "success" : "failed!");
|
||||
gLog ("Rig model has %d degrees of freedom", mRigModel->qdot_size);
|
||||
|
||||
gLog ("Reading rig geometry information ... ");
|
||||
|
||||
int frame_count = model_table["frames"].length();
|
||||
gLog ("Found %d frames", frame_count);
|
||||
|
||||
for (int fi = 1; fi <= frame_count; ++fi) {
|
||||
LuaTableNode frame_table = model_table["frames"][fi];
|
||||
string frame_name = frame_table["name"].getDefault<string>("");
|
||||
int visuals_count = frame_table["visuals"].length();
|
||||
gLog (" Frame %s has %d visuals", frame_name.c_str(), visuals_count);
|
||||
|
||||
for (int vi = 1; vi <= visuals_count; ++vi) {
|
||||
LuaTableNode visual_table = frame_table["visuals"][vi];
|
||||
bool have_geometry = visual_table["geometry"].exists();
|
||||
|
||||
if (!have_geometry) {
|
||||
gLog (" Warning: could not find geometry for visual %d of frame %s",
|
||||
vi, frame_name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector4f color (1.f, 0.f, 1.f, 1.f);
|
||||
if (visual_table["color"].length() == 3) {
|
||||
color.block<3,1>(0,0) = visual_table["color"].getDefault(Vector3f(color.block<3,1>(0,0)));
|
||||
} if (visual_table["color"].length() == 4) {
|
||||
color = visual_table["color"].getDefault(color);
|
||||
}
|
||||
|
||||
Mesh* mesh = nullptr;
|
||||
|
||||
if (visual_table["geometry"]["box"].exists()) {
|
||||
Vector3f dimensions = visual_table["geometry"]["box"]["dimensions"].getDefault(Vector3f (1.f, 1.f, 1.f));
|
||||
mesh = Mesh::sCreateCuboid (
|
||||
dimensions[0],
|
||||
dimensions[1],
|
||||
dimensions[2]
|
||||
);
|
||||
} else if (visual_table["geometry"]["sphere"].exists()) {
|
||||
int rows = static_cast<int>(
|
||||
visual_table["geometry"]["sphere"]["radius"].getDefault (16.f)
|
||||
);
|
||||
int segments = static_cast<int>(
|
||||
visual_table["geometry"]["sphere"]["segments"].getDefault (16.f)
|
||||
);
|
||||
float radius = visual_table["geometry"]["sphere"]["radius"].getDefault (1.f);
|
||||
mesh = Mesh::sCreateUVSphere (rows, segments, radius);
|
||||
} else if (visual_table["geometry"]["capsule"].exists()) {
|
||||
int rows = static_cast<int>(
|
||||
visual_table["geometry"]["capsule"]["radius"].getDefault (16.f)
|
||||
);
|
||||
int segments = static_cast<int>(
|
||||
visual_table["geometry"]["capsule"]["segments"].getDefault (16.f)
|
||||
);
|
||||
float radius = visual_table["geometry"]["capsule"]["radius"].getDefault (1.f);
|
||||
float length = visual_table["geometry"]["capsule"]["length"].getDefault (1.f);
|
||||
mesh = Mesh::sCreateCapsule (rows, segments, length, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return load_result;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Puppeteer - A Motion Capture Mapping Tool
|
||||
* Copyright (c) 2013-2015 Martin Felis <martin.felis@iwr.uni-heidelberg.de>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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 MARKER_MODEL_LUA_TYPES
|
||||
#define MARKER_MODEL_LUA_TYPES
|
||||
|
||||
#include <rbdl/addons/luamodel/luatables.h>
|
||||
|
||||
// SimpleMath Vector3f
|
||||
template<> Vector3f LuaTableNode::getDefault<Vector3f>(const Vector3f &default_value) {
|
||||
Vector3f result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d vector!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
result[0] = static_cast<float>(vector_table[1].get<double>());
|
||||
result[1] = static_cast<float>(vector_table[2].get<double>());
|
||||
result[2] = static_cast<float>(vector_table[3].get<double>());
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LuaTableNode::set<Vector3f>(const Vector3f &value) {
|
||||
LuaTable custom_table = stackCreateLuaTable();
|
||||
|
||||
custom_table[1] = static_cast<double>(value[0]);
|
||||
custom_table[2] = static_cast<double>(value[1]);
|
||||
custom_table[3] = static_cast<double>(value[2]);
|
||||
|
||||
stackRestore();
|
||||
}
|
||||
|
||||
// SimpleMath Vector4f
|
||||
template<> Vector4f LuaTableNode::getDefault<Vector4f>(const Vector4f &default_value) {
|
||||
Vector4f result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 4) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 4d vector!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
result[0] = static_cast<float>(vector_table[1].get<double>());
|
||||
result[1] = static_cast<float>(vector_table[2].get<double>());
|
||||
result[2] = static_cast<float>(vector_table[3].get<double>());
|
||||
result[3] = static_cast<float>(vector_table[4].get<double>());
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// SimpleMath Matrix33f
|
||||
template<> SimpleMath::Fixed::Matrix<float, 3, 3> LuaTableNode::getDefault<SimpleMath::Fixed::Matrix<float, 3, 3> >(const SimpleMath::Fixed::Matrix<float, 3, 3> &default_value) {
|
||||
SimpleMath::Fixed::Matrix<float, 3, 3> result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d matrix!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (vector_table[1].length() != 3
|
||||
|| vector_table[2].length() != 3
|
||||
|| vector_table[3].length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d matrix!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
result(0,0) = static_cast<float>(vector_table[1][1].get<double>());
|
||||
result(0,1) = static_cast<float>(vector_table[1][2].get<double>());
|
||||
result(0,2) = static_cast<float>(vector_table[1][3].get<double>());
|
||||
|
||||
result(1,0) = static_cast<float>(vector_table[2][1].get<double>());
|
||||
result(1,1) = static_cast<float>(vector_table[2][2].get<double>());
|
||||
result(1,2) = static_cast<float>(vector_table[2][3].get<double>());
|
||||
|
||||
result(2,0) = static_cast<float>(vector_table[3][1].get<double>());
|
||||
result(2,1) = static_cast<float>(vector_table[3][2].get<double>());
|
||||
result(2,2) = static_cast<float>(vector_table[3][3].get<double>());
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LuaTableNode::set<SimpleMath::Fixed::Matrix<float, 3, 3> >(const SimpleMath::Fixed::Matrix<float, 3, 3> &value) {
|
||||
LuaTable custom_table = stackCreateLuaTable();
|
||||
|
||||
custom_table[1][1] = static_cast<double>(value(0,0));
|
||||
custom_table[1][2] = static_cast<double>(value(0,1));
|
||||
custom_table[1][3] = static_cast<double>(value(0,2));
|
||||
|
||||
custom_table[2][1] = static_cast<double>(value(1,0));
|
||||
custom_table[2][2] = static_cast<double>(value(1,1));
|
||||
custom_table[2][3] = static_cast<double>(value(1,2));
|
||||
|
||||
custom_table[3][1] = static_cast<double>(value(2,0));
|
||||
custom_table[3][2] = static_cast<double>(value(2,1));
|
||||
custom_table[3][3] = static_cast<double>(value(2,2));
|
||||
|
||||
stackRestore();
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Math::Vector3d LuaTableNode::getDefault<RigidBodyDynamics::Math::Vector3d>(const RigidBodyDynamics::Math::Vector3d &default_value) {
|
||||
RigidBodyDynamics::Math::Vector3d result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d vector!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
result[0] = vector_table[1];
|
||||
result[1] = vector_table[2];
|
||||
result[2] = vector_table[3];
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Math::SpatialVector LuaTableNode::getDefault<RigidBodyDynamics::Math::SpatialVector>(const RigidBodyDynamics::Math::SpatialVector &default_value) {
|
||||
RigidBodyDynamics::Math::SpatialVector result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 6) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 6d vector!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
result[0] = vector_table[1];
|
||||
result[1] = vector_table[2];
|
||||
result[2] = vector_table[3];
|
||||
result[3] = vector_table[4];
|
||||
result[4] = vector_table[5];
|
||||
result[5] = vector_table[6];
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Math::Matrix3d LuaTableNode::getDefault<RigidBodyDynamics::Math::Matrix3d>(const RigidBodyDynamics::Math::Matrix3d &default_value) {
|
||||
RigidBodyDynamics::Math::Matrix3d result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
if (vector_table.length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d matrix!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
if (vector_table[1].length() != 3
|
||||
|| vector_table[2].length() != 3
|
||||
|| vector_table[3].length() != 3) {
|
||||
std::cerr << "LuaModel Error at " << keyStackToString() << " : invalid 3d matrix!" << std::endl;
|
||||
abort();
|
||||
}
|
||||
|
||||
result(0,0) = vector_table[1][1];
|
||||
result(0,1) = vector_table[1][2];
|
||||
result(0,2) = vector_table[1][3];
|
||||
|
||||
result(1,0) = vector_table[2][1];
|
||||
result(1,1) = vector_table[2][2];
|
||||
result(1,2) = vector_table[2][3];
|
||||
|
||||
result(2,0) = vector_table[3][1];
|
||||
result(2,1) = vector_table[3][2];
|
||||
result(2,2) = vector_table[3][3];
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Math::SpatialTransform LuaTableNode::getDefault<RigidBodyDynamics::Math::SpatialTransform>(const RigidBodyDynamics::Math::SpatialTransform &default_value) {
|
||||
RigidBodyDynamics::Math::SpatialTransform result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
result.r = vector_table["r"].getDefault<RigidBodyDynamics::Math::Vector3d>(RigidBodyDynamics::Math::Vector3d::Zero(3));
|
||||
result.E = vector_table["E"].getDefault<RigidBodyDynamics::Math::Matrix3d>(RigidBodyDynamics::Math::Matrix3d::Identity (3,3));
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Joint LuaTableNode::getDefault<RigidBodyDynamics::Joint>(const RigidBodyDynamics::Joint &default_value) {
|
||||
using namespace RigidBodyDynamics;
|
||||
using namespace RigidBodyDynamics::Math;
|
||||
|
||||
Joint result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
int joint_dofs = vector_table.length();
|
||||
|
||||
if (joint_dofs == 1) {
|
||||
std::string dof_string = vector_table[1].getDefault<std::string>("");
|
||||
if (dof_string == "JointTypeSpherical") {
|
||||
stackRestore();
|
||||
return Joint(JointTypeSpherical);
|
||||
} else if (dof_string == "JointTypeEulerZYX") {
|
||||
stackRestore();
|
||||
return Joint(JointTypeEulerZYX);
|
||||
}
|
||||
if (dof_string == "JointTypeEulerXYZ") {
|
||||
stackRestore();
|
||||
return Joint(JointTypeEulerXYZ);
|
||||
}
|
||||
if (dof_string == "JointTypeEulerYXZ") {
|
||||
stackRestore();
|
||||
return Joint(JointTypeEulerYXZ);
|
||||
}
|
||||
if (dof_string == "JointTypeTranslationXYZ") {
|
||||
stackRestore();
|
||||
return Joint(JointTypeTranslationXYZ);
|
||||
}
|
||||
}
|
||||
|
||||
if (joint_dofs > 0) {
|
||||
if (vector_table[1].length() != 6) {
|
||||
std::cerr << "LuaModel Error: invalid joint motion subspace description at " << this->keyStackToString() << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
switch (joint_dofs) {
|
||||
case 0: result = Joint(JointTypeFixed);
|
||||
break;
|
||||
case 1: result = Joint (vector_table[1].get<SpatialVector>());
|
||||
break;
|
||||
case 2: result = Joint(
|
||||
vector_table[1].get<SpatialVector>(),
|
||||
vector_table[2].get<SpatialVector>()
|
||||
);
|
||||
break;
|
||||
case 3: result = Joint(
|
||||
vector_table[1].get<SpatialVector>(),
|
||||
vector_table[2].get<SpatialVector>(),
|
||||
vector_table[3].get<SpatialVector>()
|
||||
);
|
||||
break;
|
||||
case 4: result = Joint(
|
||||
vector_table[1].get<SpatialVector>(),
|
||||
vector_table[2].get<SpatialVector>(),
|
||||
vector_table[3].get<SpatialVector>(),
|
||||
vector_table[4].get<SpatialVector>()
|
||||
);
|
||||
break;
|
||||
case 5: result = Joint(
|
||||
vector_table[1].get<SpatialVector>(),
|
||||
vector_table[2].get<SpatialVector>(),
|
||||
vector_table[3].get<SpatialVector>(),
|
||||
vector_table[4].get<SpatialVector>(),
|
||||
vector_table[5].get<SpatialVector>()
|
||||
);
|
||||
break;
|
||||
case 6: result = Joint(
|
||||
vector_table[1].get<SpatialVector>(),
|
||||
vector_table[2].get<SpatialVector>(),
|
||||
vector_table[3].get<SpatialVector>(),
|
||||
vector_table[4].get<SpatialVector>(),
|
||||
vector_table[5].get<SpatialVector>(),
|
||||
vector_table[6].get<SpatialVector>()
|
||||
);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Invalid number of DOFs for joint." << std::endl;
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<> RigidBodyDynamics::Body LuaTableNode::getDefault<RigidBodyDynamics::Body>(const RigidBodyDynamics::Body &default_value) {
|
||||
RigidBodyDynamics::Body result = default_value;
|
||||
|
||||
if (stackQueryValue()) {
|
||||
LuaTable vector_table = LuaTable::fromLuaState (luaTable->L);
|
||||
|
||||
double mass = 0.;
|
||||
RigidBodyDynamics::Math::Vector3d com (RigidBodyDynamics::Math::Vector3d::Zero(3));
|
||||
RigidBodyDynamics::Math::Matrix3d inertia (RigidBodyDynamics::Math::Matrix3d::Identity(3,3));
|
||||
|
||||
mass = vector_table["mass"];
|
||||
com = vector_table["com"].getDefault<RigidBodyDynamics::Math::Vector3d>(com);
|
||||
inertia = vector_table["inertia"].getDefault<RigidBodyDynamics::Math::Matrix3d>(inertia);
|
||||
|
||||
result = RigidBodyDynamics::Body (mass, com, inertia);
|
||||
}
|
||||
|
||||
stackRestore();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* MARKER_MODEL_LUA_TYPES */
|
||||
#endif
|
|
@ -1176,3 +1176,84 @@ Mesh* Mesh::sCreateCylinder (int segments) {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
Mesh* Mesh::sCreateCapsule (int rows, int segments, float length, float radius) {
|
||||
Mesh* result = new Mesh();
|
||||
|
||||
// work arrays that we fill with data
|
||||
std::vector<Vector4f> &vertices = result->mVertices;
|
||||
std::vector<Vector3f> &normals = result->mNormals;
|
||||
std::vector<Vector4f> &colors = result->mColors;
|
||||
|
||||
float delta = 2. * M_PI / static_cast<float>(segments);
|
||||
for (unsigned int i = 0; i < segments; i++) {
|
||||
float r0 = (i - 0.5) * delta;
|
||||
float r1 = (i + 0.5) * delta;
|
||||
|
||||
float c0 = cos (r0);
|
||||
float s0 = sin (r0);
|
||||
|
||||
float c1 = cos (r1);
|
||||
float s1 = sin (r1);
|
||||
|
||||
Vector3f normal0 (-c0, -s0, 0.f);
|
||||
Vector3f normal1 (-c1, -s1, 0.f);
|
||||
|
||||
Vector4f normal0_4 (-c0, -s0, 0.f, 0.f);
|
||||
Vector4f normal1_4 (-c1, -s1, 0.f, 0.f);
|
||||
|
||||
Vector4f p0 = normal0_4 + Vector4f (0., 0., 0.5f, 1.0f);
|
||||
Vector4f p1 = normal0_4 + Vector4f (0., 0., -0.5f, 1.0f);
|
||||
Vector4f p2 = normal1_4 + Vector4f (0., 0., 0.5f, 1.0f);
|
||||
Vector4f p3 = normal1_4 + Vector4f (0., 0., -0.5f, 1.0f);
|
||||
|
||||
// side triangle 1
|
||||
vertices.push_back(p0);
|
||||
normals.push_back(normal0);
|
||||
|
||||
vertices.push_back(p1);
|
||||
normals.push_back(normal0);
|
||||
|
||||
vertices.push_back(p2);
|
||||
normals.push_back(normal1);
|
||||
|
||||
// side triangle 2
|
||||
vertices.push_back(p2);
|
||||
normals.push_back(normal1);
|
||||
|
||||
vertices.push_back(p1);
|
||||
normals.push_back(normal0);
|
||||
|
||||
vertices.push_back(p3);
|
||||
normals.push_back(normal1);
|
||||
|
||||
// upper end triangle
|
||||
Vector3f normal (0.f, 0.f, 1.f);
|
||||
|
||||
vertices.push_back(p0);
|
||||
normals.push_back(normal);
|
||||
|
||||
vertices.push_back(p2);
|
||||
normals.push_back(normal);
|
||||
|
||||
vertices.push_back(Vector4f (0.f, 0.f, 0.5f, 1.0f));
|
||||
normals.push_back(normal);
|
||||
|
||||
// lower end triangle
|
||||
normal = Vector3f(0.f, 0.f, -1.f);
|
||||
|
||||
vertices.push_back(p3);
|
||||
normals.push_back(normal);
|
||||
|
||||
vertices.push_back(p1);
|
||||
normals.push_back(normal);
|
||||
|
||||
vertices.push_back(Vector4f (0.f, 0.f, -0.5f, 1.0f));
|
||||
normals.push_back(normal);
|
||||
}
|
||||
|
||||
result->Update();
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ struct Mesh {
|
|||
static Mesh *sCreateCuboid (float width, float height, float depth);
|
||||
static Mesh *sCreateUVSphere (int rows, int segments, float radius = 1.0f);
|
||||
static Mesh *sCreateCylinder (int segments);
|
||||
static Mesh *sCreateCapsule (int rows, int segments, float length, float radius);
|
||||
};
|
||||
|
||||
namespace bgfxutils {
|
||||
|
|
Loading…
Reference in New Issue