Merge remote-tracking branch 'upstream/master'

This commit is contained in:
yunfeibai
2016-05-10 10:18:27 -07:00
101 changed files with 5737 additions and 301 deletions

View File

@@ -191,6 +191,17 @@ IF (APPLE)
ENDIF()
OPTION(BUILD_BULLET3 "Set when you want to build Bullet 3" ON)
OPTION(BUILD_PYBULLET "Set when you want to build pybullet (experimental Python bindings for Bullet)" OFF)
IF(BUILD_PYBULLET)
IF(WIN32)
FIND_PACKAGE(PythonLibs 3.4 REQUIRED)
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "Shared Libs" FORCE)
ELSE(WIN32)
FIND_PACKAGE(PythonLibs 2.7 REQUIRED)
SET(BUILD_SHARED_LIBS ON CACHE BOOL "Shared Libs" FORCE)
ENDIF(WIN32)
ENDIF(BUILD_PYBULLET)
IF(BUILD_BULLET3)
IF(APPLE)

View File

@@ -73,6 +73,14 @@
description = "Enable Lua scipting support in Example Browser"
}
newoption
{
trigger = "python",
description = "Enable Python scripting (experimental, use Physics Server in Example Browser). "
}
newoption {
trigger = "targetdir",
value = "path such as ../bin",
@@ -181,16 +189,20 @@
include "../examples/OpenGLWindow"
include "../examples/ThirdPartyLibs/Gwen"
include "../examples/SimpleOpenGL3"
include "../examples/TinyRenderer"
include "../examples/HelloWorld"
include "../examples/BasicDemo"
include "../examples/InverseDynamics"
include "../examples/SharedMemory"
include "../examples/MultiThreading"
if _OPTIONS["lua"] then
include "../examples/ThirdPartyLibs/lua-5.2.3"
end
if _OPTIONS["python"] then
include "../examples/pybullet"
end
if not _OPTIONS["no-test"] then
include "../test/SharedMemory"

View File

@@ -1,10 +1,17 @@
<?xml version="0.0" ?>
<robot name="urdf_door">
<link name="world"/>
<joint name="fixed" type="fixed">
<parent link="world"/>
<child link="baseLink"/>
<origin xyz="0 0 0"/>
</joint>
<link name="baseLink">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0.35"/>
<mass value="0.0"/>
<inertia ixx="0" ixy="0" ixz="0" iyy="0" iyz="0" izz="0"/>
<mass value="1.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<origin rpy="0 0 0" xyz="0.05 0 0.5"/>

13
data/floor.mtl Normal file
View File

@@ -0,0 +1,13 @@
newmtl floor
Ns 10.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.0000 0.0000 0.0000
Kd 0.5880 0.5880 0.5880
Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000
map_Ka floor_diffuse.jpg
map_Kd floor_diffuse.jpg

18
data/floor.obj Normal file
View File

@@ -0,0 +1,18 @@
o
mtllib floor.mtl
v -1 -1 -1
v 1 -1 -1
v 1 -1 1
v -1 -1 1
vt 0 0
vt 1 0
vt 1 1
vt 0 1
vn 0 1 0
usemtl floor
f 3/3/1 2/2/1 1/1/1
f 4/4/1 3/3/1 1/1/1

BIN
data/floor_diffuse.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
data/floor_diffuse.tga Normal file

Binary file not shown.

BIN
data/floor_nm_tangent.tga Normal file

Binary file not shown.

Binary file not shown.

239
data/two_cubes.sdf Normal file
View File

@@ -0,0 +1,239 @@
<sdf version='1.6'>
<world name='default'>
<light name='sun' type='directional'>
<yunfei>99.2</yunfei>
<cast_shadows>1</cast_shadows>
<pose frame=''>0 0 10 0 -0 0</pose>
<diffuse>0.8 0.8 0.8 1</diffuse>
<specular>0.2 0.2 0.2 1</specular>
<attenuation>
<range>1000</range>
<constant>0.9</constant>
<linear>0.01</linear>
<quadratic>0.001</quadratic>
</attenuation>
<direction>-0.5 0.1 -0.9</direction>
</light>
<model name='ground_plane'>
<static>1</static>
<link name='link'>
<collision name='collision'>
<geometry>
<plane>
<normal>1 2 3</normal>
<size>100 100</size>
</plane>
</geometry>
<surface>
<contact>
<collide_bitmask>65535</collide_bitmask>
<ode/>
</contact>
<friction>
<ode>
<mu>100</mu>
<mu2>50</mu2>
</ode>
<torsional>
<ode/>
</torsional>
</friction>
<bounce/>
</surface>
<max_contacts>10</max_contacts>
</collision>
<visual name='visual'>
<cast_shadows>0</cast_shadows>
<geometry>
<plane>
<normal>4 5 6</normal>
<size>100 100</size>
</plane>
</geometry>
<material>
<script>
<uri>file://media/materials/scripts/gazebo.material</uri>
<name>Gazebo/Grey</name>
</script>
</material>
</visual>
<self_collide>0</self_collide>
<kinematic>0</kinematic>
<gravity>1</gravity>
</link>
</model>
<gravity>0 0 -9.8</gravity>
<magnetic_field>6e-06 2.3e-05 -4.2e-05</magnetic_field>
<atmosphere type='adiabatic'/>
<physics name='default_physics' default='0' type='ode'>
<max_step_size>0.001</max_step_size>
<real_time_factor>1</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
</physics>
<scene>
<ambient>0.4 0.4 0.4 1</ambient>
<background>0.7 0.7 0.7 1</background>
<shadows>1</shadows>
</scene>
<audio>
<device>default</device>
</audio>
<spherical_coordinates>
<surface_model>EARTH_WGS84</surface_model>
<latitude_deg>0</latitude_deg>
<longitude_deg>0</longitude_deg>
<elevation>0</elevation>
<heading_deg>0</heading_deg>
</spherical_coordinates>
<model name='unit_box_0'>
<pose frame=''>0.512455 -1.58317 0.5 0 -0 0</pose>
<link name='unit_box_0::link'>
<inertial>
<mass>1</mass>
<inertia>
<ixx>0.166667</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.166667</iyy>
<iyz>0</iyz>
<izz>0.166667</izz>
</inertia>
</inertial>
<collision name='collision'>
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<visual name='visual'>
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<material>
<script>
<name>Gazebo/Grey</name>
<uri>file://media/materials/scripts/gazebo.material</uri>
</script>
</material>
</visual>
<self_collide>0</self_collide>
<kinematic>0</kinematic>
<gravity>1</gravity>
</link>
</model>
<model name='unit_box_0_clone'>
<pose frame=''>0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159</pose>
<link name='unit_box_0::link'>
<inertial>
<mass>1</mass>
<inertia>
<ixx>0.166667</ixx>
<ixy>0</ixy>
<ixz>0</ixz>
<iyy>0.166667</iyy>
<iyz>0</iyz>
<izz>0.166667</izz>
</inertia>
</inertial>
<collision name='collision'>
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<max_contacts>10</max_contacts>
<surface>
<contact>
<ode/>
</contact>
<bounce/>
<friction>
<torsional>
<ode/>
</torsional>
<ode/>
</friction>
</surface>
</collision>
<visual name='visual'>
<geometry>
<box>
<size>1 1 1</size>
</box>
</geometry>
<material>
<script>
<name>Gazebo/Grey</name>
<uri>file://media/materials/scripts/gazebo.material</uri>
</script>
</material>
</visual>
<self_collide>0</self_collide>
<kinematic>0</kinematic>
<gravity>1</gravity>
</link>
</model>
<state world_name='default'>
<sim_time>0 0</sim_time>
<real_time>0 0</real_time>
<wall_time>1462824251 956472000</wall_time>
<iterations>0</iterations>
<model name='ground_plane'>
<pose frame=''>0 0 0 0 -0 0</pose>
<scale>1 1 1</scale>
<link name='link'>
<pose frame=''>0 0 0 0 -0 0</pose>
<velocity>0 0 0 0 -0 0</velocity>
<acceleration>0 0 0 0 -0 0</acceleration>
<wrench>0 0 0 0 -0 0</wrench>
</link>
</model>
<model name='unit_box_0'>
<pose frame=''>0.223196 -1.84719 0.499995 -2.89297 -0.988287 -3.14159</pose>
<scale>1 1 1</scale>
<link name='unit_box_0::link'>
<pose frame=''>0.223196 -1.84719 0.499995 -2.89297 -0.988287 -3.14159</pose>
<velocity>0.004896 3e-06 -0.004891 -6e-06 0.009793 -0</velocity>
<acceleration>0.010615 0.006191 -9.78231 -0.012424 0.021225 -1.8e-05</acceleration>
<wrench>0.010615 0.006191 -9.78231 0 -0 0</wrench>
</link>
</model>
<model name='unit_box_0_clone'>
<pose frame=''>0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159</pose>
<scale>1 1 1</scale>
<link name='unit_box_0::link'>
<pose frame=''>0.105158 -4.55002 0.499995 -2.89297 -0.988287 -3.14159</pose>
<velocity>0 0 0 0 -0 0</velocity>
<acceleration>0 0 0 0 -0 0</acceleration>
<wrench>0 0 0 0 -0 0</wrench>
</link>
</model>
<light name='sun'>
<pose frame=''>0 0 10 0 -0 0</pose>
</light>
</state>
<gui fullscreen='0'>
<camera name='user_camera'>
<pose frame=''>8.0562 -8.87312 3.07529 0 0.205021 2.5208</pose>
<view_controller>orbit</view_controller>
<projection_type>perspective</projection_type>
</camera>
</gui>
</world>
</sdf>

View File

@@ -52,7 +52,7 @@ void BasicExample::initPhysics()
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
//m_dynamicsWorld->setGravity(btVector3(0,0,0));
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
@@ -63,7 +63,7 @@ void BasicExample::initPhysics()
//groundShape->initializePolyhedralFeatures();
// btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
//btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),50);
m_collisionShapes.push_back(groundShape);
@@ -140,7 +140,11 @@ void BasicExample::renderScene()
CommonExampleInterface* BasicExampleCreateFunc(CommonExampleOptions& options)
{
return new BasicExample(options.m_guiHelper);
}
B3_STANDALONE_EXAMPLE(BasicExampleCreateFunc)

View File

@@ -29,3 +29,72 @@ IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(App_BasicExample PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
SET_TARGET_PROPERTIES(App_BasicExample PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
#################
# Standalone BasicExampleGui using OpenGL (but not the example browser)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/btgui
${BULLET_PHYSICS_SOURCE_DIR}/examples
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew
)
SET(AppBasicExampleGui_SRCS
BasicExample.cpp
${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc
../StandaloneMain/main_opengl_single_example.cpp
../ExampleBrowser/OpenGLGuiHelper.cpp
../ExampleBrowser/GL_ShapeDrawer.cpp
)
#this define maps StandaloneExampleCreateFunc to the right 'CreateFunc'
ADD_DEFINITIONS(-DB3_USE_STANDALONE_EXAMPLE)
LINK_LIBRARIES(
BulletDynamics BulletCollision LinearMath OpenGLWindow Bullet3Common ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
)
#some code to support OpenGL and Glew cross platform
IF (WIN32)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/btgui/OpenGLWindow/GlewWindows
)
ADD_DEFINITIONS(-DGLEW_STATIC)
ELSE(WIN32)
IF(APPLE)
find_library(COCOA NAMES Cocoa)
MESSAGE(${COCOA})
link_libraries(${COCOA})
ELSE(APPLE)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/btgui/OpenGLWindow/GlewWindows
)
ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1")
ADD_DEFINITIONS("-DGLEW_STATIC")
ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1")
LINK_LIBRARIES( X11 pthread dl Xext)
ENDIF(APPLE)
ENDIF(WIN32)
ADD_EXECUTABLE(AppBasicExampleGui
${AppBasicExampleGui_SRCS}
)
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES DEBUG_POSTFIX "_Debug")
SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES MINSIZEREL_POSTFIX "_MinsizeRel")
SET_TARGET_PROPERTIES(AppBasicExampleGui PROPERTIES RELWITHDEBINFO_POSTFIX "_RelWithDebugInfo")
ENDIF(INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)

View File

@@ -18,8 +18,13 @@ subject to the following restrictions:
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btHashMap.h"
int main(int argc, char* argv[])
@@ -39,3 +44,4 @@ int main(int argc, char* argv[])
return 0;
}

View File

@@ -20,3 +20,82 @@ files {
"**.h",
}
project "App_BasicExampleGui"
if _OPTIONS["ios"] then
kind "WindowedApp"
else
kind "ConsoleApp"
end
defines {"B3_USE_STANDALONE_EXAMPLE"}
includedirs {"../../src"}
links {
"BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common"
}
initOpenGL()
initGlew()
language "C++"
files {
"BasicExample.cpp",
"*.h",
"../StandaloneMain/main_opengl_single_example.cpp",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
}
if os.is("Linux") then initX11() end
if os.is("MacOSX") then
links{"Cocoa.framework"}
end
project "App_BasicExampleGuiWithSoftwareRenderer"
if _OPTIONS["ios"] then
kind "WindowedApp"
else
kind "ConsoleApp"
end
defines {"B3_USE_STANDALONE_EXAMPLE"}
includedirs {"../../src"}
links {
"BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common"
}
initOpenGL()
initGlew()
language "C++"
files {
"BasicExample.cpp",
"*.h",
"../StandaloneMain/main_sw_tinyrenderer_single_example.cpp",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
"../TinyRenderer/tgaimage.cpp",
"../TinyRenderer/our_gl.cpp",
"../TinyRenderer/TinyRenderer.cpp",
"../Utils/b3ResourcePath.cpp"
}
if os.is("Linux") then initX11() end
if os.is("MacOSX") then
links{"Cocoa.framework"}
end

View File

@@ -1,5 +1,7 @@
SUBDIRS( HelloWorld BasicDemo )
IF(BUILD_BULLET3)
SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow)
SUBDIRS( ExampleBrowser ThirdPartyLibs/Gwen OpenGLWindow )
ENDIF()
IF(BUILD_PYBULLET)
SUBDIRS(pybullet)
ENDIF(BUILD_PYBULLET)

View File

@@ -48,6 +48,17 @@ public:
};
CommonExampleInterface* StandaloneExampleCreateFunc(CommonExampleOptions& options);
#ifdef B3_USE_STANDALONE_EXAMPLE
#define B3_STANDALONE_EXAMPLE(ExampleFunc) CommonExampleInterface* StandaloneExampleCreateFunc(CommonExampleOptions& options)\
{\
return ExampleFunc(options);\
}
#else//B3_USE_STANDALONE_EXAMPLE
#define B3_STANDALONE_EXAMPLE(ExampleFunc)
#endif //B3_USE_STANDALONE_EXAMPLE
#endif //COMMON_EXAMPLE_INTERFACE_H

View File

@@ -43,7 +43,11 @@ struct CommonRenderInterface
virtual void drawPoint(const double* position, const double color[4], double pointDrawSize)=0;
virtual int registerShape(const float* vertices, int numvertices, const int* indices, int numIndices,int primitiveType=B3_GL_TRIANGLES, int textureIndex=-1)=0;
virtual void updateShape(int shapeIndex, const float* vertices)=0;
virtual int registerTexture(const unsigned char* texels, int width, int height)=0;
virtual void updateTexture(int textureIndex, const unsigned char* texels)=0;
virtual void activateTexture(int textureIndex)=0;
virtual void writeSingleInstanceTransformToCPU(const float* position, const float* orientation, int srcIndex)=0;
virtual void writeSingleInstanceTransformToCPU(const double* position, const double* orientation, int srcIndex)=0;
virtual void writeSingleInstanceColorToCPU(float* color, int srcIndex)=0;

View File

@@ -120,6 +120,8 @@ class CommonWindowInterface
virtual float getRetinaScale() const =0;
virtual void setAllowRetina(bool allow) =0;
virtual int getWidth() const = 0;
virtual int getHeight() const = 0;
virtual int fileOpenDialog(char* fileName, int maxFileNameLength) = 0;

View File

