Merge pull request #1000 from olegklimov/master

URDF loader improvement 1
This commit is contained in:
erwincoumans
2017-03-13 19:16:45 -07:00
committed by GitHub
5 changed files with 592 additions and 675 deletions

View File

@@ -32,6 +32,7 @@ static btScalar gUrdfDefaultCollisionMargin = 0.001;
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <list>
#include "UrdfParser.h" #include "UrdfParser.h"
struct MyTexture struct MyTexture
@@ -47,14 +48,27 @@ ATTRIBUTE_ALIGNED16(struct) BulletURDFInternalData
UrdfParser m_urdfParser; UrdfParser m_urdfParser;
struct GUIHelperInterface* m_guiHelper; struct GUIHelperInterface* m_guiHelper;
std::string m_sourceFile;
char m_pathPrefix[1024]; char m_pathPrefix[1024];
int m_bodyId; int m_bodyId;
btHashMap<btHashInt,btVector4> m_linkColors; btHashMap<btHashInt,btVector4> m_linkColors;
btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes; btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
LinkVisualShapesConverter* m_customVisualShapesConverter; LinkVisualShapesConverter* m_customVisualShapesConverter;
};
void setSourceFile(const std::string& relativeFileName, const std::string& prefix)
{
m_sourceFile = relativeFileName;
m_urdfParser.setSourceFile(relativeFileName);
strncpy(m_pathPrefix, prefix.c_str(), sizeof(m_pathPrefix));
m_pathPrefix[sizeof(m_pathPrefix)-1] = 0; // required, strncpy doesn't write zero on overflow
}
BulletURDFInternalData()
{
m_pathPrefix[0] = 0;
}
};
void BulletURDFImporter::printTree() void BulletURDFImporter::printTree()
{ {
@@ -76,7 +90,6 @@ BulletURDFImporter::BulletURDFImporter(struct GUIHelperInterface* helper, LinkVi
m_data = new BulletURDFInternalData; m_data = new BulletURDFInternalData;
m_data->m_guiHelper = helper; m_data->m_guiHelper = helper;
m_data->m_pathPrefix[0]=0;
m_data->m_customVisualShapesConverter = customConverter; m_data->m_customVisualShapesConverter = customConverter;
@@ -111,7 +124,6 @@ struct BulletErrorLogger : public ErrorLogger
bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase) bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase)
{ {
if (strlen(fileName)==0) if (strlen(fileName)==0)
return false; return false;
@@ -124,17 +136,16 @@ bool BulletURDFImporter::loadURDF(const char* fileName, bool forceFixedBase)
bool fileFound = (b3ResourcePath::findResourcePath(fileName,relativeFileName,1024))>0; bool fileFound = (b3ResourcePath::findResourcePath(fileName,relativeFileName,1024))>0;
std::string xml_string; 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);
if (!fileFound){
b3Warning("URDF file '%s' not found\n", fileName);
return false;
} else
{
char path[1024];
fu.extractPath(relativeFileName, path, sizeof(path));
m_data->setSourceFile(relativeFileName, path);
std::fstream xml_file(relativeFileName, std::fstream::in); std::fstream xml_file(relativeFileName, std::fstream::in);
while ( xml_file.good()) while ( xml_file.good())
@@ -166,7 +177,7 @@ void BulletURDFImporter::activateModel(int modelIndex)
bool BulletURDFImporter::loadSDF(const char* fileName, bool forceFixedBase) bool BulletURDFImporter::loadSDF(const char* fileName, bool forceFixedBase)
{ {
//int argc=0; //int argc=0;
char relativeFileName[1024]; char relativeFileName[1024];
@@ -176,17 +187,16 @@ bool BulletURDFImporter::loadSDF(const char* fileName, bool forceFixedBase)
bool fileFound = (b3ResourcePath::findResourcePath(fileName,relativeFileName,1024))>0; bool fileFound = (b3ResourcePath::findResourcePath(fileName,relativeFileName,1024))>0;
std::string xml_string; std::string xml_string;
m_data->m_pathPrefix[0] = 0;
if (!fileFound){ if (!fileFound){
std::cerr << "SDF file not found" << std::endl; b3Warning("SDF file '%s' not found\n", fileName);
return false; return false;
} else } else
{ {
int maxPathLen = 1024; char path[1024];
fu.extractPath(relativeFileName,m_data->m_pathPrefix,maxPathLen); fu.extractPath(relativeFileName, path, sizeof(path));
m_data->setSourceFile(relativeFileName, path);
std::fstream xml_file(relativeFileName, std::fstream::in); std::fstream xml_file(relativeFileName, std::fstream::in);
while ( xml_file.good() ) while ( xml_file.good() )
@@ -447,6 +457,88 @@ static btCollisionShape* createConvexHullFromShapes(std::vector<tinyobj::shape_t
return compound; return compound;
} }
bool findExistingMeshFile(
const std::string& urdf_path, std::string fn,
const std::string& error_message_prefix,
std::string* out_found_filename, int* out_type)
{
if (fn.size() <= 4)
{
b3Warning("%s: invalid mesh filename '%s'\n", error_message_prefix.c_str(), fn.c_str());
return false;
}
std::string ext;
std::string ext_ = fn.substr(fn.size()-4);
for (std::string::iterator i=ext_.begin(); i!=ext_.end(); ++i)
{
ext += char(tolower(*i));
}
if (ext==".dae")
{
*out_type = UrdfGeometry::FILE_COLLADA;
}
else if (ext==".stl")
{
*out_type = UrdfGeometry::FILE_STL;
}
else if (ext==".obj")
{
*out_type = UrdfGeometry::FILE_OBJ;
}
else
{
b3Warning("%s: invalid mesh filename extension '%s'\n", error_message_prefix.c_str(), ext.c_str());
return false;
}
std::string drop_it = "package://";
if (fn.substr(0, drop_it.length())==drop_it)
fn = fn.substr(drop_it.length());
std::list<std::string> shorter;
shorter.push_back("../..");
shorter.push_back("..");
shorter.push_back(".");
int cnt = urdf_path.size();
for (int i=0; i<cnt; ++i)
{
if (urdf_path[i]=='/' || urdf_path[i]=='\\')
{
shorter.push_back(urdf_path.substr(0, i));
}
}
shorter.reverse();
std::string existing_file;
for (std::list<std::string>::iterator x=shorter.begin(); x!=shorter.end(); ++x)
{
std::string attempt = *x + "/" + fn;
FILE* f = fopen(attempt.c_str(), "rb");
if (!f)
{
//b3Printf("%s: tried '%s'", error_message_prefix.c_str(), attempt.c_str());
continue;
}
fclose(f);
existing_file = attempt;
//b3Printf("%s: found '%s'", error_message_prefix.c_str(), attempt.c_str());
break;
}
if (existing_file.empty())
{
b3Warning("%s: cannot find '%s' in any directory in urdf path\n", error_message_prefix.c_str(), fn.c_str());
return false;
}
else
{
*out_found_filename = existing_file;
return true;
}
}
btCollisionShape* convertURDFToCollisionShape(const UrdfCollision* collision, const char* urdfPathPrefix) btCollisionShape* convertURDFToCollisionShape(const UrdfCollision* collision, const char* urdfPathPrefix)
{ {
BT_PROFILE("convertURDFToCollisionShape"); BT_PROFILE("convertURDFToCollisionShape");
@@ -507,239 +599,165 @@ btCollisionShape* convertURDFToCollisionShape(const UrdfCollision* collision, co
} }
case URDF_GEOM_SPHERE: case URDF_GEOM_SPHERE:
{ {
btScalar radius = collision->m_geometry.m_sphereRadius; btScalar radius = collision->m_geometry.m_sphereRadius;
btSphereShape* sphereShape = new btSphereShape(radius); btSphereShape* sphereShape = new btSphereShape(radius);
shape = sphereShape; shape = sphereShape;
shape ->setMargin(gUrdfDefaultCollisionMargin); shape ->setMargin(gUrdfDefaultCollisionMargin);
break; break;
}
break; case URDF_GEOM_MESH:
} {
case URDF_GEOM_MESH: GLInstanceGraphicsShape* glmesh = 0;
{ switch (collision->m_geometry.m_meshFileType)
if (collision->m_name.length()) {
case FILE_OBJ:
if (collision->m_flags & URDF_FORCE_CONCAVE_TRIMESH)
{ {
//b3Printf("collision->name=%s\n",collision->m_name.c_str()); glmesh = LoadMeshFromObj(collision->m_geometry.m_meshFileName.c_str(), 0);
} }
if (1) else
{ {
if (collision->m_geometry.m_meshFileName.length()) std::vector<tinyobj::shape_t> shapes;
std::string err = tinyobj::LoadObj(shapes, collision->m_geometry.m_meshFileName.c_str());
//create a convex hull for each shape, and store it in a btCompoundShape
shape = createConvexHullFromShapes(shapes, collision->m_geometry.m_meshScale);
return shape;
}
break;
case FILE_STL:
glmesh = LoadMeshFromSTL(collision->m_geometry.m_meshFileName.c_str());
break;
case FILE_COLLADA:
{
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans;upAxisTrans.setIdentity();
float unitMeterScaling = 1;
LoadMeshFromCollada(collision->m_geometry.m_meshFileName.c_str(), visualShapes, visualShapeInstances, upAxisTrans, unitMeterScaling, 2);
glmesh = new GLInstanceGraphicsShape;
glmesh->m_indices = new b3AlignedObjectArray<int>();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i=0;i<visualShapeInstances.size();i++)
{ {
const char* filename = collision->m_geometry.m_meshFileName.c_str(); ColladaGraphicsInstance* instance = &visualShapeInstances[i];
//b3Printf("mesh->filename=%s\n",filename); GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
char fullPath[1024];
int fileType = 0; b3AlignedObjectArray<GLInstanceVertex> verts;
sprintf(fullPath,"%s%s",urdfPathPrefix,filename); verts.resize(gfxShape->m_vertices->size());
b3FileUtils::toLower(fullPath);
char tmpPathPrefix[1024]; int baseIndex = glmesh->m_vertices->size();
int maxPathLen = 1024;
b3FileUtils::extractPath(filename,tmpPathPrefix,maxPathLen); for (int i=0;i<gfxShape->m_vertices->size();i++)
char collisionPathPrefix[1024];
sprintf(collisionPathPrefix,"%s%s",urdfPathPrefix,tmpPathPrefix);
if (strstr(fullPath,".dae"))
{ {
fileType = FILE_COLLADA; verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
} }
if (strstr(fullPath,".stl"))
int curNumIndices = glmesh->m_indices->size();
int additionalIndices = gfxShape->m_indices->size();
glmesh->m_indices->resize(curNumIndices+additionalIndices);
for (int k=0;k<additionalIndices;k++)
{ {
fileType = FILE_STL; glmesh->m_indices->at(curNumIndices+k)=gfxShape->m_indices->at(k)+baseIndex;
} }
if (strstr(fullPath,".obj"))
{
fileType = FILE_OBJ;
}
sprintf(fullPath,"%s%s",urdfPathPrefix,filename); //compensate upAxisTrans and unitMeterScaling here
FILE* f = fopen(fullPath,"rb"); btMatrix4x4 upAxisMat;
if (f) upAxisMat.setIdentity();
//upAxisMat.setPureRotation(upAxisTrans.getRotation());
btMatrix4x4 unitMeterScalingMat;
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling,unitMeterScaling,unitMeterScaling));
btMatrix4x4 worldMat = unitMeterScalingMat*instance->m_worldTransform*upAxisMat;
//btMatrix4x4 worldMat = instance->m_worldTransform;
int curNumVertices = glmesh->m_vertices->size();
int additionalVertices = verts.size();
glmesh->m_vertices->reserve(curNumVertices+additionalVertices);
for(int v=0;v<verts.size();v++)
{ {
fclose(f); btVector3 pos(verts[v].xyzw[0],verts[v].xyzw[1],verts[v].xyzw[2]);
GLInstanceGraphicsShape* glmesh = 0; pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
switch (fileType) verts[v].xyzw[2] = float(pos[2]);
{ glmesh->m_vertices->push_back(verts[v]);
case FILE_OBJ:
{
if (collision->m_flags & URDF_FORCE_CONCAVE_TRIMESH)
{
glmesh = LoadMeshFromObj(fullPath, collisionPathPrefix);
}
else
{
std::vector<tinyobj::shape_t> shapes;
std::string err = tinyobj::LoadObj(shapes, fullPath, collisionPathPrefix);
//create a convex hull for each shape, and store it in a btCompoundShape
shape = createConvexHullFromShapes(shapes, collision->m_geometry.m_meshScale);
return shape;
}
break;
}
case FILE_STL:
{
glmesh = LoadMeshFromSTL(fullPath);
break;
}
case FILE_COLLADA:
{
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans;upAxisTrans.setIdentity();
float unitMeterScaling=1;
int upAxis = 2;
LoadMeshFromCollada(fullPath,
visualShapes,
visualShapeInstances,
upAxisTrans,
unitMeterScaling,
upAxis );
glmesh = new GLInstanceGraphicsShape;
// int index = 0;
glmesh->m_indices = new b3AlignedObjectArray<int>();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i=0;i<visualShapeInstances.size();i++)
{
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
b3AlignedObjectArray<GLInstanceVertex> verts;
verts.resize(gfxShape->m_vertices->size());
int baseIndex = glmesh->m_vertices->size();
for (int i=0;i<gfxShape->m_vertices->size();i++)
{
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
}
int curNumIndices = glmesh->m_indices->size();
int additionalIndices = gfxShape->m_indices->size();
glmesh->m_indices->resize(curNumIndices+additionalIndices);
for (int k=0;k<additionalIndices;k++)
{
glmesh->m_indices->at(curNumIndices+k)=gfxShape->m_indices->at(k)+baseIndex;
}
//compensate upAxisTrans and unitMeterScaling here
btMatrix4x4 upAxisMat;
upAxisMat.setIdentity();
//upAxisMat.setPureRotation(upAxisTrans.getRotation());
btMatrix4x4 unitMeterScalingMat;
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling,unitMeterScaling,unitMeterScaling));
btMatrix4x4 worldMat = unitMeterScalingMat*instance->m_worldTransform*upAxisMat;
//btMatrix4x4 worldMat = instance->m_worldTransform;
int curNumVertices = glmesh->m_vertices->size();
int additionalVertices = verts.size();
glmesh->m_vertices->reserve(curNumVertices+additionalVertices);
for(int v=0;v<verts.size();v++)
{
btVector3 pos(verts[v].xyzw[0],verts[v].xyzw[1],verts[v].xyzw[2]);
pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
verts[v].xyzw[2] = float(pos[2]);
glmesh->m_vertices->push_back(verts[v]);
}
}
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(fullPath);
break;
}
default:
{
b3Warning("Unsupported file type in Collision: %s\n",fullPath);
btAssert(0);
}
}
if (glmesh && (glmesh->m_numvertices>0))
{
//b3Printf("extracted %d verticed from STL file %s\n", glmesh->m_numvertices,fullPath);
//int shapeId = m_glApp->m_instancingRenderer->registerShape(&gvertices[0].pos[0],gvertices.size(),&indices[0],indices.size());
//convex->setUserIndex(shapeId);
btAlignedObjectArray<btVector3> convertedVerts;
convertedVerts.reserve(glmesh->m_numvertices);
for (int i=0;i<glmesh->m_numvertices;i++)
{
convertedVerts.push_back(btVector3(
glmesh->m_vertices->at(i).xyzw[0]*collision->m_geometry.m_meshScale[0],
glmesh->m_vertices->at(i).xyzw[1]*collision->m_geometry.m_meshScale[1],
glmesh->m_vertices->at(i).xyzw[2]*collision->m_geometry.m_meshScale[2]));
}
if (collision->m_flags & URDF_FORCE_CONCAVE_TRIMESH)
{
BT_PROFILE("convert trimesh");
btTriangleMesh* meshInterface = new btTriangleMesh();
for (int i=0;i<glmesh->m_numIndices/3;i++)
{
float* v0 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3)).xyzw;
float* v1 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3+1)).xyzw;
float* v2 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3+2)).xyzw;
meshInterface->addTriangle(btVector3(v0[0],v0[1],v0[2]),
btVector3(v1[0],v1[1],v1[2]),
btVector3(v2[0],v2[1],v2[2]));
}
btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(meshInterface,true,true);
trimesh->setLocalScaling(collision->m_geometry.m_meshScale);
shape = trimesh;
} else
{
BT_PROFILE("convert btConvexHullShape");
btConvexHullShape* convexHull = new btConvexHullShape(&convertedVerts[0].getX(), convertedVerts.size(), sizeof(btVector3));
convexHull->optimizeConvexHull();
//convexHull->initializePolyhedralFeatures();
convexHull->setMargin(gUrdfDefaultCollisionMargin);
convexHull->setLocalScaling(collision->m_geometry.m_meshScale);
shape = convexHull;
}
} else
{
b3Warning("issue extracting mesh from STL file %s\n", fullPath);
}
delete glmesh;
} else
{
b3Warning("mesh geometry not found %s\n",fullPath);
} }
} }
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(success.c_str());
break;
} }
}
if (!glmesh || glmesh->m_numvertices<=0)
{
b3Warning("%s: cannot extract mesh from '%s'\n", urdfPathPrefix, collision->m_geometry.m_meshFileName.c_str());
delete glmesh;
break;
}
btAlignedObjectArray<btVector3> convertedVerts;
convertedVerts.reserve(glmesh->m_numvertices);
for (int i=0; i<glmesh->m_numvertices; i++)
{
convertedVerts.push_back(btVector3(
glmesh->m_vertices->at(i).xyzw[0]*collision->m_geometry.m_meshScale[0],
glmesh->m_vertices->at(i).xyzw[1]*collision->m_geometry.m_meshScale[1],
glmesh->m_vertices->at(i).xyzw[2]*collision->m_geometry.m_meshScale[2]));
}
if (collision->m_flags & URDF_FORCE_CONCAVE_TRIMESH)
{
BT_PROFILE("convert trimesh");
btTriangleMesh* meshInterface = new btTriangleMesh();
for (int i=0; i<glmesh->m_numIndices/3; i++)
{
float* v0 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3)).xyzw;
float* v1 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3+1)).xyzw;
float* v2 = glmesh->m_vertices->at(glmesh->m_indices->at(i*3+2)).xyzw;
meshInterface->addTriangle(
btVector3(v0[0],v0[1],v0[2]),
btVector3(v1[0],v1[1],v1[2]),
btVector3(v2[0],v2[1],v2[2]));
}
btBvhTriangleMeshShape* trimesh = new btBvhTriangleMeshShape(meshInterface,true,true);
trimesh->setLocalScaling(collision->m_geometry.m_meshScale);
shape = trimesh;
} else
{
BT_PROFILE("convert btConvexHullShape");
btConvexHullShape* convexHull = new btConvexHullShape(&convertedVerts[0].getX(), convertedVerts.size(), sizeof(btVector3));
convexHull->optimizeConvexHull();
//convexHull->initializePolyhedralFeatures();
convexHull->setMargin(gUrdfDefaultCollisionMargin);
convexHull->setLocalScaling(collision->m_geometry.m_meshScale);
shape = convexHull;
}
delete glmesh;
break;
} // mesh case
break;
}
default: default:
{ b3Warning("Error: unknown collision geometry type %i\n", collision->m_geometry.m_type);
b3Warning("Error: unknown visual geometry type\n"); // for example, URDF_GEOM_PLANE
} }
}
return shape; return shape;
} }
@@ -778,17 +796,17 @@ static void convertURDFToVisualShapeInternal(const UrdfVisual* visual, const cha
convexColShape = cylZShape; convexColShape = cylZShape;
break; break;
} }
case URDF_GEOM_BOX: case URDF_GEOM_BOX:
{ {
btVector3 extents = visual->m_geometry.m_boxSize; btVector3 extents = visual->m_geometry.m_boxSize;
btBoxShape* boxShape = new btBoxShape(extents*0.5f); btBoxShape* boxShape = new btBoxShape(extents*0.5f);
//btConvexShape* boxShape = new btConeShapeX(extents[2]*0.5,extents[0]*0.5); //btConvexShape* boxShape = new btConeShapeX(extents[2]*0.5,extents[0]*0.5);
convexColShape = boxShape; convexColShape = boxShape;
convexColShape->setMargin(gUrdfDefaultCollisionMargin); convexColShape->setMargin(gUrdfDefaultCollisionMargin);
break; break;
} }
case URDF_GEOM_SPHERE: case URDF_GEOM_SPHERE:
{ {
btScalar radius = visual->m_geometry.m_sphereRadius; btScalar radius = visual->m_geometry.m_sphereRadius;
@@ -796,206 +814,137 @@ static void convertURDFToVisualShapeInternal(const UrdfVisual* visual, const cha
convexColShape = sphereShape; convexColShape = sphereShape;
convexColShape->setMargin(gUrdfDefaultCollisionMargin); convexColShape->setMargin(gUrdfDefaultCollisionMargin);
break; break;
break;
} }
case URDF_GEOM_MESH: case URDF_GEOM_MESH:
{ {
if (visual->m_name.length()) switch (visual->m_geometry.m_meshFileType)
{ {
//b3Printf("visual->name=%s\n", visual->m_name.c_str()); case FILE_OBJ:
}
if (1)//visual->m_geometry)
{
if (visual->m_geometry.m_meshFileName.length())
{ {
const char* filename = visual->m_geometry.m_meshFileName.c_str(); b3ImportMeshData meshData;
//b3Printf("mesh->filename=%s\n", filename); if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(visual->m_geometry.m_meshFileName, meshData))
char fullPath[1024];
int fileType = 0;
char tmpPathPrefix[1024];
std::string xml_string;
int maxPathLen = 1024;
b3FileUtils::extractPath(filename,tmpPathPrefix,maxPathLen);
char visualPathPrefix[1024];
sprintf(visualPathPrefix,"%s%s",urdfPathPrefix,tmpPathPrefix);
sprintf(fullPath, "%s%s", urdfPathPrefix, filename);
b3FileUtils::toLower(fullPath);
if (strstr(fullPath, ".dae"))
{ {
fileType = FILE_COLLADA;
if (meshData.m_textureImage)
{
MyTexture texData;
texData.m_width = meshData.m_textureWidth;
texData.m_height = meshData.m_textureHeight;
texData.textureData = meshData.m_textureImage;
texturesOut.push_back(texData);
}
glmesh = meshData.m_gfxShape;
} }
if (strstr(fullPath, ".stl")) break;
{
fileType = FILE_STL;
}
if (strstr(fullPath,".obj"))
{
fileType = FILE_OBJ;
}
sprintf(fullPath, "%s%s", urdfPathPrefix, filename);
FILE* f = fopen(fullPath, "rb");
if (f)
{
fclose(f);
switch (fileType)
{
case FILE_OBJ:
{
// glmesh = LoadMeshFromObj(fullPath,visualPathPrefix);
b3ImportMeshData meshData;
if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(fullPath, meshData))
{
if (meshData.m_textureImage)
{
MyTexture texData;
texData.m_width = meshData.m_textureWidth;
texData.m_height = meshData.m_textureHeight;
texData.textureData = meshData.m_textureImage;
texturesOut.push_back(texData);
}
glmesh = meshData.m_gfxShape;
}
break;
}
case FILE_STL:
{
glmesh = LoadMeshFromSTL(fullPath);
break;
}
case FILE_COLLADA:
{
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans; upAxisTrans.setIdentity();
float unitMeterScaling = 1;
int upAxis = 2;
LoadMeshFromCollada(fullPath,
visualShapes,
visualShapeInstances,
upAxisTrans,
unitMeterScaling,
upAxis);
glmesh = new GLInstanceGraphicsShape;
// int index = 0;
glmesh->m_indices = new b3AlignedObjectArray<int>();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i = 0; i<visualShapeInstances.size(); i++)
{
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
b3AlignedObjectArray<GLInstanceVertex> verts;
verts.resize(gfxShape->m_vertices->size());
int baseIndex = glmesh->m_vertices->size();
for (int i = 0; i<gfxShape->m_vertices->size(); i++)
{
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
}
int curNumIndices = glmesh->m_indices->size();
int additionalIndices = gfxShape->m_indices->size();
glmesh->m_indices->resize(curNumIndices + additionalIndices);
for (int k = 0; k<additionalIndices; k++)
{
glmesh->m_indices->at(curNumIndices + k) = gfxShape->m_indices->at(k) + baseIndex;
}
//compensate upAxisTrans and unitMeterScaling here
btMatrix4x4 upAxisMat;
upAxisMat.setIdentity();
// upAxisMat.setPureRotation(upAxisTrans.getRotation());
btMatrix4x4 unitMeterScalingMat;
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling, unitMeterScaling, unitMeterScaling));
btMatrix4x4 worldMat = unitMeterScalingMat*upAxisMat*instance->m_worldTransform;
//btMatrix4x4 worldMat = instance->m_worldTransform;
int curNumVertices = glmesh->m_vertices->size();
int additionalVertices = verts.size();
glmesh->m_vertices->reserve(curNumVertices + additionalVertices);
for (int v = 0; v<verts.size(); v++)
{
btVector3 pos(verts[v].xyzw[0], verts[v].xyzw[1], verts[v].xyzw[2]);
pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
verts[v].xyzw[2] = float(pos[2]);
glmesh->m_vertices->push_back(verts[v]);
}
}
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(fullPath);
break;
}
default:
{
b3Warning("Error: unsupported file type for Visual mesh: %s\n", fullPath);
btAssert(0);
}
}
if (glmesh && glmesh->m_vertices && (glmesh->m_numvertices>0))
{
//apply the geometry scaling
for (int i=0;i<glmesh->m_vertices->size();i++)
{
glmesh->m_vertices->at(i).xyzw[0] *= visual->m_geometry.m_meshScale[0];
glmesh->m_vertices->at(i).xyzw[1] *= visual->m_geometry.m_meshScale[1];
glmesh->m_vertices->at(i).xyzw[2] *= visual->m_geometry.m_meshScale[2];
}
}
else
{
b3Warning("issue extracting mesh from COLLADA/STL file %s\n", fullPath);
}
}
else
{
b3Warning("mesh geometry not found %s\n", fullPath);
}
} }
case FILE_STL:
{
glmesh = LoadMeshFromSTL(visual->m_geometry.m_meshFileName.c_str());
break;
}
case FILE_COLLADA:
{
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans; upAxisTrans.setIdentity();
float unitMeterScaling = 1;
int upAxis = 2;
LoadMeshFromCollada(visual->m_geometry.m_meshFileName.c_str(),
visualShapes,
visualShapeInstances,
upAxisTrans,
unitMeterScaling,
upAxis);
glmesh = new GLInstanceGraphicsShape;
// int index = 0;
glmesh->m_indices = new b3AlignedObjectArray<int>();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i = 0; i<visualShapeInstances.size(); i++)
{
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
b3AlignedObjectArray<GLInstanceVertex> verts;
verts.resize(gfxShape->m_vertices->size());
int baseIndex = glmesh->m_vertices->size();
for (int i = 0; i<gfxShape->m_vertices->size(); i++)
{
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
}
int curNumIndices = glmesh->m_indices->size();
int additionalIndices = gfxShape->m_indices->size();
glmesh->m_indices->resize(curNumIndices + additionalIndices);
for (int k = 0; k<additionalIndices; k++)
{
glmesh->m_indices->at(curNumIndices + k) = gfxShape->m_indices->at(k) + baseIndex;
}
//compensate upAxisTrans and unitMeterScaling here
btMatrix4x4 upAxisMat;
upAxisMat.setIdentity();
// upAxisMat.setPureRotation(upAxisTrans.getRotation());
btMatrix4x4 unitMeterScalingMat;
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling, unitMeterScaling, unitMeterScaling));
btMatrix4x4 worldMat = unitMeterScalingMat*upAxisMat*instance->m_worldTransform;
//btMatrix4x4 worldMat = instance->m_worldTransform;
int curNumVertices = glmesh->m_vertices->size();
int additionalVertices = verts.size();
glmesh->m_vertices->reserve(curNumVertices + additionalVertices);
for (int v = 0; v<verts.size(); v++)
{
btVector3 pos(verts[v].xyzw[0], verts[v].xyzw[1], verts[v].xyzw[2]);
pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
verts[v].xyzw[2] = float(pos[2]);
glmesh->m_vertices->push_back(verts[v]);
}
}
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(visual->m_geometry.m_meshFileName);
break;
}
} // switch file type
if (!glmesh || !glmesh->m_vertices || glmesh->m_numvertices<=0)
{
b3Warning("%s: cannot extract anything useful from mesh '%s'\n", urdfPathPrefix, visual->m_geometry.m_meshFileName.c_str());
break;
} }
//apply the geometry scaling
for (int i=0;i<glmesh->m_vertices->size();i++)
{
glmesh->m_vertices->at(i).xyzw[0] *= visual->m_geometry.m_meshScale[0];
glmesh->m_vertices->at(i).xyzw[1] *= visual->m_geometry.m_meshScale[1];
glmesh->m_vertices->at(i).xyzw[2] *= visual->m_geometry.m_meshScale[2];
}
break; break;
} }
default: default:
{ b3Warning("Error: unknown visual geometry type %i\n", visual->m_geometry.m_type);
b3Warning("Error: unknown visual geometry type\n");
}
} }
//if we have a convex, tesselate into localVertices/localIndices //if we have a convex, tesselate into localVertices/localIndices