@@ -1,21 +1,27 @@
INCLUDE_DIRECTORIES(
.
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
)
FILE(GLOB ExampleBrowser_SRCS "*" "GwenGUISupport/*" )
FILE(GLOB ExampleBrowser_HDRS "*" "GwenGUISupport/*" )
FILE(GLOB GwenGUISupport_SRCS "GwenGUISupport/*" )
FILE(GLOB GwenGUISupport_HDRS "GwenGUISupport/*" )
SET(ExtendedTutorialsSources
../ExtendedTutorials/SimpleBox.cpp
../ExtendedTutorials/MultipleBoxes.cpp
../ExtendedTutorials/SimpleJoint.cpp
../ExtendedTutorials/SimpleCloth.cpp
../ExtendedTutorials/Chain.cpp
../ExtendedTutorials/Bridge.cpp
../ExtendedTutorials/RigidBodyFromObj.cpp
)
SET(App_ExampleBrowser_SRCS
main.cpp
ExampleEntries.cpp
ExampleEntries.h
SET(BulletExampleBrowser_SRCS
OpenGLExampleBrowser.cpp
OpenGLGuiHelper.cpp
InProcessExampleBrowser.cpp
GL_ShapeDrawer.cpp
../SharedMemory/PhysicsServer.cpp
../SharedMemory/PhysicsClientSharedMemory.cpp
../SharedMemory/PhysicsClient.cpp
@@ -97,8 +103,10 @@ SET(App_ExampleBrowser_SRCS
../../Extras/Serialize/BulletWorldImporter/btWorldImporter.cpp
../../Extras/Serialize/BulletWorldImporter/btBulletWorldImporter.cpp
../../Extras/Serialize/BulletFileLoader/bChunk.cpp ../../Extras/Serialize/BulletFileLoader/bFile.cpp
../../Extras/Serialize/BulletFileLoader/bDNA.cpp ../../Extras/Serialize/BulletFileLoader/btBulletFile.cpp
../../Extras/Serialize/BulletFileLoader/bChunk.cpp
../../Extras/Serialize/BulletFileLoader/bFile.cpp
../../Extras/Serialize/BulletFileLoader/bDNA.cpp
../../Extras/Serialize/BulletFileLoader/btBulletFile.cpp
../Importers/ImportBsp/BspLoader.h
../Importers/ImportBsp/ImportBspExample.h
@@ -124,6 +132,7 @@ SET(App_ExampleBrowser_SRCS
../Importers/ImportObjDemo/LoadMeshFromObj.cpp
../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp
../Importers/ImportSTLDemo/ImportSTLSetup.cpp
../Importers/ImportSDFDemo/ImportSDFSetup.cpp
../Importers/ImportURDFDemo/ImportURDFSetup.cpp
../Importers/ImportURDFDemo/URDF2Bullet.cpp
../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp
@@ -168,42 +177,82 @@ SET(App_ExampleBrowser_SRCS
../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp
../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp
../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/pose.cpp
../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/model.cpp
../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/link.cpp
../ThirdPartyLibs/urdf/urdfdom/urdf_parser/src/joint.cpp
../ThirdPartyLibs/urdf/urdfdom/urdf_parser/include/urdf_parser/urdf_parser.h
../ThirdPartyLibs/urdf/urdfdom_headers/urdf_exception/include/urdf_exception/exception.h
../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/pose.h
../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/model.h
../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/link.h
../ThirdPartyLibs/urdf/urdfdom_headers/urdf_model/include/urdf_model/joint.h
../ThirdPartyLibs/tinyxml/tinystr.cpp
../ThirdPartyLibs/tinyxml/tinyxml.cpp
../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp
../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp
../ThirdPartyLibs/urdf/boost_replacement/lexical_cast.h
../ThirdPartyLibs/urdf/boost_replacement/shared_ptr.h
../ThirdPartyLibs/urdf/boost_replacement/printf_console.cpp
../ThirdPartyLibs/urdf/boost_replacement/printf_console.h
../ThirdPartyLibs/urdf/boost_replacement/string_split.cpp
../ThirdPartyLibs/urdf/boost_replacement/string_split.h
../Utils/b3Clock.cpp
../Utils/b3Clock.h
../Utils/b3ResourcePath.cpp
../Utils/b3ResourcePath.h
${ExampleBrowser_SRCS}
${ExampleBrowser_HDRS}
${GwenGUISupport_SRCS}
${GwenGUISupport_HDRS}
${ExtendedTutorialsSources}
${BULLET_PHYSICS_SOURCE_DIR}/build3/bullet.rc
)
IF (WIN32)
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew
)
ADD_DEFINITIONS(-DGLEW_STATIC)
ELSE(WIN32)
IF(APPLE)
find_library(COCOA NAMES Cocoa)
ELSE(APPLE)
ADD_DEFINITIONS("-DGLEW_INIT_OPENGL11_FUNCTIONS=1")
ADD_DEFINITIONS("-DGLEW_STATIC")
ADD_DEFINITIONS("-DGLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS=1")
INCLUDE_DIRECTORIES( ${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew )
ENDIF(APPLE)
ENDIF(WIN32)
ADD_LIBRARY(BulletExampleBrowserLib ${BulletExampleBrowser_SRCS} )
SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(BulletExampleBrowserLib PROPERTIES SOVERSION ${BULLET_VERSION})
IF (BUILD_SHARED_LIBS)
IF (WIN32)
TARGET_LINK_LIBRARIES(
BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils
BulletInverseDynamics LinearMath OpenGLWindow gwen
${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
)
ELSE(WIN32)
IF(APPLE)
TARGET_LINK_LIBRARIES(
BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils
BulletInverseDynamics LinearMath OpenGLWindow gwen
${COCOA} ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
)
ELSE(APPLE)
TARGET_LINK_LIBRARIES(
BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils
BulletInverseDynamics LinearMath OpenGLWindow gwen
pthread dl
)
ENDIF(APPLE)
ENDIF(WIN32)
ENDIF(BUILD_SHARED_LIBS)
####################
#
# Bullet Example Browser main app
#
####################
INCLUDE_DIRECTORIES(
.
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
)
LINK_LIBRARIES(
Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen
BulletExampleBrowserLib Bullet3Common BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen
)
IF (WIN32)
SET(App_ExampleBrowser_SRCS ${App_ExampleBrowser_SRCS} )
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs/Glew
)
@@ -229,9 +278,19 @@ ENDIF(WIN32)
ADD_EXECUTABLE(App_ExampleBrowser
${App_ExampleBrowser_SRCS}
main.cpp
ExampleEntries.cpp
ExampleEntries.h
)
FILE( MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/data" )
ADD_CUSTOM_COMMAND(
TARGET App_ExampleBrowser
POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy_directory ${BULLET_PHYSICS_SOURCE_DIR}/data ${PROJECT_BINARY_DIR}/data
)
IF (INTERNAL_ADD_POSTFIX_EXECUTABLE_NAMES)
SET_TARGET_PROPERTIES(App_ExampleBrowser PROPERTIES DEBUG_POSTFIX "_Debug")

View File

@@ -9,13 +9,12 @@
#include "../BasicDemo/BasicExample.h"
#include "../Planar2D/Planar2D.h"
#include "../Benchmarks/BenchmarkDemo.h"
#ifdef ENABLE_URDF_OBJ
#include "../Importers/ImportObjDemo/ImportObjExample.h"
#endif
#include "../Importers/ImportBsp/ImportBspExample.h"
#include "../Importers/ImportColladaDemo/ImportColladaSetup.h"
#include "../Importers/ImportSTLDemo/ImportSTLSetup.h"
#include "../Importers/ImportURDFDemo/ImportURDFSetup.h"
#include "../Importers/ImportSDFDemo/ImportSDFSetup.h"
#include "../Collision/CollisionTutorialBullet2.h"
#include "../GyroscopicDemo/GyroscopicSetup.h"
#include "../Constraints/Dof6Spring2Setup.h"
@@ -56,7 +55,14 @@
#endif
#endif //B3_USE_CLEW
//Extended Tutorial Includes Added by Mobeen
#include "../ExtendedTutorials/SimpleBox.h"
#include "../ExtendedTutorials/MultipleBoxes.h"
#include "../ExtendedTutorials/SimpleJoint.h"
#include "../ExtendedTutorials/SimpleCloth.h"
#include "../ExtendedTutorials/Chain.h"
#include "../ExtendedTutorials/Bridge.h"
#include "../ExtendedTutorials/RigidBodyFromObj.h"
struct ExampleEntry
{
@@ -81,12 +87,11 @@ struct ExampleEntry
static ExampleEntry gDefaultExamples[]=
{
ExampleEntry(0,"API"),
ExampleEntry(1,"Basic Example","Create some rigid bodies using box collision shapes. This is a good example to familiarize with the basic initialization of Bullet. The Basic Example can also be compiled without graphical user interface, as a console application. Press W for wireframe, A to show AABBs, I to suspend/restart physics simulation. Press D to toggle auto-deactivation of the simulation. ", BasicExampleCreateFunc),
ExampleEntry(1,"Rolling Friction", "Damping is often not good enough to keep rounded objects from rolling down a sloped surface. Instead, you can set the rolling friction of a rigid body. Generally it is best to leave the rolling friction to zero, to avoid artifacts.", RollingFrictionCreateFunc),
ExampleEntry(1,"Constraints","Show the use of the various constraints in Bullet. Press the L key to visualize the constraint limits. Press the C key to visualize the constraint frames.",
@@ -122,7 +127,6 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(1,"Inverse Dynamics URDF", "Create a btMultiBody from URDF. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_LOAD_URDF),
ExampleEntry(1,"Inverse Dynamics Prog", "Create a btMultiBody programatically. Create an inverse MultiBodyTree model from that. Use either decoupled PD control or computed torque control using the inverse model to track joint position targets", InverseDynamicsExampleCreateFunc,BT_ID_PROGRAMMATICALLY),
ExampleEntry(0,"Tutorial"),
ExampleEntry(1,"Constant Velocity","Free moving rigid body, without external or constraint forces", TutorialCreateFunc,TUT_VELOCITY),
ExampleEntry(1,"Gravity Acceleration","Motion of a free falling rigid body under constant gravitational acceleration", TutorialCreateFunc,TUT_ACCELERATION),
@@ -194,9 +198,11 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(0,"Importers"),
ExampleEntry(1,"Import .bullet", "Load a binary .bullet file. The serialization mechanism can deal with versioning, differences in endianess, 32 and 64bit, double/single precision. It is easy to save a .bullet file, see the examples/Importers/ImportBullet/SerializeDemo.cpp for a code example how to export a .bullet file.", SerializeBulletCreateFunc),
#ifdef ENABLE_URDF_OBJ
ExampleEntry(1,"Wavefront Obj", "Import a Wavefront .obj file", ImportObjCreateFunc, 0),
#endif
ExampleEntry(1,"Obj2RigidBody (Show Obj)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body. We can use the original .obj mesh data to visualize the rigid body. In 'debug' wireframe mode (press 'w' to toggle) we still see the convex hull data.", ET_RigidBodyFromObjCreateFunc),
ExampleEntry(1,"Obj2RigidBody (Show Hull)", "Load a triangle mesh from Wavefront .obj and turn it in a convex hull collision shape, connected to a rigid body", ET_RigidBodyFromObjCreateFunc,ObjUseConvexHullForRendering),
ExampleEntry(1,"Obj2RigidBody Optimize", "Load a triangle mesh from Wavefront .obj, remove the vertices that are not on the convex hull", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj),
ExampleEntry(1,"Quake BSP", "Import a Quake .bsp file", ImportBspCreateFunc, 0),
ExampleEntry(1,"COLLADA dae", "Import the geometric mesh data from a COLLADA file. This is used as part of the URDF importer. This loader can also be used to import collision geometry in general. ",
ImportColladaCreateFunc, 0),
@@ -204,6 +210,7 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(1,"URDF (RigidBody)", "Import a URDF file, and create rigid bodies (btRigidBody) connected by constraints.", ImportURDFCreateFunc, 0),
ExampleEntry(1,"URDF (MultiBody)", "Import a URDF file and create a single multibody (btMultiBody) with tree hierarchy of links (mobilizers).",
ImportURDFCreateFunc, 1),
ExampleEntry(1,"SDF (MultiBody)", "Import an SDF file, create multiple multibodies etc", ImportSDFCreateFunc),
ExampleEntry(0,"Vehicles"),
ExampleEntry(1,"Hinge2 Vehicle", "A rigid body chassis with 4 rigid body wheels attached by a btHinge2Constraint",Hinge2VehicleCreateFunc),
@@ -220,13 +227,6 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(0,"Experiments"),
// ExampleEntry(1,"Robot Control (Velocity)", "Perform some robot control tasks, using physics server and client that communicate over shared memory",
// RobotControlExampleCreateFunc,ROBOT_VELOCITY_CONTROL),
// ExampleEntry(1,"Robot Control (PD)", "Perform some robot control tasks, using physics server and client that communicate over shared memory",
// RobotControlExampleCreateFunc,ROBOT_PD_CONTROL),
// ExampleEntry(1,"Robot Joint Feedback", "Apply some small ping-pong target velocity jitter, and read the joint reaction forces, using physics server and client that communicate over shared memory.",
// RobotControlExampleCreateFunc,ROBOT_PING_PONG_JOINT_FEEDBACK),
ExampleEntry(1,"Physics Server", "Create a physics server that communicates with a physics client over shared memory",
PhysicsServerCreateFunc),
ExampleEntry(1,"Physics Server (Logging)", "Create a physics server that communicates with a physics client over shared memory. It will log all commands to a file.",
@@ -254,7 +254,21 @@ static ExampleEntry gDefaultExamples[]=
ExampleEntry(0,"Rendering"),
ExampleEntry(1,"Instanced Rendering", "Simple example of fast instanced rendering, only active when using OpenGL3+.",RenderInstancingCreateFunc),
ExampleEntry(1,"CoordinateSystemDemo","Show the axis and positive rotation direction around the axis.", CoordinateSystemCreateFunc),
ExampleEntry(1,"Time Series", "Render some value(s) in a 2D graph window, shifting to the left", TimeSeriesCreateFunc)
ExampleEntry(1,"Time Series", "Render some value(s) in a 2D graph window, shifting to the left", TimeSeriesCreateFunc),
//Extended Tutorials Added by Mobeen
ExampleEntry(0,"Extended Tutorials"),
ExampleEntry(1,"Simple Box", "Simplest possible demo creating a single box rigid body that falls under gravity", ET_SimpleBoxCreateFunc),
ExampleEntry(1,"Multiple Boxes", "Adding multiple box rigid bodies that fall under gravity", ET_MultipleBoxesCreateFunc),
ExampleEntry(1,"Simple Joint", "Creating a single distance constraint between two box rigid bodies", ET_SimpleJointCreateFunc),
ExampleEntry(1,"Simple Cloth", "Creating a simple piece of cloth", ET_SimpleClothCreateFunc),
ExampleEntry(1,"Simple Chain", "Creating a simple chain using a pair of point2point/distance constraints. You may click and drag any box to see the chain respond.", ET_ChainCreateFunc),
ExampleEntry(1,"Simple Bridge", "Creating a simple bridge using a pair of point2point/distance constraints. You may click and drag any plank to see the bridge respond.", ET_BridgeCreateFunc),
//todo: create a category/tutorial about advanced topics, such as optimizations, using different collision detection algorithm, different constraint solvers etc.
//ExampleEntry(0,"Advanced"),
//ExampleEntry(1,"Obj2RigidBody Add Features", "Load a triangle mesh from Wavefront .obj and create polyhedral features to perform the separating axis test (instead of GJK/MPR). It is best to combine optimization and polyhedral feature generation.", ET_RigidBodyFromObjCreateFunc,OptimizeConvexObj+ComputePolyhedralFeatures),
};
@@ -278,17 +292,17 @@ struct ExampleEntriesInternalData
btAlignedObjectArray<ExampleEntry> m_allExamples;
};
ExampleEntries::ExampleEntries()
ExampleEntriesAll::ExampleEntriesAll()
{
m_data = new ExampleEntriesInternalData;
}
ExampleEntries::~ExampleEntries()
ExampleEntriesAll::~ExampleEntriesAll()
{
delete m_data;
}
void ExampleEntries::initOpenCLExampleEntries()
void ExampleEntriesAll::initOpenCLExampleEntries()
{
#ifdef B3_USE_CLEW
#ifndef NO_OPENGL3
@@ -301,7 +315,7 @@ void ExampleEntries::initOpenCLExampleEntries()
#endif //B3_USE_CLEW
}
void ExampleEntries::initExampleEntries()
void ExampleEntriesAll::initExampleEntries()
{
m_data->m_allExamples.clear();
@@ -334,33 +348,33 @@ void ExampleEntries::initExampleEntries()
}
void ExampleEntries::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option)
void ExampleEntriesAll::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option)
{
ExampleEntry e( menuLevel,name,description, createFunc, option);
gAdditionalRegisteredExamples.push_back(e);
}
int ExampleEntries::getNumRegisteredExamples()
int ExampleEntriesAll::getNumRegisteredExamples()
{
return m_data->m_allExamples.size();
}
CommonExampleInterface::CreateFunc* ExampleEntries::getExampleCreateFunc(int index)
CommonExampleInterface::CreateFunc* ExampleEntriesAll::getExampleCreateFunc(int index)
{
return m_data->m_allExamples[index].m_createFunc;
}
int ExampleEntries::getExampleOption(int index)
int ExampleEntriesAll::getExampleOption(int index)
{
return m_data->m_allExamples[index].m_option;
}
const char* ExampleEntries::getExampleName(int index)
const char* ExampleEntriesAll::getExampleName(int index)
{
return m_data->m_allExamples[index].m_name;
}
const char* ExampleEntries::getExampleDescription(int index)
const char* ExampleEntriesAll::getExampleDescription(int index)
{
return m_data->m_allExamples[index].m_description;
}

View File

@@ -6,32 +6,56 @@
class ExampleEntries
{
public:
virtual ~ExampleEntries() {}
virtual void initExampleEntries()=0;
virtual void initOpenCLExampleEntries()=0;
virtual int getNumRegisteredExamples()=0;
virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index)=0;
virtual const char* getExampleName(int index)=0;
virtual const char* getExampleDescription(int index)=0;
virtual int getExampleOption(int index)=0;
};
class ExampleEntriesAll : public ExampleEntries
{
struct ExampleEntriesInternalData* m_data;
public:
ExampleEntries();
virtual ~ExampleEntries();
ExampleEntriesAll();
virtual ~ExampleEntriesAll();
static void registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0);
void initExampleEntries();
virtual void initExampleEntries();
void initOpenCLExampleEntries();
virtual void initOpenCLExampleEntries();
int getNumRegisteredExamples();
virtual int getNumRegisteredExamples();
CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index);
virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index);
const char* getExampleName(int index);
virtual const char* getExampleName(int index);
const char* getExampleDescription(int index);
virtual const char* getExampleDescription(int index);
int getExampleOption(int index);
virtual int getExampleOption(int index);
};

View File

@@ -27,17 +27,19 @@ struct MyButtonEventHandler : public Gwen::Event::Handler
template<typename T>
struct MySliderEventHandler : public Gwen::Event::Handler
{
SliderParamChangedCallback m_callback;
Gwen::Controls::TextBox* m_label;
Gwen::Controls::Slider* m_pSlider;
char m_variableName[1024];
T* m_targetValue;
bool m_showValue;
MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target)
MySliderEventHandler(const char* varName, Gwen::Controls::TextBox* label, Gwen::Controls::Slider* pSlider,T* target,SliderParamChangedCallback callback)
:m_label(label),
m_pSlider(pSlider),
m_targetValue(target),
m_showValue(true)
m_showValue(true),
m_callback(callback)
{
memcpy(m_variableName,varName,strlen(varName)+1);
}
@@ -51,6 +53,11 @@ struct MySliderEventHandler : public Gwen::Event::Handler
T v = T(bla);
SetValue(v);
if (m_callback)
{
(*m_callback)(v);
}
}
void SetValue(T v)
@@ -219,7 +226,7 @@ void GwenParameterInterface::registerSliderFloatParameter(SliderParams& params)
pSlider->SetValue( *params.m_paramValuePointer);//dimensions[i] );
char labelName[1024];
sprintf(labelName,"%s",params.m_name);//axisNames[0]);
MySliderEventHandler<btScalar>* handler = new MySliderEventHandler<btScalar>(labelName,label,pSlider,params.m_paramValuePointer);
MySliderEventHandler<btScalar>* handler = new MySliderEventHandler<btScalar>(labelName,label,pSlider,params.m_paramValuePointer,params.m_callback);
handler->m_showValue = params.m_showValues;
m_paramInternalData->m_sliderEventHandlers.push_back(handler);

View File

@@ -13,7 +13,7 @@
#include "../Utils/b3Clock.h"
#include "ExampleEntries.h"
#include "Bullet3Common/b3Logging.h"
#include "Bullet3Common/b3Scalar.h"
#include "../SharedMemory/InProcessMemory.h"
void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory);
@@ -22,9 +22,19 @@ void* ExampleBrowserMemoryFunc();
#include <stdio.h>
//#include "BulletMultiThreaded/PlatformDefinitions.h"
#include "Bullet3Common/b3Logging.h"
#include "ExampleEntries.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "EmptyExample.h"
#include "../SharedMemory/PhysicsServerExample.h"
#include "../SharedMemory/PhysicsClientExample.h"
#ifndef _WIN32
#include "../MultiThreading/b3PosixThreadSupport.h"
static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads)
{
b3PosixThreadSupport::ThreadConstructionInfo constructionInfo("testThreads",
@@ -38,6 +48,7 @@ static b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThread
}
#elif defined( _WIN32)
#include "../MultiThreading/b3Win32ThreadSupport.h"
@@ -52,6 +63,138 @@ b3ThreadSupportInterface* createExampleBrowserThreadSupport(int numThreads)
class ExampleEntriesPhysicsServer : public ExampleEntries
{
struct ExampleEntriesInternalData2* m_data;
public:
ExampleEntriesPhysicsServer();
virtual ~ExampleEntriesPhysicsServer();
static void registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0);
virtual void initExampleEntries();
virtual void initOpenCLExampleEntries();
virtual int getNumRegisteredExamples();
virtual CommonExampleInterface::CreateFunc* getExampleCreateFunc(int index);
virtual const char* getExampleName(int index);
virtual const char* getExampleDescription(int index);
virtual int getExampleOption(int index);
};
struct ExampleEntryPhysicsServer
{
int m_menuLevel;
const char* m_name;
const char* m_description;
CommonExampleInterface::CreateFunc* m_createFunc;
int m_option;
ExampleEntryPhysicsServer(int menuLevel, const char* name)
:m_menuLevel(menuLevel), m_name(name), m_description(0), m_createFunc(0), m_option(0)
{
}
ExampleEntryPhysicsServer(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option=0)
:m_menuLevel(menuLevel), m_name(name), m_description(description), m_createFunc(createFunc), m_option(option)
{
}
};
struct ExampleEntriesInternalData2
{
btAlignedObjectArray<ExampleEntryPhysicsServer> m_allExamples;
};
static ExampleEntryPhysicsServer gDefaultExamplesPhysicsServer[]=
{
ExampleEntryPhysicsServer(0,"Robotics Control"),
ExampleEntryPhysicsServer(1,"Physics Server", "Create a physics server that communicates with a physics client over shared memory",
PhysicsServerCreateFunc),
ExampleEntryPhysicsServer(1,"Physics Server (Logging)", "Create a physics server that communicates with a physics client over shared memory. It will log all commands to a file.",
PhysicsServerCreateFunc,PHYSICS_SERVER_ENABLE_COMMAND_LOGGING),
ExampleEntryPhysicsServer(1,"Physics Server (Replay Log)", "Create a physics server that replay a command log from disk.",
PhysicsServerCreateFunc,PHYSICS_SERVER_REPLAY_FROM_COMMAND_LOG),
ExampleEntryPhysicsServer(1, "Physics Client", "Create a physics client that can communicate with a physics server over shared memory", PhysicsClientCreateFunc),
};
ExampleEntriesPhysicsServer::ExampleEntriesPhysicsServer()
{
m_data = new ExampleEntriesInternalData2;
}
ExampleEntriesPhysicsServer::~ExampleEntriesPhysicsServer()
{
delete m_data;
}
void ExampleEntriesPhysicsServer::initOpenCLExampleEntries()
{
}
void ExampleEntriesPhysicsServer::initExampleEntries()
{
m_data->m_allExamples.clear();
int numDefaultEntries = sizeof(gDefaultExamplesPhysicsServer)/sizeof(ExampleEntryPhysicsServer);
for (int i=0;i<numDefaultEntries;i++)
{
m_data->m_allExamples.push_back(gDefaultExamplesPhysicsServer[i]);
}
}
void ExampleEntriesPhysicsServer::registerExampleEntry(int menuLevel, const char* name,const char* description, CommonExampleInterface::CreateFunc* createFunc, int option)
{
}
int ExampleEntriesPhysicsServer::getNumRegisteredExamples()
{
return m_data->m_allExamples.size();
}
CommonExampleInterface::CreateFunc* ExampleEntriesPhysicsServer::getExampleCreateFunc(int index)
{
return m_data->m_allExamples[index].m_createFunc;
}
int ExampleEntriesPhysicsServer::getExampleOption(int index)
{
return m_data->m_allExamples[index].m_option;
}
const char* ExampleEntriesPhysicsServer::getExampleName(int index)
{
return m_data->m_allExamples[index].m_name;
}
const char* ExampleEntriesPhysicsServer::getExampleDescription(int index)
{
return m_data->m_allExamples[index].m_description;
}
struct ExampleBrowserArgs
{
ExampleBrowserArgs()
@@ -91,7 +234,7 @@ void ExampleBrowserThreadFunc(void* userPtr,void* lsMemory)
b3Clock clock;
ExampleEntries examples;
ExampleEntriesPhysicsServer examples;
examples.initExampleEntries();
DefaultBrowser* exampleBrowser = new DefaultBrowser(&examples);
@@ -147,6 +290,7 @@ struct btInProcessExampleBrowserInternalData
};
btInProcessExampleBrowserInternalData* btCreateInProcessExampleBrowser(int argc,char** argv2)
{
@@ -231,7 +375,7 @@ void btShutDownExampleBrowser(btInProcessExampleBrowserInternalData* data)
struct btInProcessExampleBrowserMainThreadInternalData
{
ExampleEntries m_examples;
ExampleEntriesPhysicsServer m_examples;
DefaultBrowser* m_exampleBrowser;
SharedMemoryInterface* m_sharedMem;
b3Clock m_clock;

View File

@@ -723,6 +723,8 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
char title[1024];
sprintf(title,"%s using OpenGL3+. %s", appTitle,optMode);
simpleApp = new SimpleOpenGL3App(title,width,height, gAllowRetina);
s_app = simpleApp;
}
#endif
@@ -735,6 +737,10 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
s_instancingRenderer = s_app->m_renderer;
s_window = s_app->m_window;
width = s_window->getWidth();
height = s_window->getHeight();
prevMouseMoveCallback = s_window->getMouseMoveCallback();
s_window->setMouseMoveCallback(MyMouseMoveCallback);
@@ -818,8 +824,6 @@ bool OpenGLExampleBrowser::init(int argc, char* argv[])
///add some demos to the gAllExamples
int numDemos = gAllExamples->getNumRegisteredExamples();
//char nodeText[1024];

View File

@@ -437,7 +437,7 @@ void OpenGLGuiHelper::createCollisionShapeGraphicsObject(btCollisionShape* colli
if (vertices.size() && indices.size())
{
int shapeId = m_data->m_glApp->m_renderer->registerShape(&vertices[0].xyzw[0],vertices.size(),&indices[0],indices.size());
int shapeId = registerGraphicsShape(&vertices[0].xyzw[0],vertices.size(),&indices[0],indices.size());
collisionShape->setUserIndex(shapeId);
}
@@ -501,6 +501,7 @@ CommonParameterInterface* OpenGLGuiHelper::getParameterInterface()
void OpenGLGuiHelper::setUpAxis(int axis)
{
m_data->m_glApp->setUpAxis(axis);
}
void OpenGLGuiHelper::resetCamera(float camDist, float pitch, float yaw, float camPosX,float camPosY, float camPosZ)

View File

@@ -22,7 +22,7 @@ int main(int argc, char* argv[])
b3Clock clock;
ExampleEntries examples;
ExampleEntriesAll examples;
examples.initExampleEntries();
ExampleBrowserInterface* exampleBrowser = new DefaultBrowser(&examples);

View File

@@ -46,6 +46,8 @@ project "App_BulletExampleBrowser"
files {"../LuaDemo/LuaPhysicsSetup.cpp"}
end
defines {"INCLUDE_CLOTH_DEMOS"}
files {
"main.cpp",
"ExampleEntries.cpp",
@@ -78,7 +80,6 @@ project "BulletExampleBrowserLib"
"../../src",
"../ThirdPartyLibs",
}
defines {"ENABLE_URDF_OBJ"}
if _OPTIONS["lua"] then
includedirs{"../ThirdPartyLibs/lua-5.2.3/src"}
@@ -135,6 +136,7 @@ project "BulletExampleBrowserLib"
"../InverseDynamics/InverseDynamicsExample.h",
"../BasicDemo/BasicExample.*",
"../Tutorial/*",
"../ExtendedTutorials/*",
"../Collision/*",
"../Collision/Internal/*",
"../Benchmarks/*",

View File

@@ -0,0 +1,150 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "Bridge.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
const int TOTAL_PLANKS = 10;
struct BridgeExample : public CommonRigidBodyBase
{
BridgeExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~BridgeExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void BridgeExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
//create two fixed boxes to hold the planks
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btScalar plankWidth = 0.4;
btScalar plankHeight = 0.2;
btScalar plankBreadth = 1;
btScalar plankOffset = plankWidth; //distance between two planks
btScalar bridgeWidth = plankWidth*TOTAL_PLANKS + plankOffset*(TOTAL_PLANKS-1);
btScalar bridgeHeight = 5;
btScalar halfBridgeWidth = bridgeWidth*0.5f;
btBoxShape* colShape = createBoxShape(btVector3(plankWidth,plankHeight,plankBreadth));
m_collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
//create a set of boxes to represent bridge
btAlignedObjectArray<btRigidBody*> boxes;
int lastBoxIndex = TOTAL_PLANKS-1;
for(int i=0;i<TOTAL_PLANKS;++i) {
float t = float(i)/lastBoxIndex;
t = -(t*2-1.0f) * halfBridgeWidth;
startTransform.setOrigin(btVector3(
btScalar(t),
bridgeHeight,
btScalar(0)
)
);
boxes.push_back(createRigidBody((i==0 || i==lastBoxIndex)?0:mass,startTransform,colShape));
}
//add N-1 spring constraints
for(int i=0;i<TOTAL_PLANKS-1;++i) {
btRigidBody* b1 = boxes[i];
btRigidBody* b2 = boxes[i+1];
btPoint2PointConstraint* leftSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(-0.5,0,-0.5), btVector3(0.5,0,-0.5));
m_dynamicsWorld->addConstraint(leftSpring);
btPoint2PointConstraint* rightSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(-0.5,0,0.5), btVector3(0.5,0,0.5));
m_dynamicsWorld->addConstraint(rightSpring);
}
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void BridgeExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_BridgeCreateFunc(CommonExampleOptions& options)
{
return new BridgeExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_BRIDGE_EXAMPLE_H
#define ET_BRIDGE_EXAMPLE_H
class CommonExampleInterface* ET_BridgeCreateFunc(struct CommonExampleOptions& options);
#endif //ET_BRIDGE_EXAMPLE_H

View File

@@ -0,0 +1,137 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "Chain.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
const int TOTAL_BOXES = 10;
struct ChainExample : public CommonRigidBodyBase
{
ChainExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~ChainExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void ChainExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btBoxShape* colShape = createBoxShape(btVector3(1,1,0.25));
m_collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
btAlignedObjectArray<btRigidBody*> boxes;
int lastBoxIndex = TOTAL_BOXES-1;
for(int i=0;i<TOTAL_BOXES;++i) {
startTransform.setOrigin(btVector3(
btScalar(0),
btScalar(5+i*2),
btScalar(0)
)
);
boxes.push_back(createRigidBody((i==lastBoxIndex)?0:mass,startTransform,colShape));
}
//add N-1 spring constraints
for(int i=0;i<TOTAL_BOXES-1;++i) {
btRigidBody* b1 = boxes[i];
btRigidBody* b2 = boxes[i+1];
btPoint2PointConstraint* leftSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(-0.5,1,0), btVector3(-0.5,-1,0));
m_dynamicsWorld->addConstraint(leftSpring);
btPoint2PointConstraint* rightSpring = new btPoint2PointConstraint(*b1, *b2, btVector3(0.5,1,0), btVector3(0.5,-1,0));
m_dynamicsWorld->addConstraint(rightSpring);
}
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void ChainExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_ChainCreateFunc(CommonExampleOptions& options)
{
return new ChainExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_CHAIN_EXAMPLE_H
#define ET_CHAIN_EXAMPLE_H
class CommonExampleInterface* ET_ChainCreateFunc(struct CommonExampleOptions& options);
#endif //ET_CHAIN_EXAMPLE_H

View File

@@ -0,0 +1,120 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "MultipleBoxes.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
const int TOTAL_BOXES = 10;
struct MultipleBoxesExample : public CommonRigidBodyBase
{
MultipleBoxesExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~MultipleBoxesExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void MultipleBoxesExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btBoxShape* colShape = createBoxShape(btVector3(1,1,1));
m_collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
for(int i=0;i<TOTAL_BOXES;++i) {
startTransform.setOrigin(btVector3(
btScalar(0),
btScalar(20+i*2),
btScalar(0)));
createRigidBody(mass,startTransform,colShape);
}
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void MultipleBoxesExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_MultipleBoxesCreateFunc(CommonExampleOptions& options)
{
return new MultipleBoxesExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_MULTIPLE_BOXES_EXAMPLE_H
#define ET_MULTIPLE_BOXES_EXAMPLE_H
class CommonExampleInterface* ET_MultipleBoxesCreateFunc(struct CommonExampleOptions& options);
#endif //ET_MULTIPLE_BOXES_EXAMPLE_H

View File

@@ -0,0 +1,159 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "RigidBodyFromObj.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
#include "../Utils/b3ResourcePath.h"
#include "Bullet3Common/b3FileUtils.h"
#include "../Importers/ImportObjDemo/LoadMeshFromObj.h"
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
struct RigidBodyFromObjExample : public CommonRigidBodyBase
{
int m_options;
RigidBodyFromObjExample(struct GUIHelperInterface* helper, int options)
:CommonRigidBodyBase(helper),
m_options(options)
{
}
virtual ~RigidBodyFromObjExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void RigidBodyFromObjExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
//if (m_dynamicsWorld->getDebugDrawer())
// m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
//load our obj mesh
const char* fileName = "teddy.obj";//sphere8.obj";//sponza_closed.obj";//sphere8.obj";
char relativeFileName[1024];
if (b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024))
{
char pathPrefix[1024];
b3FileUtils::extractPath(relativeFileName, pathPrefix, 1024);
}
GLInstanceGraphicsShape* glmesh = LoadMeshFromObj(relativeFileName, "");
printf("[INFO] Obj loaded: Extracted %d verticed from obj file [%s]\n", glmesh->m_numvertices, fileName);
const GLInstanceVertex& v = glmesh->m_vertices->at(0);
btConvexHullShape* shape = new btConvexHullShape((const btScalar*)(&(v.xyzw[0])), glmesh->m_numvertices, sizeof(GLInstanceVertex));
shape->setLocalScaling(btVector3(0.1,0.1,0.1));
if (m_options & OptimizeConvexObj)
{
shape->optimizeConvexHull();
}
if (m_options & ComputePolyhedralFeatures)
{
shape->initializePolyhedralFeatures();
}
//shape->setMargin(0.001);
m_collisionShapes.push_back(shape);
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
shape->calculateLocalInertia(mass,localInertia);
btVector3 position(0,20,0);
startTransform.setOrigin(position);
btRigidBody* body = createRigidBody(mass,startTransform,shape);
btVector3 color(1,1,1);
btVector3 scaling(0.1,0.1,0.1);
bool useConvexHullForRendering = ((m_options & ObjUseConvexHullForRendering)!=0);
if (!useConvexHullForRendering)
{
int shapeId = m_guiHelper->getRenderInterface()->registerShape(&glmesh->m_vertices->at(0).xyzw[0],
glmesh->m_numvertices,
&glmesh->m_indices->at(0),
glmesh->m_numIndices,
B3_GL_TRIANGLES,-1);
shape->setUserIndex(shapeId);
int renderInstance = m_guiHelper->getRenderInterface()->registerGraphicsInstance(shapeId,position,startTransform.getRotation(),color,scaling);
body->setUserIndex(renderInstance);
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void RigidBodyFromObjExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_RigidBodyFromObjCreateFunc(CommonExampleOptions& options)
{
return new RigidBodyFromObjExample(options.m_guiHelper,options.m_option);
}

View File

@@ -0,0 +1,28 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_RIGIDBODYFROMOBJ_EXAMPLE_H
#define ET_RIGIDBODYFROMOBJ_EXAMPLE_H
enum ObjToRigidBodyOptionsEnum
{
ObjUseConvexHullForRendering=1,
OptimizeConvexObj=2,
ComputePolyhedralFeatures=4,
};
class CommonExampleInterface* ET_RigidBodyFromObjCreateFunc(struct CommonExampleOptions& options);
#endif //ET_RIGIDBODYFROMOBJ_EXAMPLE_H

View File

@@ -0,0 +1,118 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SimpleBox.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
struct SimpleBoxExample : public CommonRigidBodyBase
{
SimpleBoxExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~SimpleBoxExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void SimpleBoxExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btBoxShape* colShape = createBoxShape(btVector3(1,1,1));
m_collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(
btScalar(0),
btScalar(20),
btScalar(0)));
createRigidBody(mass,startTransform,colShape);
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void SimpleBoxExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_SimpleBoxCreateFunc(CommonExampleOptions& options)
{
return new SimpleBoxExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_SIMPLE_BOX_EXAMPLE_H
#define ET_SIMPLE_BOX_EXAMPLE_H
class CommonExampleInterface* ET_SimpleBoxCreateFunc(struct CommonExampleOptions& options);
#endif //ET_SIMPLE_BOX_EXAMPLE_H

View File

@@ -0,0 +1,162 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SimpleCloth.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
#include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
#include "BulletSoftBody/btSoftBodyHelpers.h"
#include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h"
struct SimpleClothExample : public CommonRigidBodyBase
{
SimpleClothExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~SimpleClothExample(){}
virtual void initPhysics();
virtual void renderScene();
void createEmptyDynamicsWorld()
{
m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();
m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
m_broadphase = new btDbvtBroadphase();
m_solver = new btSequentialImpulseConstraintSolver;
m_dynamicsWorld = new btSoftRigidDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);
m_dynamicsWorld->setGravity(btVector3(0, -10, 0));
softBodyWorldInfo.m_broadphase = m_broadphase;
softBodyWorldInfo.m_dispatcher = m_dispatcher;
softBodyWorldInfo.m_gravity = m_dynamicsWorld->getGravity();
softBodyWorldInfo.m_sparsesdf.Initialize();
}
virtual btSoftRigidDynamicsWorld* getSoftDynamicsWorld()
{
///just make it a btSoftRigidDynamicsWorld please
///or we will add type checking
return (btSoftRigidDynamicsWorld*) m_dynamicsWorld;
}
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
void createSoftBody(const btScalar size, const int num_x, const int num_z, const int fixed=1+2);
btSoftBodyWorldInfo softBodyWorldInfo;
};
void SimpleClothExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
{
const btScalar s=4; //size of cloth patch
const int NUM_X=31; //vertices on X axis
const int NUM_Z=31; //vertices on Z axis
createSoftBody(s,NUM_X, NUM_Z);
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void SimpleClothExample::createSoftBody(const btScalar s,
const int numX,
const int numY,
const int fixed) {
btSoftBody* cloth=btSoftBodyHelpers::CreatePatch(softBodyWorldInfo,
btVector3(-s/2,s+1,0),
btVector3(+s/2,s+1,0),
btVector3(-s/2,s+1,+s),
btVector3(+s/2,s+1,+s),
numX,numY,
fixed,true);
cloth->getCollisionShape()->setMargin(0.001f);
cloth->generateBendingConstraints(2,cloth->appendMaterial());
cloth->setTotalMass(10);
//cloth->m_cfg.citerations = 10;
// cloth->m_cfg.diterations = 10;
cloth->m_cfg.piterations = 5;
cloth->m_cfg.kDP = 0.005f;
getSoftDynamicsWorld()->addSoftBody(cloth);
}
void SimpleClothExample::renderScene()
{
CommonRigidBodyBase::renderScene();
btSoftRigidDynamicsWorld* softWorld = getSoftDynamicsWorld();
for ( int i=0;i<softWorld->getSoftBodyArray().size();i++)
{
btSoftBody* psb=(btSoftBody*)softWorld->getSoftBodyArray()[i];
//if (softWorld->getDebugDrawer() && !(softWorld->getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
{
btSoftBodyHelpers::DrawFrame(psb,softWorld->getDebugDrawer());
btSoftBodyHelpers::Draw(psb,softWorld->getDebugDrawer(),softWorld->getDrawFlags());
}
}
}
CommonExampleInterface* ET_SimpleClothCreateFunc(CommonExampleOptions& options)
{
return new SimpleClothExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_SIMPLE_CLOTH_EXAMPLE_H
#define ET_SIMPLE_CLOTH_EXAMPLE_H
class CommonExampleInterface* ET_SimpleClothCreateFunc(struct CommonExampleOptions& options);
#endif //ET_SIMPLE_CLOTH_EXAMPLE_H

View File

@@ -0,0 +1,133 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SimpleJoint.h"
#include "btBulletDynamicsCommon.h"
#include "LinearMath/btVector3.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "../CommonInterfaces/CommonRigidBodyBase.h"
struct SimpleJointExample : public CommonRigidBodyBase
{
SimpleJointExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper)
{
}
virtual ~SimpleJointExample(){}
virtual void initPhysics();
virtual void renderScene();
void resetCamera()
{
float dist = 41;
float pitch = 52;
float yaw = 35;
float targetPos[3]={0,0.46,0};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
void SimpleJointExample::initPhysics()
{
m_guiHelper->setUpAxis(1);
createEmptyDynamicsWorld();
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
if (m_dynamicsWorld->getDebugDrawer())
m_dynamicsWorld->getDebugDrawer()->setDebugMode(btIDebugDraw::DBG_DrawWireframe+btIDebugDraw::DBG_DrawContactPoints);
///create a few basic rigid bodies
btBoxShape* groundShape = createBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
m_collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-50,0));
{
btScalar mass(0.);
createRigidBody(mass,groundTransform,groundShape, btVector4(0,0,1,1));
}
{
//create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
btBoxShape* colShape = createBoxShape(btVector3(1,1,1));
m_collisionShapes.push_back(colShape);
/// Create Dynamic Objects
btTransform startTransform;
startTransform.setIdentity();
btScalar mass(1.f);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
bool isDynamic = (mass != 0.f);
btVector3 localInertia(0,0,0);
if (isDynamic)
colShape->calculateLocalInertia(mass,localInertia);
startTransform.setOrigin(btVector3(
btScalar(0),
btScalar(10),
btScalar(0)));
btRigidBody* dynamicBox = createRigidBody(mass,startTransform,colShape);
//create a static rigid body
mass = 0;
startTransform.setOrigin(btVector3(
btScalar(0),
btScalar(20),
btScalar(0)));
btRigidBody* staticBox = createRigidBody(mass,startTransform,colShape);
//create a simple p2pjoint constraint
btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*dynamicBox, *staticBox, btVector3(0,3,0), btVector3(0,0,0));
p2p->m_setting.m_damping = 0.0625;
p2p->m_setting.m_impulseClamp = 0.95;
m_dynamicsWorld->addConstraint(p2p);
}
m_guiHelper->autogenerateGraphicsObjects(m_dynamicsWorld);
}
void SimpleJointExample::renderScene()
{
CommonRigidBodyBase::renderScene();
}
CommonExampleInterface* ET_SimpleJointCreateFunc(CommonExampleOptions& options)
{
return new SimpleJointExample(options.m_guiHelper);
}

View File

@@ -0,0 +1,22 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef ET_SIMPLE_JOINT_EXAMPLE_H
#define ET_SIMPLE_JOINT_EXAMPLE_H
class CommonExampleInterface* ET_SimpleJointCreateFunc(struct CommonExampleOptions& options);
#endif //ET_SIMPLE_JOINT_EXAMPLE_H

View File

@@ -44,20 +44,24 @@ int main(int argc, char** argv)
///-----initialization_end-----
///create a few basic rigid bodies
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
//keep track of the shapes, we release memory at exit.
//make sure to re-use collision shapes among rigid bodies whenever possible!
btAlignedObjectArray<btCollisionShape*> collisionShapes;
///create a few basic rigid bodies
//the ground is a cube of side 100 at position y = -56.
//the sphere will hit it at y = -6, with center at -5
{
btCollisionShape* groundShape = new btBoxShape(btVector3(btScalar(50.),btScalar(50.),btScalar(50.)));
collisionShapes.push_back(groundShape);
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0,-56,0));
{
btScalar mass(0.);
//rigidbody is dynamic if and only if mass is non zero, otherwise static
@@ -113,7 +117,7 @@ int main(int argc, char** argv)
///-----stepsimulation_start-----
for (i=0;i<100;i++)
for (i=0;i<150;i++)
{
dynamicsWorld->stepSimulation(1.f/60.f,10);
@@ -178,9 +182,5 @@ int main(int argc, char** argv)
//next line is optional: it will be cleared by the destructor when the array goes out of scope
collisionShapes.clear();
///-----cleanup_end-----
printf("Press a key to exit\n");
getchar();
}

View File

@@ -20,7 +20,7 @@ subject to the following restrictions:
#include <stdio.h> //fopen
#include "Bullet3Common/b3AlignedObjectArray.h"
#include <string>
#include "tinyxml/tinyxml.h"
#include "../../ThirdPartyLibs/tinyxml/tinyxml.h"
#include "Bullet3Common/b3FileUtils.h"
#include "LinearMath/btHashMap.h"

View File

@@ -21,7 +21,7 @@ subject to the following restrictions:
#include "LinearMath/btAlignedObjectArray.h"
#include "LinearMath/btTransform.h"
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "ColladaGraphicsInstance.h"

View File

@@ -101,7 +101,7 @@ void ImportObjSetup::initPhysics()
const char* filename = shape.material.diffuse_texname.c_str();
const unsigned char* image=0;
const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
const char* prefix[]={ pathPrefix,"./","./data/","../data/","../../data/","../../../data/","../../../../data/"};
int numprefix = sizeof(prefix)/sizeof(const char*);
for (int i=0;!image && i<numprefix;i++)

View File

@@ -1,6 +1,6 @@
#include "LoadMeshFromObj.h"
#include"Wavefront/tiny_obj_loader.h"
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
#include"../../ThirdPartyLibs/Wavefront/tiny_obj_loader.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
#include <stdio.h> //fopen
#include "Bullet3Common/b3AlignedObjectArray.h"
#include <string>

View File

@@ -1,12 +1,12 @@
#include "Wavefront2GLInstanceGraphicsShape.h"
#include "../OpenGLWindow/GLInstancingRenderer.h"
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "../../OpenGLWindow/GLInstancingRenderer.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "btBulletDynamicsCommon.h"
#include "../OpenGLWindow/SimpleOpenGL3App.h"
#include "../../OpenGLWindow/SimpleOpenGL3App.h"
#include "Wavefront2GLInstanceGraphicsShape.h"
#include "../OpenGLWindow/GLInstancingRenderer.h"
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "../../OpenGLWindow/GLInstancingRenderer.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes)
{

View File

@@ -1,7 +1,7 @@
#ifndef WAVEFRONT2GRAPHICS_H
#define WAVEFRONT2GRAPHICS_H
#include"Wavefront/tiny_obj_loader.h"
#include"../../ThirdPartyLibs/Wavefront/tiny_obj_loader.h"
#include <vector>
struct GLInstanceGraphicsShape* btgCreateGraphicsShapeFromWavefrontObj(std::vector<tinyobj::shape_t>& shapes);

View File

@@ -0,0 +1,302 @@
#include "ImportSDFSetup.h"
#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "Bullet3Common/b3FileUtils.h"
#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.h"
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
#include "../CommonInterfaces/CommonParameterInterface.h"
#include "../../Utils/b3ResourcePath.h"
#include "../ImportURDFDemo/BulletUrdfImporter.h"
#include "../ImportURDFDemo/URDF2Bullet.h"
//#include "urdf_samples.h"
#include "../CommonInterfaces/CommonMultiBodyBase.h"
#include "../ImportURDFDemo/MyMultiBodyCreator.h"
class ImportSDFSetup : public CommonMultiBodyBase
{
char m_fileName[1024];
struct ImportSDFInternalData* m_data;
bool m_useMultiBody;
//todo(erwincoumans) we need a name memory for each model
btAlignedObjectArray<std::string* > m_nameMemory;
public:
ImportSDFSetup(struct GUIHelperInterface* helper, int option, const char* fileName);
virtual ~ImportSDFSetup();
virtual void initPhysics();
virtual void stepSimulation(float deltaTime);
void setFileName(const char* urdfFileName);
virtual void resetCamera()
{
float dist = 3.5;
float pitch = -136;
float yaw = 28;
float targetPos[3]={0.47,0,-0.64};
m_guiHelper->resetCamera(dist,pitch,yaw,targetPos[0],targetPos[1],targetPos[2]);
}
};
static btAlignedObjectArray<std::string> gFileNameArray;
#define MAX_NUM_MOTORS 1024
struct ImportSDFInternalData
{
ImportSDFInternalData()
:m_numMotors(0)
{
for (int i=0;i<MAX_NUM_MOTORS;i++)
{
m_jointMotors[i] = 0;
m_generic6DofJointMotors[i] = 0;
}
}
btScalar m_motorTargetVelocities[MAX_NUM_MOTORS];
btMultiBodyJointMotor* m_jointMotors [MAX_NUM_MOTORS];
btGeneric6DofSpring2Constraint* m_generic6DofJointMotors [MAX_NUM_MOTORS];
int m_numMotors;
};
ImportSDFSetup::ImportSDFSetup(struct GUIHelperInterface* helper, int option, const char* fileName)
:CommonMultiBodyBase(helper)
{
m_data = new ImportSDFInternalData;
(void)option;
// if (option==1)
// {
m_useMultiBody = true;
//
// } else
// {
// m_useMultiBody = false;
// }
static int count = 0;
if (fileName)
{
setFileName(fileName);
} else
{
gFileNameArray.clear();
//load additional urdf file names from file
FILE* f = fopen("urdf_files.txt","r");
if (f)
{
int result;
//warning: we don't avoid string buffer overflow in this basic example in fscanf
char fileName[1024];
do
{
result = fscanf(f,"%s",fileName);
b3Printf("sdf_files.txt entry %s",fileName);
if (result==1)
{
gFileNameArray.push_back(fileName);
}
} while (result==1);
fclose(f);
}
if (gFileNameArray.size()==0)
{
gFileNameArray.push_back("two_cubes.sdf");
}
int numFileNames = gFileNameArray.size();
if (count>=numFileNames)
{
count=0;
}
sprintf(m_fileName,"%s",gFileNameArray[count++].c_str());
}
}
ImportSDFSetup::~ImportSDFSetup()
{
for (int i=0;i<m_nameMemory.size();i++)
{
delete m_nameMemory[i];
}
m_nameMemory.clear();
delete m_data;
}
static btVector4 colors[4] =
{
btVector4(1,0,0,1),
btVector4(0,1,0,1),
btVector4(0,1,1,1),
btVector4(1,1,0,1),
};
static btVector3 selectColor()
{
static int curColor = 0;
btVector4 color = colors[curColor];
curColor++;
curColor&=3;
return color;
}
void ImportSDFSetup::setFileName(const char* urdfFileName)
{
memcpy(m_fileName,urdfFileName,strlen(urdfFileName)+1);
}
void ImportSDFSetup::initPhysics()
{
int upAxis = 2;
m_guiHelper->setUpAxis(upAxis);
this->createEmptyDynamicsWorld();
//m_dynamicsWorld->getSolverInfo().m_numIterations = 100;
m_guiHelper->createPhysicsDebugDrawer(m_dynamicsWorld);
m_dynamicsWorld->getDebugDrawer()->setDebugMode(
btIDebugDraw::DBG_DrawConstraints
+btIDebugDraw::DBG_DrawContactPoints
+btIDebugDraw::DBG_DrawAabb
);//+btIDebugDraw::DBG_DrawConstraintLimits);
btVector3 gravity(0,0,0);
gravity[upAxis]=-9.8;
m_dynamicsWorld->setGravity(gravity);
BulletURDFImporter u2b(m_guiHelper);
bool loadOk = u2b.loadSDF(m_fileName);
if (loadOk)
{
//printTree(u2b,u2b.getRootLinkIndex());
//u2b.printTree();
btTransform identityTrans;
identityTrans.setIdentity();
for (int m =0; m<u2b.getNumModels();m++)
{
u2b.activateModel(m);
btMultiBody* mb = 0;
//todo: move these internal API called inside the 'ConvertURDF2Bullet' call, hidden from the user
int rootLinkIndex = u2b.getRootLinkIndex();
b3Printf("urdf root link index = %d\n",rootLinkIndex);
MyMultiBodyCreator creation(m_guiHelper);
ConvertURDF2Bullet(u2b,creation, identityTrans,m_dynamicsWorld,m_useMultiBody,u2b.getPathPrefix());
mb = creation.getBulletMultiBody();
}
for (int i=0;i<m_dynamicsWorld->getNumMultiBodyConstraints();i++)
{
m_dynamicsWorld->getMultiBodyConstraint(i)->finalizeMultiDof();
}
bool createGround=true;
if (createGround)
{
btVector3 groundHalfExtents(20,20,20);
groundHalfExtents[upAxis]=1.f;
btBoxShape* box = new btBoxShape(groundHalfExtents);
box->initializePolyhedralFeatures();
m_guiHelper->createCollisionShapeGraphicsObject(box);
btTransform start; start.setIdentity();
btVector3 groundOrigin(0,0,0);
groundOrigin[upAxis]=-2.5;
start.setOrigin(groundOrigin);
btRigidBody* body = createRigidBody(0,start,box);
//m_dynamicsWorld->removeRigidBody(body);
// m_dynamicsWorld->addRigidBody(body,2,1);
btVector3 color(0.5,0.5,0.5);
m_guiHelper->createRigidBodyGraphicsObject(body,color);
}
///this extra stepSimulation call makes sure that all the btMultibody transforms are properly propagates.
m_dynamicsWorld->stepSimulation(1. / 240., 0);// 1., 10, 1. / 240.);
}
}
void ImportSDFSetup::stepSimulation(float deltaTime)
{
if (m_dynamicsWorld)
{
for (int i=0;i<m_data->m_numMotors;i++)
{
if (m_data->m_jointMotors[i])
{
m_data->m_jointMotors[i]->setVelocityTarget(m_data->m_motorTargetVelocities[i]);
}
if (m_data->m_generic6DofJointMotors[i])
{
GenericConstraintUserInfo* jointInfo = (GenericConstraintUserInfo*)m_data->m_generic6DofJointMotors[i]->getUserConstraintPtr();
m_data->m_generic6DofJointMotors[i]->setTargetVelocity(jointInfo->m_jointAxisIndex,m_data->m_motorTargetVelocities[i]);
//jointInfo->
}
}
//the maximal coordinates/iterative MLCP solver requires a smallish timestep to converge
m_dynamicsWorld->stepSimulation(deltaTime,10,1./240.);
}
}
class CommonExampleInterface* ImportSDFCreateFunc(struct CommonExampleOptions& options)
{
return new ImportSDFSetup(options.m_guiHelper, options.m_option,options.m_fileName);
}

View File

@@ -0,0 +1,8 @@
#ifndef IMPORT_SDF_SETUP_H
#define IMPORT_SDF_SETUP_H
class CommonExampleInterface* ImportSDFCreateFunc(struct CommonExampleOptions& options);
#endif //IMPORT_SDF_SETUP_H

View File

@@ -2,7 +2,7 @@
#ifndef LOAD_MESH_FROM_STL_H
#define LOAD_MESH_FROM_STL_H
#include "../OpenGLWindow/GLInstanceGraphicsShape.h"
#include "../../OpenGLWindow/GLInstanceGraphicsShape.h"
#include <stdio.h> //fopen
#include "Bullet3Common/b3AlignedObjectArray.h"

View File

@@ -21,7 +21,7 @@ subject to the following restrictions:
#include "../ImportSTLDemo/LoadMeshFromSTL.h"
#include "../ImportColladaDemo/LoadMeshFromCollada.h"
#include "BulletCollision/CollisionShapes/btShapeHull.h"//to create a tesselation of a generic btConvexShape
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "../../CommonInterfaces/CommonGUIHelperInterface.h"
#include "Bullet3Common/b3FileUtils.h"
#include <string>
#include "../../Utils/b3ResourcePath.h"
@@ -133,11 +133,69 @@ bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase)
}
BulletErrorLogger loggie;
m_data->m_urdfParser.setParseSDF(false);
bool result = m_data->m_urdfParser.loadUrdf(xml_string.c_str(), &loggie, forceFixedBase);
return result;
}
int BulletURDFImporter::getNumModels() const
{
return m_data->m_urdfParser.getNumModels();
}
void BulletURDFImporter::activateModel(int modelIndex)
{
m_data->m_urdfParser.activateModel(modelIndex);
}
bool BulletURDFImporter::loadSDF(const char* fileName, bool forceFixedBase)
{
m_data->m_linkColors.clear();
//int argc=0;
char relativeFileName[1024];
b3FileUtils fu;
//bool fileFound = fu.findFile(fileName, relativeFileName, 1024);
bool fileFound = b3ResourcePath::findResourcePath(fileName,relativeFileName,1024);
std::string xml_string;
m_data->m_pathPrefix[0] = 0;
if (!fileFound){
std::cerr << "URDF file not found" << std::endl;
return false;
} else
{
int maxPathLen = 1024;
fu.extractPath(relativeFileName,m_data->m_pathPrefix,maxPathLen);
std::fstream xml_file(relativeFileName, std::fstream::in);
while ( xml_file.good() )
{
std::string line;
std::getline( xml_file, line);
xml_string += (line + "\n");
}
xml_file.close();
}
BulletErrorLogger loggie;
//todo: quick test to see if we can re-use the URDF parser for SDF or not
m_data->m_urdfParser.setParseSDF(true);
bool result = m_data->m_urdfParser.loadSDF(xml_string.c_str(), &loggie);
return result;
}
const char* BulletURDFImporter::getPathPrefix()
{
return m_data->m_pathPrefix;

View File

@@ -4,6 +4,7 @@
#include "URDFImporterInterface.h"
///BulletURDFImporter can deal with URDF and (soon) SDF files
class BulletURDFImporter : public URDFImporterInterface
{
@@ -18,6 +19,11 @@ public:
virtual bool loadURDF(const char* fileName, bool forceFixedBase = false);
//warning: some quick test to load SDF: we 'activate' a model, so we can re-use URDF code path
virtual bool loadSDF(const char* fileName, bool forceFixedBase = false);
virtual int getNumModels() const;
virtual void activateModel(int modelIndex);
const char* getPathPrefix();
void printTree(); //for debugging

View File

@@ -163,7 +163,7 @@ static btVector4 colors[4] =
};
btVector3 selectColor()
static btVector3 selectColor()
{
static int curColor = 0;

View File

@@ -1,6 +1,6 @@
#include "MyMultiBodyCreator.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "../../CommonInterfaces/CommonGUIHelperInterface.h"
#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"

View File

@@ -17,6 +17,8 @@ public:
virtual bool loadURDF(const char* fileName, bool forceFixedBase = false)=0;
virtual bool loadSDF(const char* fileName, bool forceFixedBase = false) { return false;}
virtual const char* getPathPrefix()=0;
///return >=0 for the root link index, -1 if there is no root link

View File

@@ -1,18 +1,33 @@
#include "UrdfParser.h"
#include "tinyxml/tinyxml.h"
#include "../../ThirdPartyLibs/tinyxml/tinyxml.h"
#include "urdfStringSplit.h"
#include "urdfLexicalCast.h"
UrdfParser::UrdfParser()
:m_parseSDF(false),
m_activeSdfModel(-1)
{
}
UrdfParser::~UrdfParser()
{
cleanModel(&m_urdf2Model);
for (int i=0;i<m_model.m_materials.size();i++)
for (int i=0;i<m_tmpModels.size();i++)
{
UrdfMaterial** matPtr = m_model.m_materials.getAtIndex(i);
cleanModel(m_tmpModels[i]);
}
m_sdfModels.clear();
m_tmpModels.clear();
}
void UrdfParser::cleanModel(UrdfModel* model)
{
for (int i=0;i<model->m_materials.size();i++)
{
UrdfMaterial** matPtr = model->m_materials.getAtIndex(i);
if (matPtr)
{
UrdfMaterial* mat = *matPtr;
@@ -20,9 +35,9 @@ UrdfParser::~UrdfParser()
}
}
for (int i=0;i<m_model.m_links.size();i++)
for (int i=0;i<model->m_links.size();i++)
{
UrdfLink** linkPtr = m_model.m_links.getAtIndex(i);
UrdfLink** linkPtr = model->m_links.getAtIndex(i);
if (linkPtr)
{
UrdfLink* link = *linkPtr;
@@ -30,16 +45,15 @@ UrdfParser::~UrdfParser()
}
}
for (int i=0;i<m_model.m_joints.size();i++)
for (int i=0;i<model->m_joints.size();i++)
{
UrdfJoint** jointPtr = m_model.m_joints.getAtIndex(i);
UrdfJoint** jointPtr = model->m_joints.getAtIndex(i);
if (jointPtr)
{
UrdfJoint* joint = *jointPtr;
delete joint;
}
}
}
static bool parseVector4(btVector4& vec4, const std::string& vector_str)
@@ -192,6 +206,11 @@ bool UrdfParser::parseInertia(UrdfInertia& inertia, TiXmlElement* config, ErrorL
logger->reportError("Inertial element must have a mass element");
return false;
}
if (m_parseSDF)
{
inertia.m_mass = urdfLexicalCast<double>(mass_xml->GetText());
} else
{
if (!mass_xml->Attribute("value"))
{
logger->reportError("Inertial: mass element must have value attribute");
@@ -199,7 +218,7 @@ bool UrdfParser::parseInertia(UrdfInertia& inertia, TiXmlElement* config, ErrorL
}
inertia.m_mass = urdfLexicalCast<double>(mass_xml->Attribute("value"));
}
TiXmlElement *inertia_xml = config->FirstChildElement("inertia");
if (!inertia_xml)
@@ -207,6 +226,29 @@ bool UrdfParser::parseInertia(UrdfInertia& inertia, TiXmlElement* config, ErrorL
logger->reportError("Inertial element must have inertia element");
return false;
}
if (m_parseSDF)
{
TiXmlElement* ixx = inertia_xml->FirstChildElement("ixx");
TiXmlElement* ixy = inertia_xml->FirstChildElement("ixy");
TiXmlElement* ixz = inertia_xml->FirstChildElement("ixz");
TiXmlElement* iyy = inertia_xml->FirstChildElement("iyy");
TiXmlElement* iyz = inertia_xml->FirstChildElement("iyz");
TiXmlElement* izz = inertia_xml->FirstChildElement("izz");
if (ixx && ixy && ixz && iyy && iyz && izz)
{
inertia.m_ixx = urdfLexicalCast<double>(ixx->GetText());
inertia.m_ixy = urdfLexicalCast<double>(ixy->GetText());
inertia.m_ixz = urdfLexicalCast<double>(ixz->GetText());
inertia.m_iyy = urdfLexicalCast<double>(iyy->GetText());
inertia.m_iyz = urdfLexicalCast<double>(iyz->GetText());
inertia.m_izz = urdfLexicalCast<double>(izz->GetText());
} else
{
logger->reportError("Inertial: inertia element must have ixx,ixy,ixz,iyy,iyz,izz child elements");
return false;
}
} else
{
if (!(inertia_xml->Attribute("ixx") && inertia_xml->Attribute("ixy") && inertia_xml->Attribute("ixz") &&
inertia_xml->Attribute("iyy") && inertia_xml->Attribute("iyz") &&
inertia_xml->Attribute("izz")))
@@ -220,8 +262,9 @@ bool UrdfParser::parseInertia(UrdfInertia& inertia, TiXmlElement* config, ErrorL
inertia.m_iyy = urdfLexicalCast<double>(inertia_xml->Attribute("iyy"));
inertia.m_iyz = urdfLexicalCast<double>(inertia_xml->Attribute("iyz"));
inertia.m_izz = urdfLexicalCast<double>(inertia_xml->Attribute("izz"));
}
return true;
}
bool UrdfParser::parseGeometry(UrdfGeometry& geom, TiXmlElement* g, ErrorLogger* logger)
@@ -251,14 +294,28 @@ bool UrdfParser::parseGeometry(UrdfGeometry& geom, TiXmlElement* g, ErrorLogger*
else if (type_name == "box")
{
geom.m_type = URDF_GEOM_BOX;
if (m_parseSDF)
{
TiXmlElement* size = shape->FirstChildElement("size");
if (0==size)
{
logger->reportError("box requires a size child element");
return false;
}
parseVector3(geom.m_boxSize,size->GetText(),logger);
}
else
{
if (!shape->Attribute("size"))
{
logger->reportError("box requires a size attribute");
return false;
} else
{
parseVector3(geom.m_boxSize,shape->Attribute("size"),logger);
}
}
}
else if (type_name == "cylinder")
{
geom.m_type = URDF_GEOM_CYLINDER;
@@ -293,10 +350,30 @@ bool UrdfParser::parseGeometry(UrdfGeometry& geom, TiXmlElement* g, ErrorLogger*
}
else
{
if (this->m_parseSDF)
{
if (type_name == "plane")
{
geom.m_type = URDF_GEOM_PLANE;
TiXmlElement *n = shape->FirstChildElement("normal");
TiXmlElement *s = shape->FirstChildElement("size");
if ((0==n)||(0==s))
{
logger->reportError("Plane shape must have both normal and size attributes");
return false;
}
parseVector3(geom.m_planeNormal,n->GetText(),logger);
}
} else
{
logger->reportError("Unknown geometry type:");
logger->reportError(type_name.c_str());
return false;
}
}
return true;
@@ -331,7 +408,7 @@ bool UrdfParser::parseCollision(UrdfCollision& collision, TiXmlElement* config,
return true;
}
bool UrdfParser::parseVisual(UrdfVisual& visual, TiXmlElement* config, ErrorLogger* logger)
bool UrdfParser::parseVisual(UrdfModel& model, UrdfVisual& visual, TiXmlElement* config, ErrorLogger* logger)
{
visual.m_linkLocalFrame.setIdentity();
@@ -358,7 +435,8 @@ bool UrdfParser::parseVisual(UrdfVisual& visual, TiXmlElement* config, ErrorLogg
// Material
TiXmlElement *mat = config->FirstChildElement("material");
if (mat)
//todo(erwincoumans) skip materials in SDF for now (due to complexity)
if (mat && !m_parseSDF)
{
// get material name
if (!mat->Attribute("name"))
@@ -377,7 +455,7 @@ bool UrdfParser::parseVisual(UrdfVisual& visual, TiXmlElement* config, ErrorLogg
if (parseMaterial(visual.m_localMaterial, mat,logger))
{
UrdfMaterial* matPtr = new UrdfMaterial(visual.m_localMaterial);
m_model.m_materials.insert(matPtr->m_name.c_str(),matPtr);
model.m_materials.insert(matPtr->m_name.c_str(),matPtr);
visual.m_hasLocalMaterial = true;
}
}
@@ -386,7 +464,7 @@ bool UrdfParser::parseVisual(UrdfVisual& visual, TiXmlElement* config, ErrorLogg
return true;
}
bool UrdfParser::parseLink(UrdfLink& link, TiXmlElement *config, ErrorLogger* logger)
bool UrdfParser::parseLink(UrdfModel& model, UrdfLink& link, TiXmlElement *config, ErrorLogger* logger)
{
const char* linkName = config->Attribute("name");
if (!linkName)
@@ -435,7 +513,7 @@ bool UrdfParser::parseLink(UrdfLink& link, TiXmlElement *config, ErrorLogger* lo
{
UrdfVisual visual;
if (parseVisual(visual, vis_xml,logger))
if (parseVisual(model, visual, vis_xml,logger))
{
link.m_visualArray.push_back(visual);
}
@@ -676,16 +754,16 @@ bool UrdfParser::parseJoint(UrdfJoint& joint, TiXmlElement *config, ErrorLogger*
}
bool UrdfParser::initTreeAndRoot(ErrorLogger* logger)
bool UrdfParser::initTreeAndRoot(UrdfModel& model, ErrorLogger* logger)
{
// every link has children links and joints, but no parents, so we create a
// local convenience data structure for keeping child->parent relations
btHashMap<btHashString,btHashString> parentLinkTree;
// loop through all joints, for every link, assign children links and children joints
for (int i=0;i<m_model.m_joints.size();i++)
for (int i=0;i<model.m_joints.size();i++)
{
UrdfJoint** jointPtr = m_model.m_joints.getAtIndex(i);
UrdfJoint** jointPtr = model.m_joints.getAtIndex(i);
if (jointPtr)
{
UrdfJoint* joint = *jointPtr;
@@ -698,7 +776,7 @@ bool UrdfParser::initTreeAndRoot(ErrorLogger* logger)
return false;
}
UrdfLink** childLinkPtr = m_model.m_links.find(joint->m_childLinkName.c_str());
UrdfLink** childLinkPtr = model.m_links.find(joint->m_childLinkName.c_str());
if (!childLinkPtr)
{
logger->reportError("Cannot find child link for joint ");
@@ -708,7 +786,7 @@ bool UrdfParser::initTreeAndRoot(ErrorLogger* logger)
}
UrdfLink* childLink = *childLinkPtr;
UrdfLink** parentLinkPtr = m_model.m_links.find(joint->m_parentLinkName.c_str());
UrdfLink** parentLinkPtr = model.m_links.find(joint->m_parentLinkName.c_str());
if (!parentLinkPtr)
{
logger->reportError("Cannot find parent link for a joint");
@@ -728,9 +806,9 @@ bool UrdfParser::initTreeAndRoot(ErrorLogger* logger)
}
//search for children that have no parent, those are 'root'
for (int i=0;i<m_model.m_links.size();i++)
for (int i=0;i<model.m_links.size();i++)
{
UrdfLink** linkPtr = m_model.m_links.getAtIndex(i);
UrdfLink** linkPtr = model.m_links.getAtIndex(i);
btAssert(linkPtr);
if (linkPtr)
{
@@ -739,18 +817,18 @@ bool UrdfParser::initTreeAndRoot(ErrorLogger* logger)
if (!link->m_parentLink)
{
m_model.m_rootLinks.push_back(link);
model.m_rootLinks.push_back(link);
}
}
}
if (m_model.m_rootLinks.size()>1)
if (model.m_rootLinks.size()>1)
{
logger->reportWarning("URDF file with multiple root links found");
}
if (m_model.m_rootLinks.size()==0)
if (model.m_rootLinks.size()==0)
{
logger->reportError("URDF without root link found");
return false;
@@ -785,7 +863,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
logger->reportError("Expected a name for robot");
return false;
}
m_model.m_name = name;
m_urdf2Model.m_name = name;
@@ -797,13 +875,13 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
parseMaterial(*material, material_xml, logger);
UrdfMaterial** mat =m_model.m_materials.find(material->m_name.c_str());
UrdfMaterial** mat =m_urdf2Model.m_materials.find(material->m_name.c_str());
if (mat)
{
logger->reportWarning("Duplicate material");
} else
{
m_model.m_materials.insert(material->m_name.c_str(),material);
m_urdf2Model.m_materials.insert(material->m_name.c_str(),material);
}
}
@@ -817,9 +895,9 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
{
UrdfLink* link = new UrdfLink;
if (parseLink(*link, link_xml,logger))
if (parseLink(m_urdf2Model,*link, link_xml,logger))
{
if (m_model.m_links.find(link->m_name.c_str()))
if (m_urdf2Model.m_links.find(link->m_name.c_str()))
{
logger->reportError("Link name is not unique, link names in the same model have to be unique");
logger->reportError(link->m_name.c_str());
@@ -832,7 +910,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
UrdfVisual& vis = link->m_visualArray.at(i);
if (!vis.m_hasLocalMaterial && vis.m_materialName.c_str())
{
UrdfMaterial** mat = m_model.m_materials.find(vis.m_materialName.c_str());
UrdfMaterial** mat = m_urdf2Model.m_materials.find(vis.m_materialName.c_str());
if (mat && *mat)
{
vis.m_localMaterial = **mat;
@@ -844,7 +922,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
}
}
m_model.m_links.insert(link->m_name.c_str(),link);
m_urdf2Model.m_links.insert(link->m_name.c_str(),link);
}
} else
{
@@ -854,7 +932,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
}
}
if (m_model.m_links.size() == 0)
if (m_urdf2Model.m_links.size() == 0)
{
logger->reportWarning("No links found in URDF file");
return false;
@@ -867,7 +945,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
if (parseJoint(*joint, joint_xml,logger))
{
if (m_model.m_joints.find(joint->m_name.c_str()))
if (m_urdf2Model.m_joints.find(joint->m_name.c_str()))
{
logger->reportError("joint '%s' is not unique.");
logger->reportError(joint->m_name.c_str());
@@ -875,7 +953,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
}
else
{
m_model.m_joints.insert(joint->m_name.c_str(),joint);
m_urdf2Model.m_joints.insert(joint->m_name.c_str(),joint);
}
}
else
@@ -885,7 +963,7 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
}
}
bool ok(initTreeAndRoot(logger));
bool ok(initTreeAndRoot(m_urdf2Model,logger));
if (!ok)
{
return false;
@@ -893,9 +971,9 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
if (forceFixedBase)
{
for (int i=0;i<m_model.m_rootLinks.size();i++)
for (int i=0;i<m_urdf2Model.m_rootLinks.size();i++)
{
UrdfLink* link(m_model.m_rootLinks.at(i));
UrdfLink* link(m_urdf2Model.m_rootLinks.at(i));
link->m_inertia.m_mass = 0.0;
link->m_inertia.m_ixx = 0.0;
link->m_inertia.m_ixy = 0.0;
@@ -908,3 +986,161 @@ bool UrdfParser::loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceF
return true;
}
void UrdfParser::activateModel(int modelIndex)
{
m_activeSdfModel = modelIndex;
}
bool UrdfParser::loadSDF(const char* sdfText, ErrorLogger* logger)
{
TiXmlDocument xml_doc;
xml_doc.Parse(sdfText);
if (xml_doc.Error())
{
logger->reportError(xml_doc.ErrorDesc());
xml_doc.ClearError();
return false;
}
TiXmlElement *sdf_xml = xml_doc.FirstChildElement("sdf");
if (!sdf_xml)
{
logger->reportError("expected an sdf element");
return false;
}
TiXmlElement *world_xml = sdf_xml->FirstChildElement("world");
if (!world_xml)
{
logger->reportError("expected a world element");
return false;
}
// Get all model (robot) elements
for (TiXmlElement* robot_xml = world_xml->FirstChildElement("model"); robot_xml; robot_xml = robot_xml->NextSiblingElement("model"))
{
UrdfModel* localModel = new UrdfModel;
m_tmpModels.push_back(localModel);
// Get robot name
const char *name = robot_xml->Attribute("name");
if (!name)
{
logger->reportError("Expected a name for robot");
return false;
}
localModel->m_name = name;
// Get all Material elements
for (TiXmlElement* material_xml = robot_xml->FirstChildElement("material"); material_xml; material_xml = material_xml->NextSiblingElement("material"))
{
UrdfMaterial* material = new UrdfMaterial;
parseMaterial(*material, material_xml, logger);
UrdfMaterial** mat =localModel->m_materials.find(material->m_name.c_str());
if (mat)
{
logger->reportWarning("Duplicate material");
} else
{
localModel->m_materials.insert(material->m_name.c_str(),material);
}
}
// char msg[1024];
// sprintf(msg,"Num materials=%d", m_model.m_materials.size());
// logger->printMessage(msg);
for (TiXmlElement* link_xml = robot_xml->FirstChildElement("link"); link_xml; link_xml = link_xml->NextSiblingElement("link"))
{
UrdfLink* link = new UrdfLink;
if (parseLink(*localModel, *link, link_xml,logger))
{
if (localModel->m_links.find(link->m_name.c_str()))
{
logger->reportError("Link name is not unique, link names in the same model have to be unique");
logger->reportError(link->m_name.c_str());
return false;
} else
{
//copy model material into link material, if link has no local material
for (int i=0;i<link->m_visualArray.size();i++)
{
UrdfVisual& vis = link->m_visualArray.at(i);
if (!vis.m_hasLocalMaterial && vis.m_materialName.c_str())
{
UrdfMaterial** mat = localModel->m_materials.find(vis.m_materialName.c_str());
if (mat && *mat)
{
vis.m_localMaterial = **mat;
} else
{
//logger->reportError("Cannot find material with name:");
//logger->reportError(vis.m_materialName.c_str());
}
}
}
localModel->m_links.insert(link->m_name.c_str(),link);
}
} else
{
logger->reportError("failed to parse link");
delete link;
return false;
}
}
if (localModel->m_links.size() == 0)
{
logger->reportWarning("No links found in URDF file");
return false;
}
// Get all Joint elements
for (TiXmlElement* joint_xml = robot_xml->FirstChildElement("joint"); joint_xml; joint_xml = joint_xml->NextSiblingElement("joint"))
{
UrdfJoint* joint = new UrdfJoint;
if (parseJoint(*joint, joint_xml,logger))
{
if (localModel->m_joints.find(joint->m_name.c_str()))
{
logger->reportError("joint '%s' is not unique.");
logger->reportError(joint->m_name.c_str());
return false;
}
else
{
localModel->m_joints.insert(joint->m_name.c_str(),joint);
}
}
else
{
logger->reportError("joint xml is not initialized correctly");
return false;
}
}
bool ok(initTreeAndRoot(*localModel,logger));
if (!ok)
{
return false;
}
m_sdfModels.push_back(localModel);
}
return true;
}

View File

@@ -42,7 +42,9 @@ enum UrdfGeomTypes
URDF_GEOM_SPHERE=2,
URDF_GEOM_BOX,
URDF_GEOM_CYLINDER,
URDF_GEOM_MESH
URDF_GEOM_MESH,
URDF_GEOM_PLANE,
};
@@ -57,6 +59,8 @@ struct UrdfGeometry
double m_cylinderRadius;
double m_cylinderLength;
btVector3 m_planeNormal;
std::string m_meshFileName;
btVector3 m_meshScale;
};
@@ -134,32 +138,88 @@ struct UrdfModel
class UrdfParser
{
protected:
UrdfModel m_urdf2Model;
btAlignedObjectArray<UrdfModel*> m_sdfModels;
btAlignedObjectArray<UrdfModel*> m_tmpModels;
bool m_parseSDF;
int m_activeSdfModel;
void cleanModel(UrdfModel* model);
bool parseInertia(UrdfInertia& inertia, class TiXmlElement* config, ErrorLogger* logger);
bool parseGeometry(UrdfGeometry& geom, class TiXmlElement* g, ErrorLogger* logger);
bool parseVisual(UrdfVisual& visual, class TiXmlElement* config, ErrorLogger* logger);
bool parseVisual(UrdfModel& model, UrdfVisual& visual, class TiXmlElement* config, ErrorLogger* logger);
bool parseCollision(UrdfCollision& collision, class TiXmlElement* config, ErrorLogger* logger);
bool initTreeAndRoot(ErrorLogger* logger);
bool initTreeAndRoot(UrdfModel& model, ErrorLogger* logger);
bool parseMaterial(UrdfMaterial& material, class TiXmlElement *config, ErrorLogger* logger);
bool parseJointLimits(UrdfJoint& joint, TiXmlElement* config, ErrorLogger* logger);
bool parseJoint(UrdfJoint& link, TiXmlElement *config, ErrorLogger* logger);
bool parseLink(UrdfLink& link, TiXmlElement *config, ErrorLogger* logger);
UrdfModel m_model;
bool parseLink(UrdfModel& model, UrdfLink& link, TiXmlElement *config, ErrorLogger* logger);
public:
UrdfParser();
virtual ~UrdfParser();
void setParseSDF(bool useSDF)
{
m_parseSDF = useSDF;
}
bool getParseSDF() const
{
return m_parseSDF;
}
bool loadUrdf(const char* urdfText, ErrorLogger* logger, bool forceFixedBase);
bool loadSDF(const char* sdfText, ErrorLogger* logger);
int getNumModels() const
{
//user should have loaded an SDF when calling this method
btAssert(m_parseSDF);
if (m_parseSDF)
{
return m_sdfModels.size();
}
}
void activateModel(int modelIndex);
UrdfModel& getModelByIndex(int index)
{
//user should have loaded an SDF when calling this method
btAssert(m_parseSDF);
return *m_sdfModels[index];
}
const UrdfModel& getModelByIndex(int index) const
{
//user should have loaded an SDF when calling this method
btAssert(m_parseSDF);
return *m_sdfModels[index];
}
const UrdfModel& getModel() const
{
return m_model;
if (m_parseSDF)
{
return *m_sdfModels[m_activeSdfModel];
}
return m_urdf2Model;
}
UrdfModel& getModel()
{
return m_model;
if (m_parseSDF)
{
return *m_sdfModels[m_activeSdfModel];
}
return m_urdf2Model;
}
};

View File

@@ -129,12 +129,14 @@ void InverseDynamicsExample::initPhysics()
SliderParams slider("Kp",&kp);
slider.m_minVal=0;
slider.m_maxVal=2000;
if (m_guiHelper->getParameterInterface())
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
}
{
SliderParams slider("Kd",&kd);
slider.m_minVal=0;
slider.m_maxVal=50;
if (m_guiHelper->getParameterInterface())
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
}
@@ -148,6 +150,7 @@ void InverseDynamicsExample::initPhysics()
switch (m_option)
{
case 0:
case BT_ID_LOAD_URDF:
{
BulletURDFImporter u2b(m_guiHelper);
@@ -188,10 +191,12 @@ void InverseDynamicsExample::initPhysics()
if(m_multiBody) {
{
if (m_guiHelper->getAppInterface() && m_guiHelper->getParameterInterface())
{
m_timeSeriesCanvas = new TimeSeriesCanvas(m_guiHelper->getAppInterface()->m_2dCanvasInterface,512,230, "Joint Space Trajectory");
m_timeSeriesCanvas ->setupTimeSeries(3,100, 0);
}
}
// construct inverse model
@@ -203,9 +208,14 @@ void InverseDynamicsExample::initPhysics()
}
// add joint target controls
qd.resize(m_multiBody->getNumDofs());
qd[3]=B3_HALF_PI;
qd_name.resize(m_multiBody->getNumDofs());
q_name.resize(m_multiBody->getNumDofs());
for(std::size_t dof=0;dof<qd.size();dof++) {
if (m_timeSeriesCanvas && m_guiHelper->getParameterInterface())
{
for(std::size_t dof=0;dof<qd.size();dof++)
{
qd[dof] = 0;
char tmp[25];
sprintf(tmp,"q_desired[%zu]",dof);
@@ -213,13 +223,15 @@ void InverseDynamicsExample::initPhysics()
SliderParams slider(qd_name[dof].c_str(),&qd[dof]);
slider.m_minVal=-3.14;
slider.m_maxVal=3.14;
sprintf(tmp,"q[%zu]",dof);
q_name[dof] = tmp;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter(slider);
btVector4 color = sJointCurveColors[dof&7];
m_timeSeriesCanvas->addDataSource(q_name[dof].c_str(), color[0]*255,color[1]*255,color[2]*255);
}
}
}
}
@@ -246,6 +258,7 @@ void InverseDynamicsExample::stepSimulation(float deltaTime)
const btScalar qd_dot=0;
const btScalar qd_ddot=0;
if (m_timeSeriesCanvas)
m_timeSeriesCanvas->insertDataAtCurrentTime(q[dof],dof,true);
// pd_control is either desired joint torque for pd control,
@@ -330,3 +343,4 @@ CommonExampleInterface* InverseDynamicsExampleCreateFunc(CommonExampleOptions
B3_STANDALONE_EXAMPLE(InverseDynamicsExampleCreateFunc)

View File

@@ -0,0 +1,162 @@
project "App_InverseDynamicsExample"
if _OPTIONS["ios"] then
kind "WindowedApp"
else
kind "ConsoleApp"
end
defines {"B3_USE_STANDALONE_EXAMPLE"}
includedirs {"../../src"}
links {
"BulletInverseDynamicsUtils", "BulletInverseDynamics","Bullet3Common","BulletDynamics","BulletCollision", "LinearMath"
}
language "C++"
files {
"**.cpp",
"**.h",
"../StandaloneMain/main_console_single_example.cpp",
"../Utils/b3ResourcePath.cpp",
"../Utils/b3ResourcePath.h",
"../RenderingExamples/TimeSeriesCanvas.cpp",
"../RenderingExamples/TimeSeriesFontData.cpp",
"../MultiBody/InvertedPendulumPDControl.cpp",
"../ThirdPartyLibs/tinyxml/tinystr.cpp",
"../ThirdPartyLibs/tinyxml/tinyxml.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.h",
"../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
"../Importers/ImportObjDemo/LoadMeshFromObj.cpp",
"../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
"../Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
"../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
"../Importers/ImportURDFDemo/URDF2Bullet.cpp",
"../Importers/ImportURDFDemo/UrdfParser.cpp",
"../Importers/ImportURDFDemo/urdfStringSplit.cpp",
}
project "App_InverseDynamicsExampleGui"
if _OPTIONS["ios"] then
kind "WindowedApp"
else
kind "ConsoleApp"
end
defines {"B3_USE_STANDALONE_EXAMPLE"}
includedirs {"../../src"}
links {
"BulletInverseDynamicsUtils", "BulletInverseDynamics","BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common"
}
initOpenGL()
initGlew()
language "C++"
files {
"InverseDynamicsExample.cpp",
"*.h",
"../StandaloneMain/main_opengl_single_example.cpp",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../Utils/b3ResourcePath.cpp",
"../Utils/b3ResourcePath.h",
"../RenderingExamples/TimeSeriesCanvas.cpp",
"../RenderingExamples/TimeSeriesFontData.cpp",
"../MultiBody/InvertedPendulumPDControl.cpp",
"../ThirdPartyLibs/tinyxml/tinystr.cpp",
"../ThirdPartyLibs/tinyxml/tinyxml.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.h",
"../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
"../Importers/ImportObjDemo/LoadMeshFromObj.cpp",
"../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
"../Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
"../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
"../Importers/ImportURDFDemo/URDF2Bullet.cpp",
"../Importers/ImportURDFDemo/UrdfParser.cpp",
"../Importers/ImportURDFDemo/urdfStringSplit.cpp",
}
if os.is("Linux") then initX11() end
if os.is("MacOSX") then
links{"Cocoa.framework"}
end
project "App_InverseDynamicsExampleGuiWithSoftwareRenderer"
if _OPTIONS["ios"] then
kind "WindowedApp"
else
kind "ConsoleApp"
end
defines {"B3_USE_STANDALONE_EXAMPLE"}
includedirs {"../../src"}
links {
"BulletInverseDynamicsUtils", "BulletInverseDynamics","BulletDynamics","BulletCollision", "LinearMath", "OpenGL_Window","Bullet3Common"
}
initOpenGL()
initGlew()
language "C++"
files {
"InverseDynamicsExample.cpp",
"*.h",
"../StandaloneMain/main_sw_tinyrenderer_single_example.cpp",
"../ExampleBrowser/OpenGLGuiHelper.cpp",
"../ExampleBrowser/GL_ShapeDrawer.cpp",
"../TinyRenderer/geometry.cpp",
"../TinyRenderer/model.cpp",
"../TinyRenderer/tgaimage.cpp",
"../TinyRenderer/our_gl.cpp",
"../TinyRenderer/TinyRenderer.cpp",
"../Utils/b3ResourcePath.cpp",
"../Utils/b3ResourcePath.cpp",
"../Utils/b3ResourcePath.h",
"../RenderingExamples/TimeSeriesCanvas.cpp",
"../RenderingExamples/TimeSeriesFontData.cpp",
"../MultiBody/InvertedPendulumPDControl.cpp",
"../ThirdPartyLibs/tinyxml/tinystr.cpp",
"../ThirdPartyLibs/tinyxml/tinyxml.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlerror.cpp",
"../ThirdPartyLibs/tinyxml/tinyxmlparser.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.cpp",
"../ThirdPartyLibs/Wavefront/tiny_obj_loader.h",
"../Importers/ImportColladaDemo/LoadMeshFromCollada.cpp",
"../Importers/ImportObjDemo/LoadMeshFromObj.cpp",
"../Importers/ImportObjDemo/Wavefront2GLInstanceGraphicsShape.cpp",
"../Importers/ImportURDFDemo/BulletUrdfImporter.cpp",
"../Importers/ImportURDFDemo/MyMultiBodyCreator.cpp",
"../Importers/ImportURDFDemo/URDF2Bullet.cpp",
"../Importers/ImportURDFDemo/UrdfParser.cpp",
"../Importers/ImportURDFDemo/urdfStringSplit.cpp",
}
if os.is("Linux") then initX11() end
if os.is("MacOSX") then
links{"Cocoa.framework"}
end

View File

@@ -59,7 +59,7 @@ if (BUILD_SHARED_LIBS)
else()
set (CMAKE_THREAD_PREFER_PTHREAD TRUE)
FIND_PACKAGE(Threads)
target_link_libraries(OpenGLWindow ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(OpenGLWindow dl ${CMAKE_THREAD_LIBS_INIT})
endif()
endif()

View File

@@ -134,7 +134,12 @@ extern int gShapeIndex;
struct InternalTextureHandle
{
GLuint m_glTexture;
int m_width;
int m_height;
};
@@ -148,7 +153,7 @@ struct InternalDataRenderer : public GLInstanceRendererInternalData
GLuint m_defaultTexturehandle;
b3AlignedObjectArray<GLuint> m_textureHandles;
b3AlignedObjectArray<InternalTextureHandle> m_textureHandles;
GLRenderToTexture* m_shadowMap;
GLuint m_shadowTexture;
@@ -518,7 +523,7 @@ int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float*
int GLInstancingRenderer::registerTexture(const unsigned char* texels, int width, int height)
{
b3Assert(glGetError() ==GL_NO_ERROR);
glActiveTexture(GL_TEXTURE0);
int textureIndex = m_data->m_textureHandles.size();
const GLubyte* image= (const GLubyte*)texels;
GLuint textureHandle;
@@ -527,17 +532,63 @@ int GLInstancingRenderer::registerTexture(const unsigned char* texels, int width
b3Assert(glGetError() ==GL_NO_ERROR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width,height,0,GL_RGB,GL_UNSIGNED_BYTE,image);
InternalTextureHandle h;
h.m_glTexture = textureHandle;
h.m_width = width;
h.m_height = height;
m_data->m_textureHandles.push_back(h);
updateTexture(textureIndex, texels);
return textureIndex;
}
void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned char* texels)
{
if (textureIndex>=0)
{
glActiveTexture(GL_TEXTURE0);
b3Assert(glGetError() ==GL_NO_ERROR);
InternalTextureHandle& h = m_data->m_textureHandles[textureIndex];
//textures need to be flipped for OpenGL...
b3AlignedObjectArray<unsigned char> flippedTexels;
flippedTexels.resize(h.m_width* h.m_height * 3);
for (int i = 0; i < h.m_width; i++)
{
for (int j = 0; j < h.m_height; j++)
{
flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height - 1 -j )*h.m_width) * 3];
flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1];
flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+2];
}
}
glBindTexture(GL_TEXTURE_2D,h.m_glTexture);
b3Assert(glGetError() ==GL_NO_ERROR);
const GLubyte* image= (const GLubyte*)texels;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,&flippedTexels[0]);
b3Assert(glGetError() ==GL_NO_ERROR);
glGenerateMipmap(GL_TEXTURE_2D);
b3Assert(glGetError() ==GL_NO_ERROR);
}
}
void GLInstancingRenderer::activateTexture(int textureIndex)
{
glActiveTexture(GL_TEXTURE0);
m_data->m_textureHandles.push_back(textureHandle);
return textureIndex;
if (textureIndex>=0)
{
glBindTexture(GL_TEXTURE_2D,m_data->m_textureHandles[textureIndex].m_glTexture);
} else
{
glBindTexture(GL_TEXTURE_2D,0);
}
}
void GLInstancingRenderer::updateShape(int shapeIndex, const float* vertices)
@@ -559,7 +610,7 @@ int GLInstancingRenderer::registerShape(const float* vertices, int numvertices,
if (textureId>=0)
{
gfxObj->m_texturehandle = m_data->m_textureHandles[textureId];
gfxObj->m_texturehandle = m_data->m_textureHandles[textureId].m_glTexture;
}
gfxObj->m_primitiveType = primitiveType;

View File

@@ -63,6 +63,9 @@ public:
virtual int registerShape(const float* vertices, int numvertices, const int* indices, int numIndices, int primitiveType=B3_GL_TRIANGLES, int textureIndex=-1);
virtual int registerTexture(const unsigned char* texels, int width, int height);
virtual void updateTexture(int textureIndex, const unsigned char* texels);
virtual void activateTexture(int textureIndex);
///position x,y,z, quaternion x,y,z,w, color r,g,b,a, scaling x,y,z
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling);

View File

@@ -101,6 +101,9 @@ public:
virtual float getTimeInSeconds();
virtual int getWidth() const;
virtual int getHeight() const;
virtual void setRenderCallback( b3RenderCallback renderCallback);

View File

@@ -423,8 +423,8 @@ void MacOpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci)
[m_internalData->m_window makeKeyAndOrderFront: nil];
[m_internalData->m_myview MakeCurrent];
//m_internalData->m_width = m_internalData->m_myview.GetWindowWidth;
//m_internalData->m_height = m_internalData->m_myview.GetWindowHeight;
m_internalData->m_width = m_internalData->m_myview.GetWindowWidth;
m_internalData->m_height = m_internalData->m_myview.GetWindowHeight;
[NSApp activateIgnoringOtherApps:YES];
@@ -1132,6 +1132,21 @@ void MacOpenGLWindow::getMouseCoordinates(int& x, int& y)
}
int MacOpenGLWindow::getWidth() const
{
if (m_internalData && m_internalData->m_myview && m_internalData->m_myview.GetWindowWidth)
return m_internalData->m_myview.GetWindowWidth;
return 0;
}
int MacOpenGLWindow::getHeight() const
{
if (m_internalData && m_internalData->m_myview && m_internalData->m_myview.GetWindowHeight)
return m_internalData->m_myview.GetWindowHeight;
return 0;
}
void MacOpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback)
{
[m_internalData->m_myview setResizeCallback:resizeCallback];

View File

@@ -50,6 +50,10 @@ struct SimpleOpenGL2Renderer : public CommonRenderInterface
{
return -1;
}
virtual void updateTexture(int textureIndex, const unsigned char* texels) {}
virtual void activateTexture(int textureIndex) {}
virtual int registerGraphicsInstance(int shapeIndex, const double* position, const double* quaternion, const double* color, const double* scaling);
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling);

View File

@@ -56,7 +56,10 @@ static void SimpleResizeCallback( float widthf, float heightf)
{
int width = (int)widthf;
int height = (int)heightf;
if (gApp && gApp->m_instancingRenderer)
gApp->m_instancingRenderer->resize(width,height);
if (gApp && gApp->m_primRenderer)
gApp->m_primRenderer->setScreenSize(width,height);
}
@@ -115,6 +118,7 @@ extern unsigned char OpenSansData[];
SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, bool allowRetina)
{
gApp = this;
m_data = new SimpleInternalData;
m_data->m_frameDumpPngFileName = 0;
m_data->m_renderTexture = 0;
@@ -123,6 +127,7 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo
m_data->m_upAxis = 1;
m_window = new b3gDefaultOpenGLWindow();
m_window->setAllowRetina(allowRetina);
b3gWindowConstructionInfo ci;
@@ -141,6 +146,9 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo
1.f);
m_window->startRendering();
width = m_window->getWidth();
height = m_window->getHeight();
b3Assert(glGetError() ==GL_NO_ERROR);
#ifndef __APPLE__
@@ -160,16 +168,20 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo
b3Assert(glGetError() ==GL_NO_ERROR);
m_primRenderer = new GLPrimitiveRenderer(width,height);
m_parameterInterface = 0;
b3Assert(glGetError() ==GL_NO_ERROR);
m_instancingRenderer = new GLInstancingRenderer(128*1024,64*1024*1024);
m_primRenderer = new GLPrimitiveRenderer(width,height);
m_renderer = m_instancingRenderer ;
m_window->setResizeCallback(SimpleResizeCallback);
m_instancingRenderer->init();
m_instancingRenderer->resize(width,height);
m_primRenderer->setScreenSize(width,height);
b3Assert(glGetError() ==GL_NO_ERROR);
m_instancingRenderer->InitShaders();
@@ -178,7 +190,6 @@ SimpleOpenGL3App::SimpleOpenGL3App( const char* title, int width,int height, boo
m_window->setMouseButtonCallback(SimpleMouseButtonCallback);
m_window->setKeyboardCallback(SimpleKeyboardCallback);
m_window->setWheelCallback(SimpleWheelCallback);
m_window->setResizeCallback(SimpleResizeCallback);
TwGenerateDefaultFonts();
m_data->m_fontTextureId = BindFont(g_DefaultNormalFont);

View File

@@ -180,6 +180,21 @@ int Win32OpenGLWindow::fileOpenDialog(char* fileName, int maxFileNameLength)
//return 0;
}
int Win32OpenGLWindow::getWidth() const
{
if (m_data)
return m_data->m_openglViewportWidth;
return 0;
}
int Win32OpenGLWindow::getHeight() const
{
if (m_data)
return m_data->m_openglViewportHeight;
return 0;
}
#endif

View File

@@ -53,6 +53,9 @@ public:
virtual float getRetinaScale() const {return 1.f;}
virtual void setAllowRetina(bool /*allowRetina*/) {};
virtual int getWidth() const;
virtual int getHeight() const;
virtual int fileOpenDialog(char* fileName, int maxFileNameLength);
};

View File

@@ -461,6 +461,7 @@ void X11OpenGLWindow::enableOpenGL()
printf( "Making context current\n" );
glXMakeCurrent( m_data->m_dpy, m_data->m_win, ctx );
m_data->m_glc = ctx;
} else
{
@@ -1075,6 +1076,20 @@ b3KeyboardCallback X11OpenGLWindow::getKeyboardCallback()
return m_data->m_keyboardCallback;
}
int X11OpenGLWindow::getWidth() const
{
if (m_data)
return m_data->m_glWidth;
return 0;
}
int X11OpenGLWindow::getHeight() const
{
if (m_data)
return m_data->m_glHeight;
return 0;
}
#include <stdio.h>
int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength)

View File

@@ -65,9 +65,14 @@ public:
virtual void setWindowTitle(const char* title);
virtual int getWidth() const;
virtual int getHeight() const;
int fileOpenDialog(char* filename, int maxNameLength);
};
#endif

View File

@@ -72,13 +72,14 @@ struct TimeSeriesInternalData
TimeSeriesCanvas::TimeSeriesCanvas(struct Common2dCanvasInterface* canvasInterface, int width, int height, const char* windowTitle)
{
btAssert(canvasInterface);
m_internalData = new TimeSeriesInternalData(width,height);
m_internalData->m_canvasInterface = canvasInterface;
if (canvasInterface)
{
m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle,m_internalData->m_width,m_internalData->m_height);
}
}
void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char red,unsigned char green,unsigned char blue)
@@ -105,6 +106,9 @@ void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char
}
void TimeSeriesCanvas::setupTimeSeries(float yScale, int ticksPerSecond, int startTime)
{
if (0==m_internalData->m_canvasInterface)
return;
m_internalData->m_pixelsPerUnit = -(m_internalData->m_height/3.f)/yScale;
m_internalData->m_ticksPerSecond = ticksPerSecond;
m_internalData->m_yScale = yScale;
@@ -282,6 +286,9 @@ void TimeSeriesCanvas::shift1PixelToLeft()
void TimeSeriesCanvas::insertDataAtCurrentTime(float orgV, int dataSourceIndex, bool connectToPrevious)
{
if (0==m_internalData->m_canvasInterface)
return;
btAssert(dataSourceIndex < m_internalData->m_dataSources.size());
float zero = m_internalData->m_zero;

View File

@@ -222,6 +222,27 @@ void b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandl
}
}
void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int linkIndex, b3LinkState *state)
{
const SharedMemoryStatus* status = (const SharedMemoryStatus* ) statusHandle;
b3Assert(status);
int bodyIndex = status->m_sendActualStateArgs.m_bodyUniqueId;
b3Assert(bodyIndex>=0);
if (bodyIndex>=0)
{
for (int i = 0; i < 3; ++i)
{
state->m_worldPosition[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + i];
state->m_localInertialPosition[i] = status->m_sendActualStateArgs.m_linkLocalInertialFrames[7 * linkIndex + i];
}
for (int i = 0; i < 4; ++i)
{
state->m_worldOrientation[i] = status->m_sendActualStateArgs.m_linkState[7 * linkIndex + 3 + i];
state->m_localInertialOrientation[i] = status->m_sendActualStateArgs.m_linkLocalInertialFrames[7 * linkIndex + 3 + i];
}
}
}
b3SharedMemoryCommandHandle b3CreateBoxShapeCommandInit(b3PhysicsClientHandle physClient)
{
PhysicsClient* cl = (PhysicsClient* ) physClient;

View File

@@ -130,6 +130,7 @@ int b3CreateSensorEnableIMUForLink(b3SharedMemoryCommandHandle commandHandle, in
b3SharedMemoryCommandHandle b3RequestActualStateCommandInit(b3PhysicsClientHandle physClient,int bodyUniqueId);
void b3GetJointState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int jointIndex, struct b3JointSensorState *state);
void b3GetLinkState(b3PhysicsClientHandle physClient, b3SharedMemoryStatusHandle statusHandle, int linkIndex, struct b3LinkState *state);
b3SharedMemoryCommandHandle b3PickBody(b3PhysicsClientHandle physClient, double rayFromWorldX,
double rayFromWorldY, double rayFromWorldZ,

View File

@@ -82,6 +82,7 @@ struct InteralBodyData
int m_testData;
btTransform m_rootLocalInertialFrame;
btAlignedObjectArray<btTransform> m_linkLocalInertialFrames;
InteralBodyData()
:m_multiBody(0),
@@ -763,11 +764,18 @@ bool PhysicsServerCommandProcessor::loadUrdf(const char* fileName, const btVecto
//disable serialization of the collision objects (they are too big, and the client likely doesn't need them);
util->m_memSerializer->m_skipPointers.insert(mb->getBaseCollider(),0);
bodyHandle->m_linkLocalInertialFrames.reserve(mb->getNumLinks());
for (int i=0;i<mb->getNumLinks();i++)
{
//disable serialization of the collision objects
util->m_memSerializer->m_skipPointers.insert(mb->getLink(i).m_collider,0);
int urdfLinkIndex = creation.m_mb2urdfLink[i];
btScalar mass;
btVector3 localInertiaDiagonal(0,0,0);
btTransform localInertialFrame;
u2b.getMassAndInertia(urdfLinkIndex, mass,localInertiaDiagonal,localInertialFrame);
bodyHandle->m_linkLocalInertialFrames.push_back(localInertialFrame);
std::string* linkName = new std::string(u2b.getLinkName(urdfLinkIndex).c_str());
m_data->m_strings.push_back(linkName);
util->m_memSerializer->registerNameForPointer(linkName->c_str(),linkName->c_str());
@@ -1349,6 +1357,29 @@ bool PhysicsServerCommandProcessor::processCommand(const struct SharedMemoryComm
//}
}
}
btVector3 linkLocalInertialOrigin = body->m_linkLocalInertialFrames[l].getOrigin();
btQuaternion linkLocalInertialRotation = body->m_linkLocalInertialFrames[l].getRotation();
btVector3 linkOrigin = mb->getLink(l).m_cachedWorldTransform.getOrigin();
btQuaternion linkRotation = mb->getLink(l).m_cachedWorldTransform.getRotation();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+0] = linkOrigin.getX();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+1] = linkOrigin.getY();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+2] = linkOrigin.getZ();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+3] = linkRotation.x();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+4] = linkRotation.y();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+5] = linkRotation.z();
serverCmd.m_sendActualStateArgs.m_linkState[l*7+6] = linkRotation.w();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+0] = linkLocalInertialOrigin.getX();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+1] = linkLocalInertialOrigin.getY();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+2] = linkLocalInertialOrigin.getZ();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+3] = linkLocalInertialRotation.x();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+4] = linkLocalInertialRotation.y();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+5] = linkLocalInertialRotation.z();
serverCmd.m_sendActualStateArgs.m_linkLocalInertialFrames[l*7+6] = linkLocalInertialRotation.w();
}

View File

@@ -31,6 +31,7 @@
#define MAX_NUM_SENSORS 256
#define MAX_URDF_FILENAME_LENGTH 1024
#define MAX_FILENAME_LENGTH MAX_URDF_FILENAME_LENGTH
#define MAX_NUM_LINKS MAX_DEGREE_OF_FREEDOM
struct TmpFloat3
{
@@ -196,6 +197,9 @@ struct SendActualStateArgs
double m_jointReactionForces[6*MAX_DEGREE_OF_FREEDOM];
double m_jointMotorForce[MAX_DEGREE_OF_FREEDOM];
double m_linkState[7*MAX_NUM_LINKS];
double m_linkLocalInertialFrames[7*MAX_NUM_LINKS];
};
enum EnumSensorTypes

View File

@@ -105,6 +105,20 @@ struct b3DebugLines
const float* m_linesColor;//float red,green,blue times 'm_numDebugLines'.
};
///b3LinkState provides extra information such as the Cartesian world coordinates
///center of mass (COM) of the link, relative to the world reference frame.
///Orientation is a quaternion x,y,z,w
///Note: to compute the URDF link frame (which equals the joint frame at joint position 0)
///use URDF link frame = link COM frame * inertiaFrame.inverse()
struct b3LinkState
{
double m_worldPosition[3];
double m_worldOrientation[4];
double m_localInertialPosition[3];
double m_localInertialOrientation[4];
};
//todo: discuss and decide about control mode and combinations
enum {
// POSITION_CONTROL=0,

View File

@@ -1,10 +1,8 @@
#include "OpenGLWindow/SimpleOpenGL3App.h"
#include "Bullet3Common/b3Vector3.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "assert.h"
#include <stdio.h>
#include "OpenGLWindow/OpenGLInclude.h"
char* gVideoFileName = 0;
char* gPngFileName = 0;
@@ -16,6 +14,8 @@ static b3MouseButtonCallback sOldMouseButtonCB = 0;
static b3KeyboardCallback sOldKeyboardCB = 0;
//static b3RenderCallback sOldRenderCB = 0;
float gWidth = 0 ;
float gHeight = 0;
void MyWheelCallback(float deltax, float deltay)
{
@@ -24,6 +24,9 @@ void MyWheelCallback(float deltax, float deltay)
}
void MyResizeCallback( float width, float height)
{
gWidth = width;
gHeight = height;
if (sOldResizeCB)
sOldResizeCB(width,height);
}
@@ -59,6 +62,7 @@ int main(int argc, char* argv[])
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",1024,768,true);
app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13);
app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0);
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0);
@@ -74,9 +78,6 @@ int main(int argc, char* argv[])
app->m_window->setResizeCallback(MyResizeCallback);
assert(glGetError()==GL_NO_ERROR);
myArgs.GetCmdLineArgument("mp4_file",gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
@@ -84,6 +85,23 @@ int main(int argc, char* argv[])
myArgs.GetCmdLineArgument("png_file",gPngFileName);
char fileName[1024];
int textureWidth = 128;
int textureHeight = 128;
unsigned char* image=new unsigned char[textureWidth*textureHeight*4];
int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight);
int cubeIndex = app->registerCubeShape(1,1,1);
b3Vector3 pos = b3MakeVector3(0,0,0);
b3Quaternion orn(0,0,0,1);
b3Vector3 color=b3MakeVector3(1,0,0);
b3Vector3 scaling=b3MakeVector3 (1,1,1);
app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
app->m_renderer->writeTransforms();
do
{
static int frameCount = 0;
@@ -96,10 +114,33 @@ int main(int argc, char* argv[])
app->dumpNextFrameToPng(fileName);
}
assert(glGetError()==GL_NO_ERROR);
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
const int t=(y+frameCount)>>4;
unsigned char* pi=image+y*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
const int s=x>>4;
const unsigned char b=180;
unsigned char c=b+((s+(t&1))&1)*(255-b);
pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3;
}
}
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle,image);
float color[4] = {255,1,1,1};
app->m_primRenderer->drawTexturedRect(100,200,gWidth/2-50,gHeight/2-50,color,0,0,1,1,true);
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
app->m_renderer->renderScene();
app->drawGrid();
char bla[1024];
sprintf(bla,"Simple test frame %d", frameCount);