View File

@@ -8,9 +8,9 @@ UrdfParser::UrdfParser()
:m_parseSDF(false), :m_parseSDF(false),
m_activeSdfModel(-1) m_activeSdfModel(-1)
{ {
m_urdf2Model.m_sourceFile = "IN_MEMORY_STRING"; // if loadUrdf() called later, source file name will be replaced with real
} }
UrdfParser::~UrdfParser() UrdfParser::~UrdfParser()
{ {
cleanModel(&m_urdf2Model); cleanModel(&m_urdf2Model);
@@ -410,59 +410,68 @@ bool UrdfParser::parseGeometry(UrdfGeometry& geom, TiXmlElement* g, ErrorLogger*
geom.m_type = URDF_GEOM_CAPSULE; geom.m_type = URDF_GEOM_CAPSULE;
if (!shape->Attribute("length") || if (!shape->Attribute("length") ||
!shape->Attribute("radius")) !shape->Attribute("radius"))
{ {
logger->reportError("Capsule shape must have both length and radius attributes"); logger->reportError("Capsule shape must have both length and radius attributes");
return false; return false;
} }
geom.m_hasFromTo = false; geom.m_hasFromTo = false;
geom.m_capsuleRadius = urdfLexicalCast<double>(shape->Attribute("radius")); geom.m_capsuleRadius = urdfLexicalCast<double>(shape->Attribute("radius"));
geom.m_capsuleHalfHeight = btScalar(0.5)*urdfLexicalCast<double>(shape->Attribute("length")); geom.m_capsuleHalfHeight = btScalar(0.5)*urdfLexicalCast<double>(shape->Attribute("length"));
} }
else if (type_name == "mesh") else if (type_name == "mesh")
{ {
geom.m_type = URDF_GEOM_MESH; geom.m_type = URDF_GEOM_MESH;
if (m_parseSDF) geom.m_meshScale.setValue(1,1,1);
{ std::string fn;
TiXmlElement* scale = shape->FirstChildElement("scale");
if (0==scale)
{
geom.m_meshScale.setValue(1,1,1);
}
else
{
parseVector3(geom.m_meshScale,scale->GetText(),logger);
}
TiXmlElement* filename = shape->FirstChildElement("uri");
geom.m_meshFileName = filename->GetText();
}
else
{
if (!shape->Attribute("filename")) {
logger->reportError("Mesh must contain a filename attribute");
return false;
}
geom.m_meshFileName = shape->Attribute("filename");
geom.m_meshScale.setValue(1,1,1);
if (shape->Attribute("scale")) if (m_parseSDF)
{ {
if (!parseVector3(geom.m_meshScale,shape->Attribute("scale"),logger)) if (TiXmlElement* scale = shape->FirstChildElement("scale"))
{ {
logger->reportWarning("scale should be a vector3, not single scalar. Workaround activated.\n"); parseVector3(geom.m_meshScale,scale->GetText(),logger);
std::string scalar_str = shape->Attribute("scale"); }
double scaleFactor = urdfLexicalCast<double>(scalar_str.c_str()); if (TiXmlElement* filename = shape->FirstChildElement("uri"))
if (scaleFactor) {
{ fn = filename->GetText();
geom.m_meshScale.setValue(scaleFactor,scaleFactor,scaleFactor); }
} }
} else
} else {
{ // URDF
} if (shape->Attribute("filename"))
} {
fn = shape->Attribute("filename");
}
if (shape->Attribute("scale"))
{
if (!parseVector3(geom.m_meshScale, shape->Attribute("scale"), logger))
{
logger->reportWarning("Scale should be a vector3, not single scalar. Workaround activated.\n");
std::string scalar_str = shape->Attribute("scale");
double scaleFactor = urdfLexicalCast<double>(scalar_str.c_str());
if (scaleFactor)
{
geom.m_meshScale.setValue(scaleFactor, scaleFactor, scaleFactor);
}
}
}
}
if (fn.empty())
{
logger->reportError("Mesh filename is empty");
return false;
}
geom.m_meshFileName = fn;
bool success = findExistingMeshFile(
m_urdf2Model.m_sourceFile, fn, sourceFileLocation(shape),
&geom.m_meshFileName, &geom.m_meshFileType);
if (!success)
{
// warning already printed
return false;
}
} }
else else
{ {
@@ -845,7 +854,8 @@ bool UrdfParser::parseLink(UrdfModel& model, UrdfLink& link, TiXmlElement *confi
for (TiXmlElement* vis_xml = config->FirstChildElement("visual"); vis_xml; vis_xml = vis_xml->NextSiblingElement("visual")) for (TiXmlElement* vis_xml = config->FirstChildElement("visual"); vis_xml; vis_xml = vis_xml->NextSiblingElement("visual"))
{ {
UrdfVisual visual; UrdfVisual visual;
visual.m_sourceFileLocation = sourceFileLocation(vis_xml);
if (parseVisual(model, visual, vis_xml,logger)) if (parseVisual(model, visual, vis_xml,logger))
{ {
link.m_visualArray.push_back(visual); link.m_visualArray.push_back(visual);
@@ -864,6 +874,8 @@ bool UrdfParser::parseLink(UrdfModel& model, UrdfLink& link, TiXmlElement *confi
for (TiXmlElement* col_xml = config->FirstChildElement("collision"); col_xml; col_xml = col_xml->NextSiblingElement("collision")) for (TiXmlElement* col_xml = config->FirstChildElement("collision"); col_xml; col_xml = col_xml->NextSiblingElement("collision"))
{ {
UrdfCollision col; UrdfCollision col;
col.m_sourceFileLocation = sourceFileLocation(col_xml);
if (parseCollision(col, col_xml,logger)) if (parseCollision(col, col_xml,logger))
{ {
link.m_collisionArray.push_back(col); link.m_collisionArray.push_back(col);
@@ -1657,3 +1669,9 @@ bool UrdfParser::loadSDF(const char* sdfText, ErrorLogger* logger)
return true; return true;
} }
std::string UrdfParser::sourceFileLocation(TiXmlElement* e)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%s:%i", m_urdf2Model.m_sourceFile.c_str(), e->Row());
return buf;
}

View File

@@ -69,14 +69,25 @@ struct UrdfGeometry
double m_cylinderRadius; double m_cylinderRadius;
double m_cylinderLength; double m_cylinderLength;
btVector3 m_planeNormal; btVector3 m_planeNormal;
enum {
FILE_STL =1,
FILE_COLLADA =2,
FILE_OBJ =3,
};
int m_meshFileType;
std::string m_meshFileName; std::string m_meshFileName;
btVector3 m_meshScale; btVector3 m_meshScale;
}; };
bool findExistingMeshFile(const std::string& urdf_path, std::string fn,
const std::string& error_message_prefix,
std::string* out_found_filename, int* out_type); // intended to fill UrdfGeometry::m_meshFileName and Type, but can be used elsewhere
struct UrdfVisual struct UrdfVisual
{ {
std::string m_sourceFileLocation;
btTransform m_linkLocalFrame; btTransform m_linkLocalFrame;
UrdfGeometry m_geometry; UrdfGeometry m_geometry;
std::string m_name; std::string m_name;
@@ -90,6 +101,7 @@ struct UrdfVisual
struct UrdfCollision struct UrdfCollision
{ {
std::string m_sourceFileLocation;
btTransform m_linkLocalFrame; btTransform m_linkLocalFrame;
UrdfGeometry m_geometry; UrdfGeometry m_geometry;
std::string m_name; std::string m_name;
@@ -159,6 +171,7 @@ struct UrdfJoint
struct UrdfModel struct UrdfModel
{ {
std::string m_name; std::string m_name;
std::string m_sourceFile;
btTransform m_rootTransformInWorld; btTransform m_rootTransformInWorld;
btHashMap<btHashString, UrdfMaterial*> m_materials; btHashMap<btHashString, UrdfMaterial*> m_materials;
btHashMap<btHashString, UrdfLink*> m_links; btHashMap<btHashString, UrdfLink*> m_links;
@@ -204,7 +217,7 @@ public:
UrdfParser(); UrdfParser();
virtual ~UrdfParser(); virtual ~UrdfParser();
void setParseSDF(bool useSDF) void setParseSDF(bool useSDF)
{ {
m_parseSDF = useSDF; m_parseSDF = useSDF;
@@ -263,6 +276,13 @@ public:
} }
return m_urdf2Model; return m_urdf2Model;
} }
std::string sourceFileLocation(TiXmlElement* e);
void setSourceFile(const std::string& sourceFile)
{
m_urdf2Model.m_sourceFile = sourceFile;
}
}; };
#endif #endif

View File

@@ -36,13 +36,6 @@ subject to the following restrictions:
#include "../TinyRenderer/model.h" #include "../TinyRenderer/model.h"
#include "../ThirdPartyLibs/stb_image/stb_image.h" #include "../ThirdPartyLibs/stb_image/stb_image.h"
enum MyFileType
{
MY_FILE_STL=1,
MY_FILE_COLLADA=2,
MY_FILE_OBJ=3,
};
struct MyTexture2 struct MyTexture2
{ {
unsigned char* textureData; unsigned char* textureData;
@@ -241,226 +234,153 @@ void convertURDFToVisualShape(const UrdfVisual* visual, const char* urdfPathPref
convexColShape = sphereShape; convexColShape = sphereShape;
convexColShape->setMargin(0.001); convexColShape->setMargin(0.001);
break; break;
break;
} }
case URDF_GEOM_MESH: case URDF_GEOM_MESH:
{ {
if (visual->m_name.length()) strncpy(visualShapeOut.m_meshAssetFileName, visual->m_geometry.m_meshFileName.c_str(), VISUAL_SHAPE_MAX_PATH_LEN);
visualShapeOut.m_meshAssetFileName[VISUAL_SHAPE_MAX_PATH_LEN-1] = 0;
visualShapeOut.m_dimensions[0] = visual->m_geometry.m_meshScale[0];
visualShapeOut.m_dimensions[1] = visual->m_geometry.m_meshScale[1];
visualShapeOut.m_dimensions[2] = visual->m_geometry.m_meshScale[2];
visualShapeOut.m_localVisualFrame[0] = visual->m_linkLocalFrame.getOrigin()[0];
visualShapeOut.m_localVisualFrame[1] = visual->m_linkLocalFrame.getOrigin()[1];
visualShapeOut.m_localVisualFrame[2] = visual->m_linkLocalFrame.getOrigin()[2];
visualShapeOut.m_localVisualFrame[3] = visual->m_linkLocalFrame.getRotation()[0];
visualShapeOut.m_localVisualFrame[4] = visual->m_linkLocalFrame.getRotation()[1];
visualShapeOut.m_localVisualFrame[5] = visual->m_linkLocalFrame.getRotation()[2];
visualShapeOut.m_localVisualFrame[6] = visual->m_linkLocalFrame.getRotation()[3];
switch (visual->m_geometry.m_meshFileType)
{ {
//b3Printf("visual->name=%s\n", visual->m_name.c_str()); case UrdfGeometry::FILE_OBJ:
}
if (1)//visual->m_geometry)
{
if (visual->m_geometry.m_meshFileName.length())
{ {
const char* filename = visual->m_geometry.m_meshFileName.c_str(); //glmesh = LoadMeshFromObj(fullPath,visualPathPrefix);
//b3Printf("mesh->filename=%s\n", filename); b3ImportMeshData meshData;
char fullPath[1024]; if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(visual->m_geometry.m_meshFileName, meshData))
int fileType = 0;
char tmpPathPrefix[1024];
std::string xml_string;
int maxPathLen = 1024;
b3FileUtils::extractPath(filename,tmpPathPrefix,maxPathLen);
char visualPathPrefix[1024];
sprintf(visualPathPrefix,"%s%s",urdfPathPrefix,tmpPathPrefix);
sprintf(fullPath, "%s%s", urdfPathPrefix, filename);
b3FileUtils::toLower(fullPath);
if (strstr(fullPath, ".dae"))
{ {
fileType = MY_FILE_COLLADA;
}
if (strstr(fullPath, ".stl"))
{
fileType = MY_FILE_STL;
}
if (strstr(fullPath,".obj"))
{
fileType = MY_FILE_OBJ;
}
if (meshData.m_textureImage)
sprintf(fullPath, "%s%s", urdfPathPrefix, filename);
visualShapeOut.m_dimensions[0] = visual->m_geometry.m_meshScale[0];
visualShapeOut.m_dimensions[1] = visual->m_geometry.m_meshScale[1];
visualShapeOut.m_dimensions[2] = visual->m_geometry.m_meshScale[2];
visualShapeOut.m_localVisualFrame[0] = visual->m_linkLocalFrame.getOrigin()[0];
visualShapeOut.m_localVisualFrame[1] = visual->m_linkLocalFrame.getOrigin()[1];
visualShapeOut.m_localVisualFrame[2] = visual->m_linkLocalFrame.getOrigin()[2];
visualShapeOut.m_localVisualFrame[3] = visual->m_linkLocalFrame.getRotation()[0];
visualShapeOut.m_localVisualFrame[4] = visual->m_linkLocalFrame.getRotation()[1];
visualShapeOut.m_localVisualFrame[5] = visual->m_linkLocalFrame.getRotation()[2];
visualShapeOut.m_localVisualFrame[6] = visual->m_linkLocalFrame.getRotation()[3];
int sl = strlen(fullPath);
if (sl < (VISUAL_SHAPE_MAX_PATH_LEN-1))
{
memcpy(visualShapeOut.m_meshAssetFileName, fullPath, sl);
visualShapeOut.m_meshAssetFileName[sl] = 0;
}
FILE* f = fopen(fullPath, "rb");
if (f)
{
fclose(f);
switch (fileType)
{ {
case MY_FILE_OBJ: MyTexture2 texData;
{ texData.m_width = meshData.m_textureWidth;
//glmesh = LoadMeshFromObj(fullPath,visualPathPrefix); texData.m_height = meshData.m_textureHeight;
b3ImportMeshData meshData; texData.textureData = meshData.m_textureImage;
if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(fullPath, meshData)) texturesOut.push_back(texData);
{
if (meshData.m_textureImage)
{
MyTexture2 texData;
texData.m_width = meshData.m_textureWidth;
texData.m_height = meshData.m_textureHeight;
texData.textureData = meshData.m_textureImage;
texturesOut.push_back(texData);
}
glmesh = meshData.m_gfxShape;
}
break;
}
case MY_FILE_STL:
{
glmesh = LoadMeshFromSTL(fullPath);
break;
} }
case MY_FILE_COLLADA: glmesh = meshData.m_gfxShape;
}
break;
}
case UrdfGeometry::FILE_STL:
glmesh = LoadMeshFromSTL(visual->m_geometry.m_meshFileName.c_str());
break;
case UrdfGeometry::FILE_COLLADA:
{
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes;
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans; upAxisTrans.setIdentity();
float unitMeterScaling = 1;
int upAxis = 2;
LoadMeshFromCollada(visual->m_geometry.m_meshFileName.c_str(),
visualShapes,
visualShapeInstances,
upAxisTrans,
unitMeterScaling,
upAxis);
glmesh = new GLInstanceGraphicsShape;
// int index = 0;
glmesh->m_indices = new b3AlignedObjectArray<int>();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i = 0; i<visualShapeInstances.size(); i++)
{
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
b3AlignedObjectArray<GLInstanceVertex> verts;
verts.resize(gfxShape->m_vertices->size());
int baseIndex = glmesh->m_vertices->size();
for (int i = 0; i<gfxShape->m_vertices->size(); i++)
{ {
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
btAlignedObjectArray<GLInstanceGraphicsShape> visualShapes; }
btAlignedObjectArray<ColladaGraphicsInstance> visualShapeInstances;
btTransform upAxisTrans; upAxisTrans.setIdentity();
float unitMeterScaling = 1;
int upAxis = 2;
LoadMeshFromCollada(fullPath, int curNumIndices = glmesh->m_indices->size();
visualShapes, int additionalIndices = gfxShape->m_indices->size();
visualShapeInstances, glmesh->m_indices->resize(curNumIndices + additionalIndices);
upAxisTrans, for (int k = 0; k<additionalIndices; k++)
unitMeterScaling, {
upAxis); glmesh->m_indices->at(curNumIndices + k) = gfxShape->m_indices->at(k) + baseIndex;
}
glmesh = new GLInstanceGraphicsShape; //compensate upAxisTrans and unitMeterScaling here
// int index = 0; btMatrix4x4 upAxisMat;
glmesh->m_indices = new b3AlignedObjectArray<int>(); upAxisMat.setIdentity();
glmesh->m_vertices = new b3AlignedObjectArray<GLInstanceVertex>();
for (int i = 0; i<visualShapeInstances.size(); i++)
{
ColladaGraphicsInstance* instance = &visualShapeInstances[i];
GLInstanceGraphicsShape* gfxShape = &visualShapes[instance->m_shapeIndex];
b3AlignedObjectArray<GLInstanceVertex> verts;
verts.resize(gfxShape->m_vertices->size());
int baseIndex = glmesh->m_vertices->size();
for (int i = 0; i<gfxShape->m_vertices->size(); i++)
{
verts[i].normal[0] = gfxShape->m_vertices->at(i).normal[0];
verts[i].normal[1] = gfxShape->m_vertices->at(i).normal[1];
verts[i].normal[2] = gfxShape->m_vertices->at(i).normal[2];
verts[i].uv[0] = gfxShape->m_vertices->at(i).uv[0];
verts[i].uv[1] = gfxShape->m_vertices->at(i).uv[1];
verts[i].xyzw[0] = gfxShape->m_vertices->at(i).xyzw[0];
verts[i].xyzw[1] = gfxShape->m_vertices->at(i).xyzw[1];
verts[i].xyzw[2] = gfxShape->m_vertices->at(i).xyzw[2];
verts[i].xyzw[3] = gfxShape->m_vertices->at(i).xyzw[3];
}
int curNumIndices = glmesh->m_indices->size();
int additionalIndices = gfxShape->m_indices->size();
glmesh->m_indices->resize(curNumIndices + additionalIndices);
for (int k = 0; k<additionalIndices; k++)
{
glmesh->m_indices->at(curNumIndices + k) = gfxShape->m_indices->at(k) + baseIndex;
}
//compensate upAxisTrans and unitMeterScaling here
btMatrix4x4 upAxisMat;
upAxisMat.setIdentity();
// upAxisMat.setPureRotation(upAxisTrans.getRotation()); // upAxisMat.setPureRotation(upAxisTrans.getRotation());
btMatrix4x4 unitMeterScalingMat; btMatrix4x4 unitMeterScalingMat;
unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling, unitMeterScaling, unitMeterScaling)); unitMeterScalingMat.setPureScaling(btVector3(unitMeterScaling, unitMeterScaling, unitMeterScaling));
btMatrix4x4 worldMat = unitMeterScalingMat*upAxisMat*instance->m_worldTransform; btMatrix4x4 worldMat = unitMeterScalingMat*upAxisMat*instance->m_worldTransform;
//btMatrix4x4 worldMat = instance->m_worldTransform; //btMatrix4x4 worldMat = instance->m_worldTransform;
int curNumVertices = glmesh->m_vertices->size(); int curNumVertices = glmesh->m_vertices->size();
int additionalVertices = verts.size(); int additionalVertices = verts.size();
glmesh->m_vertices->reserve(curNumVertices + additionalVertices); glmesh->m_vertices->reserve(curNumVertices + additionalVertices);
for (int v = 0; v<verts.size(); v++) for (int v = 0; v<verts.size(); v++)
{
btVector3 pos(verts[v].xyzw[0], verts[v].xyzw[1], verts[v].xyzw[2]);
pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
verts[v].xyzw[2] = float(pos[2]);
glmesh->m_vertices->push_back(verts[v]);
}
}
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(fullPath);
break;
}
default:
{ {
b3Warning("Error: unsupported file type for Visual mesh: %s\n", fullPath); btVector3 pos(verts[v].xyzw[0], verts[v].xyzw[1], verts[v].xyzw[2]);
btAssert(0); pos = worldMat*pos;
verts[v].xyzw[0] = float(pos[0]);
verts[v].xyzw[1] = float(pos[1]);
verts[v].xyzw[2] = float(pos[2]);
glmesh->m_vertices->push_back(verts[v]);
} }
}
if (glmesh && glmesh->m_vertices && (glmesh->m_numvertices>0))
{
//apply the geometry scaling
for (int i=0;i<glmesh->m_vertices->size();i++)
{
glmesh->m_vertices->at(i).xyzw[0] *= visual->m_geometry.m_meshScale[0];
glmesh->m_vertices->at(i).xyzw[1] *= visual->m_geometry.m_meshScale[1];
glmesh->m_vertices->at(i).xyzw[2] *= visual->m_geometry.m_meshScale[2];
}
}
else
{
b3Warning("issue extracting mesh from COLLADA/STL file %s\n", fullPath);
}
}
else
{
b3Warning("mesh geometry not found %s\n", fullPath);
} }
glmesh->m_numIndices = glmesh->m_indices->size();
glmesh->m_numvertices = glmesh->m_vertices->size();
//glmesh = LoadMeshFromCollada(visual->m_geometry.m_meshFileName.c_str());
break;
}
default:
// should never get here (findExistingMeshFile returns false if it doesn't recognize extension)
btAssert(0);
}
if (glmesh && glmesh->m_vertices && (glmesh->m_numvertices>0))
{
//apply the geometry scaling
for (int i=0;i<glmesh->m_vertices->size();i++)
{
glmesh->m_vertices->at(i).xyzw[0] *= visual->m_geometry.m_meshScale[0];
glmesh->m_vertices->at(i).xyzw[1] *= visual->m_geometry.m_meshScale[1];
glmesh->m_vertices->at(i).xyzw[2] *= visual->m_geometry.m_meshScale[2];
} }
} }
else
{
b3Warning("issue extracting mesh from COLLADA/STL file %s\n", visual->m_geometry.m_meshFileName.c_str());
}
break; break;
} } // case mesh
default: default:
{ {
b3Warning("Error: unknown visual geometry type\n"); b3Warning("TinyRenderer: unknown visual geometry type %i\n", visual->m_geometry.m_type);
} }
} }

View File

@@ -507,6 +507,16 @@ LoadObj(
const char* filename, const char* filename,
const char* mtl_basepath) const char* mtl_basepath)
{ {
std::string tmp = filename;
if (!mtl_basepath) {
int last_slash = 0;
for (int c=0; c<(int)tmp.size(); ++c)
if (tmp[c]=='/' || tmp[c]=='\\')
last_slash = c;
tmp = tmp.substr(0, last_slash);
mtl_basepath = tmp.c_str();
//fprintf(stderr, "MTL PATH '%s' orig '%s'\n", mtl_basepath, filename);
}
shapes.resize(0); shapes.resize(0);
std::vector<vertex_index> allIndices; std::vector<vertex_index> allIndices;