View File

@@ -0,0 +1,50 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btHashMap.h"
int main(int argc, char* argv[])
{
DummyGUIHelper noGfx;
CommonExampleOptions options(&noGfx);
CommonExampleInterface* example = StandaloneExampleCreateFunc(options);
example->initPhysics();
for (int i=0;i<1000;i++)
{
printf("Simulating step %d\n",i);
example->stepSimulation(1.f/60.f);
}
example->exitPhysics();
delete example;
return 0;
}

View File

@@ -0,0 +1,100 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btHashMap.h"
#include "../OpenGLWindow/SimpleOpenGL3App.h"
#include <stdio.h>
#include "../ExampleBrowser/OpenGLGuiHelper.h"
CommonExampleInterface* example;
b3MouseMoveCallback prevMouseMoveCallback = 0;
static void OnMouseMove( float x, float y)
{
bool handled = false;
handled = example->mouseMoveCallback(x,y);
if (!handled)
{
if (prevMouseMoveCallback)
prevMouseMoveCallback (x,y);
}
}
b3MouseButtonCallback prevMouseButtonCallback = 0;
static void OnMouseDown(int button, int state, float x, float y) {
bool handled = false;
handled = example->mouseButtonCallback(button, state, x,y);
if (!handled)
{
if (prevMouseButtonCallback )
prevMouseButtonCallback (button,state,x,y);
}
}
int main(int argc, char* argv[])
{
SimpleOpenGL3App* app = new SimpleOpenGL3App("Bullet Standalone Example",1024,768,true);
prevMouseButtonCallback = app->m_window->getMouseButtonCallback();
prevMouseMoveCallback = app->m_window->getMouseMoveCallback();
app->m_window->setMouseButtonCallback((b3MouseButtonCallback)OnMouseDown);
app->m_window->setMouseMoveCallback((b3MouseMoveCallback)OnMouseMove);
OpenGLGuiHelper gui(app,false);
CommonExampleOptions options(&gui);
example = StandaloneExampleCreateFunc(options);
example->initPhysics();
example->resetCamera();
do
{
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera(app->getUpAxis());
example->stepSimulation(1./60.);
example->renderScene();
DrawGridData dg;
dg.upAxis = app->getUpAxis();
app->drawGrid(dg);
app->swapBuffer();
} while (!app->m_window->requestedExit());
example->exitPhysics();
delete example;
delete app;
return 0;
}

View File

@@ -0,0 +1,268 @@
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2015 Google Inc. http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../CommonInterfaces/CommonExampleInterface.h"
#include "../CommonInterfaces/CommonGUIHelperInterface.h"
#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
#include "BulletCollision/CollisionShapes/btCollisionShape.h"
#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
#include "LinearMath/btTransform.h"
#include "LinearMath/btHashMap.h"
#include "../TinyRenderer/TinyRenderer.h"
#include "../OpenGLWindow/SimpleOpenGL3App.h"
#include <stdio.h>
#include "../ExampleBrowser/OpenGLGuiHelper.h"
class SW_And_OpenGLGuiHelper : public OpenGLGuiHelper
{
btHashMap<btHashInt,TinyRenderObjectData*> m_swRenderObjects;
btHashMap<btHashInt,int> m_swInstances;
int m_swWidth;
int m_swHeight;
TGAImage m_rgbColorBuffer;
b3AlignedObjectArray<float> m_depthBuffer;
int m_textureHandle;
unsigned char* m_image;
GLPrimitiveRenderer* m_primRenderer;
public:
SW_And_OpenGLGuiHelper (CommonGraphicsApp* glApp, bool useOpenGL2, int swWidth, int swHeight, GLPrimitiveRenderer* primRenderer)
:OpenGLGuiHelper(glApp,useOpenGL2),
m_swWidth(swWidth),
m_swHeight(swHeight),
m_rgbColorBuffer(swWidth,swHeight,TGAImage::RGB),
m_primRenderer(primRenderer)
{
m_depthBuffer.resize(swWidth*swHeight);
CommonRenderInterface* render = getRenderInterface();
m_image=new unsigned char[m_swWidth*m_swHeight*4];
m_textureHandle = render->registerTexture(m_image,m_swWidth,m_swHeight);
}
void clearBuffers(TGAColor& clearColor)
{
for(int y=0;y<m_swHeight;++y)
{
for(int x=0;x<m_swWidth;++x)
{
m_rgbColorBuffer.set(x,y,clearColor);
m_depthBuffer[x+y*m_swWidth] = -1e30f;
}
}
}
const TGAImage& getFrameBuffer() const
{
return m_rgbColorBuffer;
}
virtual ~SW_And_OpenGLGuiHelper()
{
for (int i=0;i<m_swRenderObjects.size();i++)
{
TinyRenderObjectData** d = m_swRenderObjects[i];
if (d && *d)
{
delete *d;
}
}
}
virtual void createCollisionObjectGraphicsObject(btCollisionObject* obj,const btVector3& color)
{
OpenGLGuiHelper::createCollisionObjectGraphicsObject(obj,color);
int colIndex = obj->getUserIndex();
int shapeIndex = obj->getCollisionShape()->getUserIndex();
if (colIndex>=0 && shapeIndex>=0)
{
m_swInstances.insert(colIndex,shapeIndex);
}
}
virtual int registerGraphicsShape(const float* vertices, int numvertices, const int* indices, int numIndices)
{
int shapeIndex = OpenGLGuiHelper::registerGraphicsShape(vertices,numvertices,indices,numIndices);
if (shapeIndex>=0)
{
TinyRenderObjectData* swObj = new TinyRenderObjectData(m_swWidth,m_swHeight,m_rgbColorBuffer,m_depthBuffer);
swObj->registerMeshShape(vertices,numvertices,indices,numIndices);
//swObj->createCube(1,1,1);//MeshShape(vertices,numvertices,indices,numIndices);
m_swRenderObjects.insert(shapeIndex,swObj);
}
return shapeIndex;
}
virtual int registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)
{
int instanceId = OpenGLGuiHelper::registerGraphicsInstance(shapeIndex,position,quaternion,color,scaling);
return instanceId ;
}
virtual void createCollisionShapeGraphicsObject(btCollisionShape* collisionShape)
{
OpenGLGuiHelper::createCollisionShapeGraphicsObject(collisionShape);
}
virtual void syncPhysicsToGraphics(const btDiscreteDynamicsWorld* rbWorld)
{
OpenGLGuiHelper::syncPhysicsToGraphics(rbWorld);
}
virtual void render(const btDiscreteDynamicsWorld* rbWorld)
{
OpenGLGuiHelper::render(rbWorld);
//clear the color buffer
TGAColor clearColor;
clearColor.bgra[0] = 255;
clearColor.bgra[1] = 255;
clearColor.bgra[2] = 255;
clearColor.bgra[3] = 255;
clearBuffers(clearColor);
ATTRIBUTE_ALIGNED16(float modelMat[16]);
ATTRIBUTE_ALIGNED16(float viewMat[16]);
CommonRenderInterface* render = getRenderInterface();
render->getActiveCamera()->getCameraViewMatrix(viewMat);
for (int i=0;i<rbWorld->getNumCollisionObjects();i++)
{
btCollisionObject* colObj = rbWorld->getCollisionObjectArray()[i];
int colObjIndex = colObj->getUserIndex();
int shapeIndex = colObj->getCollisionShape()->getUserIndex();
if (colObjIndex>=0 && shapeIndex>=0)
{
TinyRenderObjectData* renderObj = 0;
int* cptr = m_swInstances[colObjIndex];
if (cptr)
{
int c = *cptr;
TinyRenderObjectData** sptr = m_swRenderObjects[c];
if (sptr)
{
renderObj = *sptr;
}
}
//sync the object transform
const btTransform& tr = colObj->getWorldTransform();
tr.getOpenGLMatrix(modelMat);
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
renderObj->m_modelMatrix[i][j] = modelMat[i+4*j];
renderObj->m_viewMatrix[i][j] = viewMat[i+4*j];
}
}
TinyRenderer::renderObject(*renderObj);
}
}
for(int y=0;y<m_swHeight;++y)
{
unsigned char* pi=m_image+(y)*m_swWidth*3;
for(int x=0;x<m_swWidth;++x)
{
const TGAColor& color = getFrameBuffer().get(x,y);
pi[0] = color.bgra[2];
pi[1] = color.bgra[1];
pi[2] = color.bgra[0];
pi+=3;
}
}
render->activateTexture(m_textureHandle);
render->updateTexture(m_textureHandle,m_image);
static int counter=0;
counter++;
if (counter>10)
{
counter=0;
getFrameBuffer().write_tga_file("/Users/erwincoumans/develop/bullet3/framebuf.tga",true);
}
float color[4] = {1,1,1,1};
m_primRenderer->drawTexturedRect(0,0,m_swWidth, m_swHeight,color,0,0,1,1,true);
}
virtual void autogenerateGraphicsObjects(btDiscreteDynamicsWorld* rbWorld)
{
OpenGLGuiHelper::autogenerateGraphicsObjects(rbWorld);
}
};
int main(int argc, char* argv[])
{
SimpleOpenGL3App* app = new SimpleOpenGL3App("Standalone Example (Software Renderer, TinyRenderer)",1024,768,true);
int textureWidth = 640;
int textureHeight = 480;
SW_And_OpenGLGuiHelper gui(app,false,textureWidth,textureHeight,app->m_primRenderer);
CommonExampleOptions options(&gui);
CommonExampleInterface* example = StandaloneExampleCreateFunc(options);
example->initPhysics();
example->resetCamera();
do
{
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera(app->getUpAxis());
example->stepSimulation(1./60.);
example->renderScene();
DrawGridData dg;
dg.upAxis = app->getUpAxis();
app->drawGrid(dg);
app->swapBuffer();
} while (!app->m_window->requestedExit());
example->exitPhysics();
delete example;
delete app;
return 0;
}

View File

@@ -0,0 +1,13 @@
Tiny Renderer, https://github.com/ssloy/tinyrenderer
Copyright Dmitry V. Sokolov
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@@ -0,0 +1,212 @@
#include "TinyRenderer.h"
#include <vector>
#include <limits>
#include <iostream>
#include "tgaimage.h"
#include "model.h"
#include "geometry.h"
#include "our_gl.h"
#include "../Utils/b3ResourcePath.h"
#include "Bullet3Common/b3MinMax.h"
#include "../OpenGLWindow/ShapeData.h"
Vec3f light_dir_world(1,1,1);
struct Shader : public IShader {
Model* m_model;
Vec3f m_light_dir_local;
Matrix& m_modelView;
Matrix& m_projectionMatrix;
mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader
mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS
mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS
mat<3,3,float> ndc_tri; // triangle in normalized device coordinates
Shader(Model* model, Vec3f light_dir_local, Matrix& modelView, Matrix& projectionMatrix)
:m_model(model),
m_light_dir_local(light_dir_local),
m_modelView(modelView),
m_projectionMatrix(projectionMatrix)
{
}
virtual Vec4f vertex(int iface, int nthvert) {
Vec2f uv = m_model->uv(iface, nthvert);
//printf("uv = %f,%f\n", uv.x,uv.y);
varying_uv.set_col(nthvert, uv);
varying_nrm.set_col(nthvert, proj<3>((m_projectionMatrix*m_modelView).invert_transpose()*embed<4>(m_model->normal(iface, nthvert), 0.f)));
Vec4f gl_Vertex = m_projectionMatrix*m_modelView*embed<4>(m_model->vert(iface, nthvert));
varying_tri.set_col(nthvert, gl_Vertex);
ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3]));
return gl_Vertex;
}
virtual bool fragment(Vec3f bar, TGAColor &color) {
Vec3f bn = (varying_nrm*bar).normalize();
Vec2f uv = varying_uv*bar;
mat<3,3,float> A;
A[0] = ndc_tri.col(1) - ndc_tri.col(0);
A[1] = ndc_tri.col(2) - ndc_tri.col(0);
A[2] = bn;
mat<3,3,float> AI = A.invert();
Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0);
Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0);
mat<3,3,float> B;
B.set_col(0, i.normalize());
B.set_col(1, j.normalize());
B.set_col(2, bn);
Vec3f n = (B*m_model->normal(uv)).normalize();
float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.3f),1.f);
//float diff = b3Max(0.f, n*m_light_dir_local);
color = m_model->diffuse(uv)*diff;
return false;
}
};
TinyRenderObjectData::TinyRenderObjectData(int width, int height,TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>&depthBuffer)
:m_width(width),
m_height(height),
m_rgbColorBuffer(rgbColorBuffer),
m_depthBuffer(depthBuffer),
m_model(0),
m_userData(0),
m_userIndex(-1)
{
Vec3f eye(1,1,3);
Vec3f center(0,0,0);
Vec3f up(0,1,0);
m_modelMatrix = Matrix::identity();
m_viewMatrix = lookat(eye, center, up);
m_viewportMatrix = viewport(width/8, height/8, width*3/4, height*3/4);
m_projectionMatrix = projection(-1.f/(eye-center).norm());
}
void TinyRenderObjectData::loadModel(const char* fileName)
{
//todo(erwincoumans) move the file loading out of here
char relativeFileName[1024];
if (!b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024))
{
printf("Cannot find file %s\n", fileName);
} else
{
m_model = new Model(relativeFileName);
}
}
void TinyRenderObjectData::registerMeshShape(const float* vertices, int numVertices,const int* indices, int numIndices)
{
if (0==m_model)
{
m_model = new Model();
char relativeFileName[1024];
if (b3ResourcePath::findResourcePath("floor_diffuse.tga", relativeFileName, 1024))
{
m_model->loadDiffuseTexture(relativeFileName);
}
for (int i=0;i<numVertices;i++)
{
m_model->addVertex(vertices[i*9],
vertices[i*9+1],
vertices[i*9+2],
vertices[i*9+4],
vertices[i*9+5],
vertices[i*9+6],
vertices[i*9+7],
vertices[i*9+8]);
}
for (int i=0;i<numIndices;i+=3)
{
m_model->addTriangle(indices[i],indices[i],indices[i],
indices[i+1],indices[i+1],indices[i+1],
indices[i+2],indices[i+2],indices[i+2]);
}
}
}
void TinyRenderObjectData::createCube(float halfExtentsX,float halfExtentsY,float halfExtentsZ)
{
m_model = new Model();
char relativeFileName[1024];
if (b3ResourcePath::findResourcePath("floor_diffuse.tga", relativeFileName, 1024))
{
m_model->loadDiffuseTexture(relativeFileName);
}
int strideInBytes = 9*sizeof(float);
int numVertices = sizeof(cube_vertices_textured)/strideInBytes;
int numIndices = sizeof(cube_indices)/sizeof(int);
for (int i=0;i<numVertices;i++)
{
m_model->addVertex(halfExtentsX*cube_vertices_textured[i*9],
halfExtentsY*cube_vertices_textured[i*9+1],
halfExtentsY*cube_vertices_textured[i*9+2],
cube_vertices_textured[i*9+4],
cube_vertices_textured[i*9+5],
cube_vertices_textured[i*9+6],
cube_vertices_textured[i*9+7],
cube_vertices_textured[i*9+8]);
}
for (int i=0;i<numIndices;i+=3)
{
m_model->addTriangle(cube_indices[i],cube_indices[i],cube_indices[i],
cube_indices[i+1],cube_indices[i+1],cube_indices[i+1],
cube_indices[i+2],cube_indices[i+2],cube_indices[i+2]);
}
}
TinyRenderObjectData::~TinyRenderObjectData()
{
delete m_model;
}
void TinyRenderer::renderObject(TinyRenderObjectData& renderData)
{
Model* model = renderData.m_model;
if (0==model)
return;
b3AlignedObjectArray<float>& zbuffer = renderData.m_depthBuffer;
TGAImage& frame = renderData.m_rgbColorBuffer;
Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*renderData.m_modelMatrix*embed<4>(light_dir_world, 0.f))).normalize();
{
Matrix modelViewMatrix = renderData.m_viewMatrix*renderData.m_modelMatrix;
Shader shader(model, light_dir_local, modelViewMatrix, renderData.m_projectionMatrix);
for (int i=0; i<model->nfaces(); i++) {
for (int j=0; j<3; j++) {
shader.vertex(i, j);
}
triangle(shader.varying_tri, shader, frame, &zbuffer[0], renderData.m_viewportMatrix);
}
}
}

View File

@@ -0,0 +1,44 @@
#ifndef TINY_RENDERER_H
#define TINY_RENDERER_H
#include "geometry.h"
#include "Bullet3Common/b3AlignedObjectArray.h"
#include "tgaimage.h"
struct TinyRenderObjectData
{
//Camera
Matrix m_viewMatrix;
Matrix m_projectionMatrix;
Matrix m_viewportMatrix;
//Model (vertices, indices, textures, shader)
Matrix m_modelMatrix;
class Model* m_model;
//class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader
//Output
int m_width;
int m_height;
TGAImage& m_rgbColorBuffer;
b3AlignedObjectArray<float>& m_depthBuffer;
TinyRenderObjectData(int width, int height,TGAImage& rgbColorBuffer,b3AlignedObjectArray<float>& depthBuffer);
virtual ~TinyRenderObjectData();
void loadModel(const char* fileName);
void createCube(float HalfExtentsX,float HalfExtentsY,float HalfExtentsZ);
void registerMeshShape(const float* vertices, int numVertices,const int* indices, int numIndices);
void* m_userData;
int m_userIndex;
};
class TinyRenderer
{
public:
static void renderObject(TinyRenderObjectData& renderData);
};
#endif // TINY_RENDERER_Hbla

View File

@@ -0,0 +1,7 @@
#include "geometry.h"
template <> template <> vec<3,int> ::vec(const vec<3,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)),z(int(v.z+.5f)) {}
template <> template <> vec<3,float>::vec(const vec<3,int> &v) : x(v.x),y(v.y),z(v.z) {}
template <> template <> vec<2,int> ::vec(const vec<2,float> &v) : x(int(v.x+.5f)),y(int(v.y+.5f)) {}
template <> template <> vec<2,float>::vec(const vec<2,int> &v) : x(v.x),y(v.y) {}

View File

@@ -0,0 +1,222 @@
#ifndef __GEOMETRY_H__
#define __GEOMETRY_H__
#include <cmath>
#include <cassert>
#include <stdlib.h>
template<size_t DimCols,size_t DimRows,typename T> class mat;
template <size_t DIM, typename T> struct vec {
vec() { for (size_t i=DIM; i--; data_[i] = T()); }
T& operator[](const size_t i) { assert(i<DIM); return data_[i]; }
const T& operator[](const size_t i) const { assert(i<DIM); return data_[i]; }
private:
T data_[DIM];
};
/////////////////////////////////////////////////////////////////////////////////
template <typename T> struct vec<2,T> {
vec() : x(T()), y(T()) {}
vec(T X, T Y) : x(X), y(Y) {}
template <class U> vec<2,T>(const vec<2,U> &v);
T& operator[](const size_t i) { assert(i<2); return i<=0 ? x : y; }
const T& operator[](const size_t i) const { assert(i<2); return i<=0 ? x : y; }
T x,y;
};
/////////////////////////////////////////////////////////////////////////////////
template <typename T> struct vec<3,T> {
vec() : x(T()), y(T()), z(T()) {}
vec(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
template <class U> vec<3,T>(const vec<3,U> &v);
T& operator[](const size_t i) { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
const T& operator[](const size_t i) const { assert(i<3); return i<=0 ? x : (1==i ? y : z); }
float norm() { return std::sqrt(x*x+y*y+z*z); }
vec<3,T> & normalize(T l=1) { *this = (*this)*(l/norm()); return *this; }
T x,y,z;
};
/////////////////////////////////////////////////////////////////////////////////
template<size_t DIM,typename T> T operator*(const vec<DIM,T>& lhs, const vec<DIM,T>& rhs) {
T ret = T();
for (size_t i=DIM; i--; ret+=lhs[i]*rhs[i]);
return ret;
}
template<size_t DIM,typename T>vec<DIM,T> operator+(vec<DIM,T> lhs, const vec<DIM,T>& rhs) {
for (size_t i=DIM; i--; lhs[i]+=rhs[i]);
return lhs;
}
template<size_t DIM,typename T>vec<DIM,T> operator-(vec<DIM,T> lhs, const vec<DIM,T>& rhs) {
for (size_t i=DIM; i--; lhs[i]-=rhs[i]);
return lhs;
}
template<size_t DIM,typename T,typename U> vec<DIM,T> operator*(vec<DIM,T> lhs, const U& rhs) {
for (size_t i=DIM; i--; lhs[i]*=rhs);
return lhs;
}
template<size_t DIM,typename T,typename U> vec<DIM,T> operator/(vec<DIM,T> lhs, const U& rhs) {
for (size_t i=DIM; i--; lhs[i]/=rhs);
return lhs;
}
template<size_t LEN,size_t DIM,typename T> vec<LEN,T> embed(const vec<DIM,T> &v, T fill=1) {
vec<LEN,T> ret;
for (size_t i=LEN; i--; ret[i]=(i<DIM?v[i]:fill));
return ret;
}
template<size_t LEN,size_t DIM, typename T> vec<LEN,T> proj(const vec<DIM,T> &v) {
vec<LEN,T> ret;
for (size_t i=LEN; i--; ret[i]=v[i]);
return ret;
}
template <typename T> vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) {
return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x);
}
#if 0
template <size_t DIM, typename T> std::ostream& operator<<(std::ostream& out, vec<DIM,T>& v) {
for(unsigned int i=0; i<DIM; i++) {
out << v[i] << " " ;
}
return out ;
}
#endif
/////////////////////////////////////////////////////////////////////////////////
template<size_t DIM,typename T> struct dt {
static T det(const mat<DIM,DIM,T>& src) {
T ret=0;
for (size_t i=DIM; i--; ret += src[0][i]*src.cofactor(0,i));
return ret;
}
};
template<typename T> struct dt<1,T> {
static T det(const mat<1,1,T>& src) {
return src[0][0];
}
};
/////////////////////////////////////////////////////////////////////////////////
template<size_t DimRows,size_t DimCols,typename T> class mat {
vec<DimCols,T> rows[DimRows];
public:
mat() {}
vec<DimCols,T>& operator[] (const size_t idx) {
assert(idx<DimRows);
return rows[idx];
}
const vec<DimCols,T>& operator[] (const size_t idx) const {
assert(idx<DimRows);
return rows[idx];
}
vec<DimRows,T> col(const size_t idx) const {
assert(idx<DimCols);
vec<DimRows,T> ret;
for (size_t i=DimRows; i--; ret[i]=rows[i][idx]);
return ret;
}
void set_col(size_t idx, vec<DimRows,T> v) {
assert(idx<DimCols);
for (size_t i=DimRows; i--; rows[i][idx]=v[i]);
}
static mat<DimRows,DimCols,T> identity() {
mat<DimRows,DimCols,T> ret;
for (size_t i=DimRows; i--; )
for (size_t j=DimCols;j--; ret[i][j]=(i==j));
return ret;
}
T det() const {
return dt<DimCols,T>::det(*this);
}
mat<DimRows-1,DimCols-1,T> get_minor(size_t row, size_t col) const {
mat<DimRows-1,DimCols-1,T> ret;
for (size_t i=DimRows-1; i--; )
for (size_t j=DimCols-1;j--; ret[i][j]=rows[i<row?i:i+1][j<col?j:j+1]);
return ret;
}
T cofactor(size_t row, size_t col) const {
return get_minor(row,col).det()*((row+col)%2 ? -1 : 1);
}
mat<DimRows,DimCols,T> adjugate() const {
mat<DimRows,DimCols,T> ret;
for (size_t i=DimRows; i--; )
for (size_t j=DimCols; j--; ret[i][j]=cofactor(i,j));
return ret;
}
mat<DimRows,DimCols,T> invert_transpose() {
mat<DimRows,DimCols,T> ret = adjugate();
T tmp = ret[0]*rows[0];
return ret/tmp;
}
mat<DimRows,DimCols,T> invert() {
return invert_transpose().transpose();
}
mat<DimCols,DimRows,T> transpose() {
mat<DimCols,DimRows,T> ret;
for (size_t i=DimCols; i--; ret[i]=this->col(i));
return ret;
}
};
/////////////////////////////////////////////////////////////////////////////////
template<size_t DimRows,size_t DimCols,typename T> vec<DimRows,T> operator*(const mat<DimRows,DimCols,T>& lhs, const vec<DimCols,T>& rhs) {
vec<DimRows,T> ret;
for (size_t i=DimRows; i--; ret[i]=lhs[i]*rhs);
return ret;
}
template<size_t R1,size_t C1,size_t C2,typename T>mat<R1,C2,T> operator*(const mat<R1,C1,T>& lhs, const mat<C1,C2,T>& rhs) {
mat<R1,C2,T> result;
for (size_t i=R1; i--; )
for (size_t j=C2; j--; result[i][j]=lhs[i]*rhs.col(j));
return result;
}
template<size_t DimRows,size_t DimCols,typename T>mat<DimCols,DimRows,T> operator/(mat<DimRows,DimCols,T> lhs, const T& rhs) {
for (size_t i=DimRows; i--; lhs[i]=lhs[i]/rhs);
return lhs;
}
#if 0
template <size_t DimRows,size_t DimCols,class T> std::ostream& operator<<(std::ostream& out, mat<DimRows,DimCols,T>& m) {
for (size_t i=0; i<DimRows; i++) out << m[i] << std::endl;
return out;
}
#endif
/////////////////////////////////////////////////////////////////////////////////
typedef vec<2, float> Vec2f;
typedef vec<2, int> Vec2i;
typedef vec<3, float> Vec3f;
typedef vec<3, int> Vec3i;
typedef vec<4, float> Vec4f;
typedef mat<4,4,float> Matrix;
#endif //__GEOMETRY_H__

View File

@@ -0,0 +1,237 @@
#include "OpenGLWindow/SimpleOpenGL3App.h"
#include "Bullet3Common/b3Quaternion.h"
#include "Bullet3Common/b3CommandLineArgs.h"
#include "Bullet3Common/b3Transform.h"
#include "assert.h"
#include <stdio.h>
char* gVideoFileName = 0;
char* gPngFileName = 0;
static b3WheelCallback sOldWheelCB = 0;
static b3ResizeCallback sOldResizeCB = 0;
static b3MouseMoveCallback sOldMouseMoveCB = 0;
static b3MouseButtonCallback sOldMouseButtonCB = 0;
static b3KeyboardCallback sOldKeyboardCB = 0;
//static b3RenderCallback sOldRenderCB = 0;
float gWidth = 0 ;
float gHeight = 0;
void MyWheelCallback(float deltax, float deltay)
{
if (sOldWheelCB)
sOldWheelCB(deltax,deltay);
}
void MyResizeCallback( float width, float height)
{
gWidth = width;
gHeight = height;
if (sOldResizeCB)
sOldResizeCB(width,height);
}
void MyMouseMoveCallback( float x, float y)
{
printf("Mouse Move: %f, %f\n", x,y);
if (sOldMouseMoveCB)
sOldMouseMoveCB(x,y);
}
void MyMouseButtonCallback(int button, int state, float x, float y)
{
if (sOldMouseButtonCB)
sOldMouseButtonCB(button,state,x,y);
}
void MyKeyboardCallback(int keycode, int state)
{
//keycodes are in examples/CommonInterfaces/CommonWindowInterface.h
//for example B3G_ESCAPE for escape key
//state == 1 for pressed, state == 0 for released.
// use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys
printf("MyKeyboardCallback received key:%c in state %d\n",keycode,state);
if (sOldKeyboardCB)
sOldKeyboardCB(keycode,state);
}
#include "TinyRenderer.h"
int main(int argc, char* argv[])
{
b3CommandLineArgs myArgs(argc,argv);
SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",640,480,true);
app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13);
app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0);
app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0);
sOldKeyboardCB = app->m_window->getKeyboardCallback();
app->m_window->setKeyboardCallback(MyKeyboardCallback);
sOldMouseMoveCB = app->m_window->getMouseMoveCallback();
app->m_window->setMouseMoveCallback(MyMouseMoveCallback);
sOldMouseButtonCB = app->m_window->getMouseButtonCallback();
app->m_window->setMouseButtonCallback(MyMouseButtonCallback);
sOldWheelCB = app->m_window->getWheelCallback();
app->m_window->setWheelCallback(MyWheelCallback);
sOldResizeCB = app->m_window->getResizeCallback();
app->m_window->setResizeCallback(MyResizeCallback);
int textureWidth = gWidth;
int textureHeight = gHeight;
TGAImage rgbColorBuffer(gWidth,gHeight,TGAImage::RGB);
b3AlignedObjectArray<float> depthBuffer;
depthBuffer.resize(gWidth*gHeight);
TinyRenderObjectData renderData(textureWidth, textureHeight,rgbColorBuffer,depthBuffer);//, "african_head/african_head.obj");//floor.obj");
//renderData.loadModel("african_head/african_head.obj");
//renderData.loadModel("floor.obj");
renderData.createCube(1,1,1);
myArgs.GetCmdLineArgument("mp4_file",gVideoFileName);
if (gVideoFileName)
app->dumpFramesToVideo(gVideoFileName);
myArgs.GetCmdLineArgument("png_file",gPngFileName);
char fileName[1024];
unsigned char* image=new unsigned char[textureWidth*textureHeight*4];
int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight);
int cubeIndex = app->registerCubeShape(1,1,1);
b3Vector3 pos = b3MakeVector3(0,0,0);
b3Quaternion orn(0,0,0,1);
b3Vector3 color=b3MakeVector3(1,0,0);
b3Vector3 scaling=b3MakeVector3 (1,1,1);
app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling);
app->m_renderer->writeTransforms();
do
{
static int frameCount = 0;
frameCount++;
if (gPngFileName)
{
printf("gPngFileName=%s\n",gPngFileName);
sprintf(fileName,"%s%d.png",gPngFileName,frameCount++);
app->dumpNextFrameToPng(fileName);
}
app->m_instancingRenderer->init();
app->m_instancingRenderer->updateCamera();
///clear the color and z (depth) buffer
for(int y=0;y<textureHeight;++y)
{
unsigned char* pi=image+(y)*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color;
color.bgra[0] = 255;
color.bgra[1] = 255;
color.bgra[2] = 255;
color.bgra[3] = 255;
renderData.m_rgbColorBuffer.set(x,y,color);
renderData.m_depthBuffer[x+y*textureWidth] = -1e30f;
}
}
float projMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat);
float viewMat[16];
app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat);
B3_ATTRIBUTE_ALIGNED16(float modelMat[16]);
//sync the object transform
b3Transform tr;
tr.setIdentity();
static float posUp = 0.f;
// posUp += 0.001;
b3Vector3 org = b3MakeVector3(0,posUp,0);
tr.setOrigin(org);
tr.getOpenGLMatrix(modelMat);
for (int i=0;i<4;i++)
{
for (int j=0;j<4;j++)
{
renderData.m_viewMatrix[i][j] = viewMat[i+4*j];
renderData.m_modelMatrix[i][j] = modelMat[i+4*j];
}
}
//render the object
TinyRenderer::renderObject(renderData);
#if 1
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
unsigned char* pi=image+(y)*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x,y);
pi[0] = color.bgra[2];
pi[1] = color.bgra[1];
pi[2] = color.bgra[0];
pi[3] = 255;
pi+=3;
}
}
#else
//update the texels of the texture using a simple pattern, animated using frame index
for(int y=0;y<textureHeight;++y)
{
const int t=(y+frameCount)>>4;
unsigned char* pi=image+y*textureWidth*3;
for(int x=0;x<textureWidth;++x)
{
TGAColor color = renderData.m_rgbColorBuffer.get(x,y);
const int s=x>>4;
const unsigned char b=180;
unsigned char c=b+((s+(t&1))&1)*(255-b);
pi[0]=pi[1]=pi[2]=pi[3]=c;
pi+=3;
}
}
#endif
app->m_renderer->activateTexture(textureHandle);
app->m_renderer->updateTexture(textureHandle,image);
float color[4] = {1,1,1,1};
app->m_primRenderer->drawTexturedRect(0,0,gWidth/3,gHeight/3,color,0,0,1,1,true);
app->m_renderer->renderScene();
app->drawGrid();
char bla[1024];
sprintf(bla,"Simple test frame %d", frameCount);
app->drawText(bla,10,10);
app->swapBuffer();
} while (!app->m_window->requestedExit());
delete app;
return 0;
}

View File

@@ -0,0 +1,136 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include "model.h"
Model::Model(const char *filename) : verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_() {
std::ifstream in;
in.open (filename, std::ifstream::in);
if (in.fail()) return;
std::string line;
while (!in.eof()) {
std::getline(in, line);
std::istringstream iss(line.c_str());
char trash;
if (!line.compare(0, 2, "v ")) {
iss >> trash;
Vec3f v;
for (int i=0;i<3;i++) iss >> v[i];
verts_.push_back(v);
} else if (!line.compare(0, 3, "vn ")) {
iss >> trash >> trash;
Vec3f n;
for (int i=0;i<3;i++) iss >> n[i];
norms_.push_back(n);
} else if (!line.compare(0, 3, "vt ")) {
iss >> trash >> trash;
Vec2f uv;
for (int i=0;i<2;i++) iss >> uv[i];
uv_.push_back(uv);
} else if (!line.compare(0, 2, "f ")) {
std::vector<Vec3i> f;
Vec3i tmp;
iss >> trash;
while (iss >> tmp[0] >> trash >> tmp[1] >> trash >> tmp[2]) {
for (int i=0; i<3; i++) tmp[i]--; // in wavefront obj all indices start at 1, not zero
f.push_back(tmp);
}
faces_.push_back(f);
}
}
std::cerr << "# v# " << verts_.size() << " f# " << faces_.size() << " vt# " << uv_.size() << " vn# " << norms_.size() << std::endl;
load_texture(filename, "_diffuse.tga", diffusemap_);
load_texture(filename, "_nm_tangent.tga", normalmap_);
load_texture(filename, "_spec.tga", specularmap_);
}
Model::Model():verts_(), faces_(), norms_(), uv_(), diffusemap_(), normalmap_(), specularmap_()
{
}
void Model::loadDiffuseTexture(const char* relativeFileName)
{
diffusemap_.read_tga_file(relativeFileName);
}
void Model::addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v)
{
verts_.push_back(Vec3f(x,y,z));
norms_.push_back(Vec3f(normalX,normalY,normalZ));
uv_.push_back(Vec2f(u,v));
}
void Model::addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2)
{
std::vector<Vec3i> f;
f.push_back(Vec3i(vertexposIndex0, normalIndex0, uvIndex0));
f.push_back(Vec3i(vertexposIndex1, normalIndex1, uvIndex1));
f.push_back(Vec3i(vertexposIndex2, normalIndex2, uvIndex2));
faces_.push_back(f);
}
Model::~Model() {}
int Model::nverts() {
return (int)verts_.size();
}
int Model::nfaces() {
return (int)faces_.size();
}
std::vector<int> Model::face(int idx) {
std::vector<int> face;
for (int i=0; i<(int)faces_[idx].size(); i++) face.push_back(faces_[idx][i][0]);
return face;
}
Vec3f Model::vert(int i) {
return verts_[i];
}
Vec3f Model::vert(int iface, int nthvert) {
return verts_[faces_[iface][nthvert][0]];
}
void Model::load_texture(std::string filename, const char *suffix, TGAImage &img) {
std::string texfile(filename);
size_t dot = texfile.find_last_of(".");
if (dot!=std::string::npos) {
texfile = texfile.substr(0,dot) + std::string(suffix);
std::cerr << "texture file " << texfile << " loading " << (img.read_tga_file(texfile.c_str()) ? "ok" : "failed") << std::endl;
img.flip_vertically();
}
}
TGAColor Model::diffuse(Vec2f uvf) {
Vec2i uv(uvf[0]*diffusemap_.get_width(), uvf[1]*diffusemap_.get_height());
return diffusemap_.get(uv[0], uv[1]);
}
Vec3f Model::normal(Vec2f uvf) {
Vec2i uv(uvf[0]*normalmap_.get_width(), uvf[1]*normalmap_.get_height());
TGAColor c = normalmap_.get(uv[0], uv[1]);
Vec3f res;
for (int i=0; i<3; i++)
res[2-i] = (float)c[i]/255.f*2.f - 1.f;
return res;
}
Vec2f Model::uv(int iface, int nthvert) {
return uv_[faces_[iface][nthvert][1]];
}
float Model::specular(Vec2f uvf) {
Vec2i uv(uvf[0]*specularmap_.get_width(), uvf[1]*specularmap_.get_height());
return specularmap_.get(uv[0], uv[1])[0]/1.f;
}
Vec3f Model::normal(int iface, int nthvert) {
int idx = faces_[iface][nthvert][2];
return norms_[idx].normalize();
}

View File

@@ -0,0 +1,40 @@
#ifndef __MODEL_H__
#define __MODEL_H__
#include <vector>
#include <string>
#include "geometry.h"
#include "tgaimage.h"
class Model {
private:
std::vector<Vec3f> verts_;
std::vector<std::vector<Vec3i> > faces_; // attention, this Vec3i means vertex/uv/normal
std::vector<Vec3f> norms_;
std::vector<Vec2f> uv_;
TGAImage diffusemap_;
TGAImage normalmap_;
TGAImage specularmap_;
void load_texture(std::string filename, const char *suffix, TGAImage &img);
public:
Model(const char *filename);
Model();
void loadDiffuseTexture(const char* relativeFileName);
void addVertex(float x,float y,float z, float normalX, float normalY, float normalZ, float u, float v);
void addTriangle(int vertexposIndex0, int normalIndex0, int uvIndex0,
int vertexposIndex1, int normalIndex1, int uvIndex1,
int vertexposIndex2, int normalIndex2, int uvIndex2);
~Model();
int nverts();
int nfaces();
Vec3f normal(int iface, int nthvert);
Vec3f normal(Vec2f uv);
Vec3f vert(int i);
Vec3f vert(int iface, int nthvert);
Vec2f uv(int iface, int nthvert);
TGAColor diffuse(Vec2f uv);
float specular(Vec2f uv);
std::vector<int> face(int idx);
};
#endif //__MODEL_H__

View File

@@ -0,0 +1,106 @@
#include <cmath>
#include <limits>
#include <cstdlib>
#include "our_gl.h"
#include "Bullet3Common/b3MinMax.h"
IShader::~IShader() {}
Matrix viewport(int x, int y, int w, int h)
{
Matrix Viewport;
Viewport = Matrix::identity();
Viewport[0][3] = x+w/2.f;
Viewport[1][3] = y+h/2.f;
Viewport[2][3] = 1.f;
Viewport[0][0] = w/2.f;
Viewport[1][1] = h/2.f;
Viewport[2][2] = 0;
return Viewport;
}
Matrix projection(float coeff) {
Matrix Projection;
Projection = Matrix::identity();
Projection[3][2] = coeff;
return Projection;
}
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) {
Vec3f z = (eye-center).normalize();
Vec3f x = cross(up,z).normalize();
Vec3f y = cross(z,x).normalize();
Matrix Minv = Matrix::identity();
Matrix Tr = Matrix::identity();
for (int i=0; i<3; i++) {
Minv[0][i] = x[i];
Minv[1][i] = y[i];
Minv[2][i] = z[i];
Tr[i][3] = -center[i];
}
Matrix ModelView;
ModelView = Minv*Tr;
return ModelView;
}
Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) {
Vec3f s[2];
for (int i=2; i--; ) {
s[i][0] = C[i]-A[i];
s[i][1] = B[i]-A[i];
s[i][2] = A[i]-P[i];
}
Vec3f u = cross(s[0], s[1]);
if (std::abs(u[2])>1e-2) // dont forget that u[2] is integer. If it is zero then triangle ABC is degenerate
return Vec3f(1.f-(u.x+u.y)/u.z, u.y/u.z, u.x/u.z);
return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator
}
void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix) {
mat<3,4,float> pts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points
//we don't clip triangles that cross the near plane, just discard them instead of showing artifacts
if (pts[0][3]<0 || pts[1][3] <0 || pts[2][3] <0)
return;
mat<3,2,float> pts2;
for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]);
Vec2f bboxmin( std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
Vec2f bboxmax(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
Vec2f clamp(image.get_width()-1, image.get_height()-1);
for (int i=0; i<3; i++) {
for (int j=0; j<2; j++) {
bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j]));
bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j]));
}
}
Vec2i P;
TGAColor color;
for (P.x=bboxmin.x; P.x<=bboxmax.x; P.x++) {
for (P.y=bboxmin.y; P.y<=bboxmax.y; P.y++) {
Vec3f bc_screen = barycentric(pts2[0], pts2[1], pts2[2], P);
Vec3f bc_clip = Vec3f(bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]);
bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z);
float frag_depth = clipc[2]*bc_clip;
if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 || zbuffer[P.x+P.y*image.get_width()]>frag_depth) continue;
bool discard = shader.fragment(bc_clip, color);
if (!discard) {
zbuffer[P.x+P.y*image.get_width()] = frag_depth;
image.set(P.x, P.y, color);
}
}
}
}

View File

@@ -0,0 +1,22 @@
#ifndef __OUR_GL_H__
#define __OUR_GL_H__
#include "tgaimage.h"
#include "geometry.h"
Matrix viewport(int x, int y, int w, int h);
Matrix projection(float coeff=0.f); // coeff = -1/c
Matrix lookat(Vec3f eye, Vec3f center, Vec3f up);
struct IShader {
virtual ~IShader();
virtual Vec4f vertex(int iface, int nthvert) = 0;
virtual bool fragment(Vec3f bar, TGAColor &color) = 0;
};
//void triangle(Vec4f *pts, IShader &shader, TGAImage &image, float *zbuffer);
void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix);
#endif //__OUR_GL_H__

View File

@@ -0,0 +1,29 @@
project "App_TinyRenderer"
language "C++"
kind "ConsoleApp"
includedirs {
".",
"../../src",
".."
}
links{ "OpenGL_Window","Bullet3Common"}
initOpenGL()
initGlew()
files {
"*.cpp",
"*.h",
"../Utils/b3ResourcePath.cpp"
}
if os.is("Linux") then initX11() end
if os.is("MacOSX") then
links{"Cocoa.framework"}
end

View File

@@ -0,0 +1,356 @@
#include <iostream>
#include <fstream>
#include <string.h>
#include <time.h>
#include <math.h>
#include "tgaimage.h"
TGAImage::TGAImage() : data(NULL), width(0), height(0), bytespp(0) {}
TGAImage::TGAImage(int w, int h, int bpp) : data(NULL), width(w), height(h), bytespp(bpp) {
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
memset(data, 0, nbytes);
}
TGAImage::TGAImage(const TGAImage &img) : data(NULL), width(img.width), height(img.height), bytespp(img.bytespp) {
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
memcpy(data, img.data, nbytes);
}
TGAImage::~TGAImage() {
if (data) delete [] data;
}
TGAImage & TGAImage::operator =(const TGAImage &img) {
if (this != &img) {
if (data) delete [] data;
width = img.width;
height = img.height;
bytespp = img.bytespp;
unsigned long nbytes = width*height*bytespp;
data = new unsigned char[nbytes];
memcpy(data, img.data, nbytes);
}
return *this;
}
bool TGAImage::read_tga_file(const char *filename) {
if (data) delete [] data;
data = NULL;
std::ifstream in;
in.open (filename, std::ios::binary);
if (!in.is_open()) {
std::cerr << "can't open file " << filename << "\n";
in.close();
return false;
}
TGA_Header header;
in.read((char *)&header, sizeof(header));
if (!in.good()) {
in.close();
std::cerr << "an error occured while reading the header\n";
return false;
}
width = header.width;
height = header.height;
bytespp = header.bitsperpixel>>3;
if (width<=0 || height<=0 || (bytespp!=GRAYSCALE && bytespp!=RGB && bytespp!=RGBA)) {
in.close();
std::cerr << "bad bpp (or width/height) value\n";
return false;
}
unsigned long nbytes = bytespp*width*height;
data = new unsigned char[nbytes];
if (3==header.datatypecode || 2==header.datatypecode) {
in.read((char *)data, nbytes);
if (!in.good()) {
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
} else if (10==header.datatypecode||11==header.datatypecode) {
if (!load_rle_data(in)) {
in.close();
std::cerr << "an error occured while reading the data\n";
return false;
}
} else {
in.close();
std::cerr << "unknown file format " << (int)header.datatypecode << "\n";
return false;
}
if (!(header.imagedescriptor & 0x20)) {
flip_vertically();
}
if (header.imagedescriptor & 0x10) {
flip_horizontally();
}
std::cerr << width << "x" << height << "/" << bytespp*8 << "\n";
in.close();
return true;
}
bool TGAImage::load_rle_data(std::ifstream &in) {
unsigned long pixelcount = width*height;
unsigned long currentpixel = 0;
unsigned long currentbyte = 0;
TGAColor colorbuffer;
do {
unsigned char chunkheader = 0;
chunkheader = in.get();
if (!in.good()) {
std::cerr << "an error occured while reading the data\n";
return false;
}
if (chunkheader<128) {
chunkheader++;
for (int i=0; i<chunkheader; i++) {
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good()) {
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int t=0; t<bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel>pixelcount) {
std::cerr << "Too many pixels read\n";
return false;
}
}
} else {
chunkheader -= 127;
in.read((char *)colorbuffer.bgra, bytespp);
if (!in.good()) {
std::cerr << "an error occured while reading the header\n";
return false;
}
for (int i=0; i<chunkheader; i++) {
for (int t=0; t<bytespp; t++)
data[currentbyte++] = colorbuffer.bgra[t];
currentpixel++;
if (currentpixel>pixelcount) {
std::cerr << "Too many pixels read\n";
return false;
}
}
}
} while (currentpixel < pixelcount);
return true;
}
bool TGAImage::write_tga_file(const char *filename, bool rle) const {
unsigned char developer_area_ref[4] = {0, 0, 0, 0};
unsigned char extension_area_ref[4] = {0, 0, 0, 0};
unsigned char footer[18] = {'T','R','U','E','V','I','S','I','O','N','-','X','F','I','L','E','.','\0'};
std::ofstream out;
out.open (filename, std::ios::binary);
if (!out.is_open()) {
std::cerr << "can't open file " << filename << "\n";
out.close();
return false;
}
TGA_Header header;
memset((void *)&header, 0, sizeof(header));
header.bitsperpixel = bytespp<<3;
header.width = width;
header.height = height;
header.datatypecode = (bytespp==GRAYSCALE?(rle?11:3):(rle?10:2));
header.imagedescriptor = 0x20; // top-left origin
out.write((char *)&header, sizeof(header));
if (!out.good()) {
out.close();
std::cerr << "can't dump the tga file\n";
return false;
}
if (!rle) {
out.write((char *)data, width*height*bytespp);
if (!out.good()) {
std::cerr << "can't unload raw data\n";
out.close();
return false;
}
} else {
if (!unload_rle_data(out)) {
out.close();
std::cerr << "can't unload rle data\n";
return false;
}
}
out.write((char *)developer_area_ref, sizeof(developer_area_ref));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)extension_area_ref, sizeof(extension_area_ref));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.write((char *)footer, sizeof(footer));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
out.close();
return false;
}
out.close();
return true;
}
// TODO: it is not necessary to break a raw chunk for two equal pixels (for the matter of the resulting size)
bool TGAImage::unload_rle_data(std::ofstream &out) const {
const unsigned char max_chunk_length = 128;
unsigned long npixels = width*height;
unsigned long curpix = 0;
while (curpix<npixels) {
unsigned long chunkstart = curpix*bytespp;
unsigned long curbyte = curpix*bytespp;
unsigned char run_length = 1;
bool raw = true;
while (curpix+run_length<npixels && run_length<max_chunk_length) {
bool succ_eq = true;
for (int t=0; succ_eq && t<bytespp; t++) {
succ_eq = (data[curbyte+t]==data[curbyte+t+bytespp]);
}
curbyte += bytespp;
if (1==run_length) {
raw = !succ_eq;
}
if (raw && succ_eq) {
run_length--;
break;
}
if (!raw && !succ_eq) {
break;
}
run_length++;
}
curpix += run_length;
out.put(raw?run_length-1:run_length+127);
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
return false;
}
out.write((char *)(data+chunkstart), (raw?run_length*bytespp:bytespp));
if (!out.good()) {
std::cerr << "can't dump the tga file\n";
return false;
}
}
return true;
}
TGAColor TGAImage::get(int x, int y) const {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return TGAColor(128.f,128.f,128.f,255.f);
}
return TGAColor(data+(x+y*width)*bytespp, bytespp);
}
bool TGAImage::set(int x, int y, TGAColor &c) {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return false;
}
memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp);
return true;
}
bool TGAImage::set(int x, int y, const TGAColor &c) {
if (!data || x<0 || y<0 || x>=width || y>=height) {
return false;
}
memcpy(data+(x+y*width)*bytespp, c.bgra, bytespp);
return true;
}
int TGAImage::get_bytespp() {
return bytespp;
}
int TGAImage::get_width() {
return width;
}
int TGAImage::get_height() {
return height;
}
bool TGAImage::flip_horizontally() {
if (!data) return false;
int half = width>>1;
for (int i=0; i<half; i++) {
for (int j=0; j<height; j++) {
TGAColor c1 = get(i, j);
TGAColor c2 = get(width-1-i, j);
set(i, j, c2);
set(width-1-i, j, c1);
}
}
return true;
}
bool TGAImage::flip_vertically() {
if (!data) return false;
unsigned long bytes_per_line = width*bytespp;
unsigned char *line = new unsigned char[bytes_per_line];
int half = height>>1;
for (int j=0; j<half; j++) {
unsigned long l1 = j*bytes_per_line;
unsigned long l2 = (height-1-j)*bytes_per_line;
memmove((void *)line, (void *)(data+l1), bytes_per_line);
memmove((void *)(data+l1), (void *)(data+l2), bytes_per_line);
memmove((void *)(data+l2), (void *)line, bytes_per_line);
}
delete [] line;
return true;
}
unsigned char *TGAImage::buffer() {
return data;
}
void TGAImage::clear() {
memset((void *)data, 0, width*height*bytespp);
}
bool TGAImage::scale(int w, int h) {
if (w<=0 || h<=0 || !data) return false;
unsigned char *tdata = new unsigned char[w*h*bytespp];
int nscanline = 0;
int oscanline = 0;
int erry = 0;
unsigned long nlinebytes = w*bytespp;
unsigned long olinebytes = width*bytespp;
for (int j=0; j<height; j++) {
int errx = width-w;
int nx = -bytespp;
int ox = -bytespp;
for (int i=0; i<width; i++) {
ox += bytespp;
errx += w;
while (errx>=(int)width) {
errx -= width;
nx += bytespp;
memcpy(tdata+nscanline+nx, data+oscanline+ox, bytespp);
}
}
erry += h;
oscanline += olinebytes;
while (erry>=(int)height) {
if (erry>=(int)height<<1) // it means we jump over a scanline
memcpy(tdata+nscanline+nlinebytes, tdata+nscanline, nlinebytes);
erry -= height;
nscanline += nlinebytes;
}
}
delete [] data;
data = tdata;
width = w;
height = h;
return true;
}

View File

@@ -0,0 +1,99 @@
#ifndef __IMAGE_H__
#define __IMAGE_H__
#include <fstream>
#pragma pack(push,1)
struct TGA_Header {
char idlength;
char colormaptype;
char datatypecode;
short colormaporigin;
short colormaplength;
char colormapdepth;
short x_origin;
short y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
};
#pragma pack(pop)
struct TGAColor {
unsigned char bgra[4];
unsigned char bytespp;
TGAColor() : bgra(), bytespp(1) {
for (int i=0; i<4; i++) bgra[i] = 0;
}
TGAColor(unsigned char R, unsigned char G, unsigned char B, unsigned char A=255) : bgra(), bytespp(4) {
bgra[0] = B;
bgra[1] = G;
bgra[2] = R;
bgra[3] = A;
}
TGAColor(unsigned char v) : bgra(), bytespp(1) {
for (int i=0; i<4; i++) bgra[i] = 0;
bgra[0] = v;
}
TGAColor(const unsigned char *p, unsigned char bpp) : bgra(), bytespp(bpp) {
for (int i=0; i<(int)bpp; i++) {
bgra[i] = p[i];
}
for (int i=bpp; i<4; i++) {
bgra[i] = 0;
}
}
unsigned char& operator[](const int i) { return bgra[i]; }
TGAColor operator *(float intensity) const {
TGAColor res = *this;
intensity = (intensity>1.f?1.f:(intensity<0.f?0.f:intensity));
for (int i=0; i<4; i++) res.bgra[i] = bgra[i]*intensity;
return res;
}
};
class TGAImage {
protected:
unsigned char* data;
int width;
int height;
int bytespp;
bool load_rle_data(std::ifstream &in);
bool unload_rle_data(std::ofstream &out) const;
public:
enum Format {
GRAYSCALE=1, RGB=3, RGBA=4
};
TGAImage();
TGAImage(int w, int h, int bpp);
TGAImage(const TGAImage &img);
bool read_tga_file(const char *filename);
bool write_tga_file(const char *filename, bool rle=true) const;
bool flip_horizontally();
bool flip_vertically();
bool scale(int w, int h);
TGAColor get(int x, int y) const;
bool set(int x, int y, TGAColor &c);
bool set(int x, int y, const TGAColor &c);
~TGAImage();
TGAImage & operator =(const TGAImage &img);
int get_width();
int get_height();
int get_bytespp();
unsigned char *buffer();
void clear();
};
#endif //__IMAGE_H__

View File

@@ -0,0 +1,29 @@
INCLUDE_DIRECTORIES(
${BULLET_PHYSICS_SOURCE_DIR}/src
${BULLET_PHYSICS_SOURCE_DIR}/examples
${BULLET_PHYSICS_SOURCE_DIR}/examples/ThirdPartyLibs
${PYTHON_INCLUDE_DIRS}
)
SET(pybullet_SRCS
pybullet.c
../../examples/ExampleBrowser/ExampleEntries.cpp
)
IF(WIN32)
LINK_LIBRARIES(
${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}
)
ENDIF(WIN32)
ADD_LIBRARY(pybullet SHARED ${pybullet_SRCS})
SET_TARGET_PROPERTIES(pybullet PROPERTIES VERSION ${BULLET_VERSION})
SET_TARGET_PROPERTIES(pybullet PROPERTIES SOVERSION ${BULLET_VERSION})
TARGET_LINK_LIBRARIES(pybullet BulletExampleBrowserLib BulletSoftBody BulletDynamics BulletCollision BulletInverseDynamicsUtils BulletInverseDynamics LinearMath OpenGLWindow gwen Bullet3Common ${PYTHON_LIBRARIES})

View File

@@ -0,0 +1,49 @@
project ("pybullet")
language "C++"
kind "SharedLib"
targetsuffix ("")
targetprefix ("")
targetextension (".so")
includedirs {"../../src", "../../examples",
"../../examples/ThirdPartyLibs"}
defines {"PHYSICS_IN_PROCESS_EXAMPLE_BROWSER"}
hasCL = findOpenCL("clew")
links{"BulletExampleBrowserLib","gwen", "OpenGL_Window","BulletSoftBody", "BulletInverseDynamicsUtils", "BulletInverseDynamics", "BulletDynamics","BulletCollision","LinearMath","Bullet3Common"}
initOpenGL()
initGlew()
includedirs {
".",
"../../src",
"../ThirdPartyLibs",
"/usr/include/python2.7",
}
if os.is("MacOSX") then
links{"Cocoa.framework","Python"}
end
if (hasCL) then
links {
"Bullet3OpenCL_clew",
"Bullet3Dynamics",
"Bullet3Collision",
"Bullet3Geometry",
"Bullet3Common",
}
end
files {
"pybullet.c",
"../../examples/ExampleBrowser/ExampleEntries.cpp",
}
if os.is("Linux") then
initX11()
end

View File

@@ -0,0 +1,346 @@
#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h"
#include "../SharedMemory/PhysicsClientC_API.h"
#include "../SharedMemory/PhysicsDirectC_API.h"
#include "../SharedMemory/SharedMemoryInProcessPhysicsC_API.h"
#ifdef __APPLE__
#include <Python/Python.h>
#else
#include <Python.h>
#endif
enum eCONNECT_METHOD
{
eCONNECT_GUI=1,
eCONNECT_DIRECT=2,
eCONNECT_SHARED_MEMORY=3,
};
static PyObject *SpamError;
static b3PhysicsClientHandle sm=0;
static PyObject *
pybullet_stepSimulation(PyObject *self, PyObject *args)
{
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
{
b3SharedMemoryStatusHandle statusHandle;
int statusType;
if (b3CanSubmitCommand(sm))
{
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitStepSimulationCommand(sm));
statusType = b3GetStatusType(statusHandle);
}
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pybullet_connectPhysicsServer(PyObject *self, PyObject *args)
{
if (0!=sm)
{
PyErr_SetString(SpamError, "Already connected to physics server, disconnect first.");
return NULL;
}
{
int method=eCONNECT_GUI;
if (!PyArg_ParseTuple(args, "i", &method))
{
PyErr_SetString(SpamError, "connectPhysicsServer expected argument eCONNECT_GUI, eCONNECT_DIRECT or eCONNECT_SHARED_MEMORY");
return NULL;
}
switch (method)
{
case eCONNECT_GUI:
{
int argc=0;
char* argv[1]={0};
#ifdef __APPLE__
sm = b3CreateInProcessPhysicsServerAndConnectMainThread(argc, argv);
#else
sm = b3CreateInProcessPhysicsServerAndConnect(argc, argv);
#endif
break;
}
case eCONNECT_DIRECT:
{
sm = b3ConnectPhysicsDirect();
break;
}
case eCONNECT_SHARED_MEMORY:
{
sm = b3ConnectSharedMemory(SHARED_MEMORY_KEY);
break;
}
default:
{
PyErr_SetString(SpamError, "connectPhysicsServer unexpected argument");
return NULL;
}
};
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pybullet_disconnectPhysicsServer(PyObject *self, PyObject *args)
{
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
{
b3DisconnectSharedMemory(sm);
sm = 0;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pybullet_loadURDF(PyObject* self, PyObject* args)
{
int size= PySequence_Size(args);
int bodyIndex = -1;
const char* urdfFileName=0;
float startPosX =0;
float startPosY =0;
float startPosZ = 1;
float startOrnX = 0;
float startOrnY = 0;
float startOrnZ = 0;
float startOwnW = 1;
printf("size=%d\n", size);
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
if (size==1)
{
if (!PyArg_ParseTuple(args, "s", &urdfFileName))
return NULL;
}
if (size == 4)
{
if (!PyArg_ParseTuple(args, "sfff", &urdfFileName,
&startPosX,&startPosY,&startPosZ))
return NULL;
}
if (size==7)
{
if (!PyArg_ParseTuple(args, "sfffffff", &urdfFileName,
&startPosX,startPosY,&startPosZ,
&startOrnX,&startOrnY,&startOrnZ, &startOwnW))
return NULL;
}
{
b3SharedMemoryStatusHandle statusHandle;
int statusType;
b3SharedMemoryCommandHandle command = b3LoadUrdfCommandInit(sm, urdfFileName);
printf("urdf filename = %s\n", urdfFileName);
//setting the initial position, orientation and other arguments are optional
b3LoadUrdfCommandSetStartPosition(command, startPosX,startPosY,startPosZ);
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command);
statusType = b3GetStatusType(statusHandle);
if (statusType!=CMD_URDF_LOADING_COMPLETED)
{
PyErr_SetString(SpamError, "Cannot load URDF file.");
return NULL;
}
bodyIndex = b3GetStatusBodyIndex(statusHandle);
}
return PyLong_FromLong(bodyIndex);
}
static PyObject *
pybullet_resetSimulation(PyObject* self, PyObject* args)
{
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
{
b3SharedMemoryStatusHandle statusHandle;
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, b3InitResetSimulationCommand(sm));
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pybullet_setGravity(PyObject* self, PyObject* args)
{
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
{
float gravX=0;
float gravY=0;
float gravZ=-10;
int ret;
b3SharedMemoryCommandHandle command = b3InitPhysicsParamCommand(sm);
b3SharedMemoryStatusHandle statusHandle;
if (!PyArg_ParseTuple(args, "fff", &gravX,&gravY,&gravZ))
{
PyErr_SetString(SpamError, "setGravity expected (x,y,z) values.");
return NULL;
}
ret = b3PhysicsParamSetGravity(command, gravX,gravY, gravZ);
//ret = b3PhysicsParamSetTimeStep(command, timeStep);
statusHandle = b3SubmitClientCommandAndWaitStatus(sm, command);
//ASSERT_EQ(b3GetStatusType(statusHandle), CMD_CLIENT_COMMAND_COMPLETED);
}
if (1)
{
PyObject *pylist;
PyObject *item;
int i;
int num=3;
pylist = PyTuple_New(num);
for (i = 0; i < num; i++)
{
item = PyFloat_FromDouble(i);
PyTuple_SetItem(pylist, i, item);
}
return pylist;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *
pybullet_getNumJoints(PyObject* self, PyObject* args)
{
if (0==sm)
{
PyErr_SetString(SpamError, "Not connected to physics server.");
return NULL;
}
{
int bodyIndex = -1;
int numJoints=0;
if (!PyArg_ParseTuple(args, "i", &bodyIndex ))
{
PyErr_SetString(SpamError, "Expected a body index (integer).");
return NULL;
}
numJoints = b3GetNumJoints(sm,bodyIndex);
#if PY_MAJOR_VERSION >= 3
return PyLong_FromLong(numJoints);
#else
return PyInt_FromLong(numJoints);
#endif
}
}
static PyMethodDef SpamMethods[] = {
{"loadURDF", pybullet_loadURDF, METH_VARARGS,
"Create a multibody by loading a URDF file."},
{"connect", pybullet_connectPhysicsServer, METH_VARARGS,
"Connect to an existing physics server (using shared memory by default)."},
{"disconnect", pybullet_disconnectPhysicsServer, METH_VARARGS,
"Disconnect from the physics server."},
{"resetSimulation", pybullet_resetSimulation, METH_VARARGS,
"Reset the simulation: remove all objects and start from an empty world."},
{"stepSimulation", pybullet_stepSimulation, METH_VARARGS,
"Step the simulation using forward dynamics."},
{"setGravity", pybullet_setGravity, METH_VARARGS,
"Set the gravity acceleration (x,y,z)."},
{"getNumsetGravity", pybullet_setGravity, METH_VARARGS,
"Set the gravity acceleration (x,y,z)."},
{
"getNumJoints", pybullet_getNumJoints, METH_VARARGS,
"Get the number of joints for an object."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"pybullet", /* m_name */
"Python bindings for Bullet", /* m_doc */
-1, /* m_size */
SpamMethods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#endif
PyMODINIT_FUNC
#if PY_MAJOR_VERSION >= 3
PyInit_pybullet(void)
#else
initpybullet(void)
#endif
{
PyObject *m;
#if PY_MAJOR_VERSION >= 3
m = PyModule_Create(&moduledef);
#else
m = Py_InitModule3("pybullet",
SpamMethods, "Python bindings for Bullet");
#endif
if (m == NULL)
return m;
PyModule_AddIntConstant (m, "SHARED_MEMORY", eCONNECT_SHARED_MEMORY); // user read
PyModule_AddIntConstant (m, "DIRECT", eCONNECT_DIRECT); // user read
PyModule_AddIntConstant (m, "GUI", eCONNECT_GUI); // user read
SpamError = PyErr_NewException("pybullet.error", NULL, NULL);
Py_INCREF(SpamError);
PyModule_AddObject(m, "error", SpamError);
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}

34
examples/pybullet/test.py Normal file
View File

@@ -0,0 +1,34 @@
import pybullet
import time
#choose connection method: GUI, DIRECT, SHARED_MEMORY
pybullet.connect(pybullet.SHARED_MEMORY)
#load URDF, given a relative or absolute file+path
obj = pybullet.loadURDF("r2d2.urdf")
posX=0
posY=3
posZ=2
obj2 = pybullet.loadURDF("kuka_lwr/kuka.urdf",posX,posY,posZ)
#query the number of joints of the object
numJoints = pybullet.getNumJoints(obj)
print (numJoints)
#set the gravity acceleration
pybullet.setGravity(0,0,-9.8)
#step the simulation for 5 seconds
t_end = time.time() + 5
while time.time() < t_end:
pybullet.stepSimulation()
print ("finished")
#remove all objects
pybullet.resetSimulation()
#disconnect from the physics server
pybullet.disconnect()

View File

@@ -790,23 +790,50 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
}
}
} else {
///@todo : use AABB tree or other BVH acceleration structure!
if (collisionShape->isCompound())
{
BT_PROFILE("convexSweepCompound");
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
int i=0;
for (i=0;i<compoundShape->getNumChildShapes();i++)
struct btCompoundLeafCallback : btDbvt::ICollide
{
btTransform childTrans = compoundShape->getChildTransform(i);
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childWorldTrans = colObjWorldTransform * childTrans;
btCompoundLeafCallback(
const btCollisionObjectWrapper* colObjWrap,
const btConvexShape* castShape,
const btTransform& convexFromTrans,
const btTransform& convexToTrans,
btScalar allowedPenetration,
const btCompoundShape* compoundShape,
const btTransform& colObjWorldTransform,
ConvexResultCallback& resultCallback)
:
m_colObjWrap(colObjWrap),
m_castShape(castShape),
m_convexFromTrans(convexFromTrans),
m_convexToTrans(convexToTrans),
m_allowedPenetration(allowedPenetration),
m_compoundShape(compoundShape),
m_colObjWorldTransform(colObjWorldTransform),
m_resultCallback(resultCallback) {
}
const btCollisionObjectWrapper* m_colObjWrap;
const btConvexShape* m_castShape;
const btTransform& m_convexFromTrans;
const btTransform& m_convexToTrans;
btScalar m_allowedPenetration;
const btCompoundShape* m_compoundShape;
const btTransform& m_colObjWorldTransform;
ConvexResultCallback& m_resultCallback;
public:
void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
{
btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
struct LocalInfoAdder : public ConvexResultCallback {
ConvexResultCallback* m_userCallback;
int m_i;
LocalInfoAdder (int i, ConvexResultCallback *user)
LocalInfoAdder(int i, ConvexResultCallback *user)
: m_userCallback(user), m_i(i)
{
m_closestHitFraction = m_userCallback->m_closestHitFraction;
@@ -815,7 +842,7 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
{
return m_userCallback->needsCollision(p);
}
virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult& r, bool b)
virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
{
btCollisionWorld::LocalShapeInfo shapeInfo;
shapeInfo.m_shapePart = -1;
@@ -829,13 +856,52 @@ void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape,
}
};
LocalInfoAdder my_cb(i, &resultCallback);
LocalInfoAdder my_cb(index, &m_resultCallback);
btCollisionObjectWrapper tmpObj(colObjWrap,childCollisionShape,colObjWrap->getCollisionObject(),childWorldTrans,-1,i);
btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
objectQuerySingleInternal(castShape, convexFromTrans,convexToTrans,
&tmpObj,my_cb, allowedPenetration);
objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
}
void Process(const btDbvtNode* leaf)
{
// Processing leaf node
int index = leaf->dataAsInt;
btTransform childTrans = m_compoundShape->getChildTransform(index);
const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
ProcessChild(index, childTrans, childCollisionShape);
}
};
BT_PROFILE("convexSweepCompound");
const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
btVector3 fromLocalAabbMin, fromLocalAabbMax;
btVector3 toLocalAabbMin, toLocalAabbMax;
castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
fromLocalAabbMin.setMin(toLocalAabbMin);
fromLocalAabbMax.setMax(toLocalAabbMax);
btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
const btDbvt* tree = compoundShape->getDynamicAabbTree();
if (tree) {
const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
tree->collideTV(tree->m_root, bounds, callback);
} else {
int i;
for (i=0;i<compoundShape->getNumChildShapes();i++)
{
const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
btTransform childTrans = compoundShape->getChildTransform(i);
callback.ProcessChild(i, childTrans, childCollisionShape);
}
}
}
}

View File

@@ -22,6 +22,8 @@ subject to the following restrictions:
#include "LinearMath/btQuaternion.h"
#include "LinearMath/btSerializer.h"
#include "btConvexPolyhedron.h"
#include "LinearMath/btConvexHullComputer.h"
btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape ()
{
@@ -121,10 +123,17 @@ btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
}
void btConvexHullShape::optimizeConvexHull()
{
btConvexHullComputer conv;
conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3),m_unscaledPoints.size(),0.f,0.f);
int numVerts = conv.vertices.size();
m_unscaledPoints.resize(0);
for (int i=0;i<numVerts;i++)
{
m_unscaledPoints.push_back(conv.vertices[i]);
}
}

Some files were not shown because too many files have changed in this diff Show More