Implement InMemoryFile for memory caching for fileIO plugin.

Support SDF loading through fileIO plugin.
Replace strcspn by C code (not crossplatform)
Add flag for loadURDF to use color from MTL file (instead from URDF link material)
pybullet.URDF_USE_MATERIAL_COLORS_FROM_MTL and pybullet.URDF_USE_MATERIAL_TRANSPARANCY_FROM_MTL
This commit is contained in:
erwincoumans
2018-10-14 12:54:34 -07:00
parent 3309ce8f6a
commit c1e20c448f
12 changed files with 511 additions and 66 deletions

View File

@@ -53,6 +53,7 @@ bool b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(const std::string&
meshData.m_textureImage1 = 0; meshData.m_textureImage1 = 0;
meshData.m_textureHeight = 0; meshData.m_textureHeight = 0;
meshData.m_textureWidth = 0; meshData.m_textureWidth = 0;
meshData.m_flags = 0;
meshData.m_isCached = false; meshData.m_isCached = false;
char relativeFileName[1024]; char relativeFileName[1024];
@@ -78,6 +79,18 @@ bool b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(const std::string&
for (int i = 0; meshData.m_textureImage1 == 0 && i < shapes.size(); i++) for (int i = 0; meshData.m_textureImage1 == 0 && i < shapes.size(); i++)
{ {
const tinyobj::shape_t& shape = shapes[i]; const tinyobj::shape_t& shape = shapes[i];
meshData.m_rgbaColor[0] = shape.material.diffuse[0];
meshData.m_rgbaColor[1] = shape.material.diffuse[1];
meshData.m_rgbaColor[2] = shape.material.diffuse[2];
meshData.m_rgbaColor[3] = shape.material.transparency;
meshData.m_flags |= B3_IMPORT_MESH_HAS_RGBA_COLOR;
meshData.m_specularColor[0] = shape.material.specular[0];
meshData.m_specularColor[1] = shape.material.specular[1];
meshData.m_specularColor[2] = shape.material.specular[2];
meshData.m_specularColor[3] = 1;
meshData.m_flags |= B3_IMPORT_MESH_HAS_SPECULAR_COLOR;
if (shape.material.diffuse_texname.length() > 0) if (shape.material.diffuse_texname.length() > 0)
{ {
int width, height, n; int width, height, n;

View File

@@ -3,6 +3,12 @@
#include <string> #include <string>
enum b3ImportMeshDataFlags
{
B3_IMPORT_MESH_HAS_RGBA_COLOR=1,
B3_IMPORT_MESH_HAS_SPECULAR_COLOR=2,
};
struct b3ImportMeshData struct b3ImportMeshData
{ {
struct GLInstanceGraphicsShape* m_gfxShape; struct GLInstanceGraphicsShape* m_gfxShape;
@@ -11,6 +17,20 @@ struct b3ImportMeshData
bool m_isCached; bool m_isCached;
int m_textureWidth; int m_textureWidth;
int m_textureHeight; int m_textureHeight;
double m_rgbaColor[4];
double m_specularColor[4];
int m_flags;
b3ImportMeshData()
:m_gfxShape(0),
m_textureImage1(0),
m_isCached(false),
m_textureWidth(0),
m_textureHeight(0),
m_flags(0)
{
}
}; };
class b3ImportMeshUtility class b3ImportMeshUtility

View File

@@ -228,24 +228,36 @@ bool BulletURDFImporter::loadSDF(const char* fileName, bool forceFixedBase)
} }
else else
{ {
char path[1024]; char path[1024];
fu.extractPath(relativeFileName, path, sizeof(path)); fu.extractPath(relativeFileName, path, sizeof(path));
m_data->setSourceFile(relativeFileName, path); m_data->setSourceFile(relativeFileName, path);
std::fstream xml_file(relativeFileName, std::fstream::in); //read file
while (xml_file.good()) int fileId = m_data->m_fileIO->fileOpen(relativeFileName,"r");
char destBuffer[8192];
char* line = 0;
do
{ {
std::string line; line = m_data->m_fileIO->readLine(fileId, destBuffer, 8192);
std::getline(xml_file, line); if (line)
xml_string += (line + "\n"); {
xml_string += (std::string(destBuffer) + "\n");
}
} }
xml_file.close(); while (line);
m_data->m_fileIO->fileClose(fileId);
} }
BulletErrorLogger loggie; BulletErrorLogger loggie;
//todo: quick test to see if we can re-use the URDF parser for SDF or not //todo: quick test to see if we can re-use the URDF parser for SDF or not
m_data->m_urdfParser.setParseSDF(true); m_data->m_urdfParser.setParseSDF(true);
bool result = m_data->m_urdfParser.loadSDF(xml_string.c_str(), &loggie); bool result = false;
if (xml_string.length())
{
result = m_data->m_urdfParser.loadSDF(xml_string.c_str(), &loggie);
}
return result; return result;
} }
@@ -861,7 +873,7 @@ btCollisionShape* BulletURDFImporter::convertURDFToCollisionShape(const UrdfColl
return shape; return shape;
} }
void BulletURDFImporter::convertURDFToVisualShapeInternal(const UrdfVisual* visual, const char* urdfPathPrefix, const btTransform& visualTransform, btAlignedObjectArray<GLInstanceVertex>& verticesOut, btAlignedObjectArray<int>& indicesOut, btAlignedObjectArray<BulletURDFTexture>& texturesOut) const void BulletURDFImporter::convertURDFToVisualShapeInternal(const UrdfVisual* visual, const char* urdfPathPrefix, const btTransform& visualTransform, btAlignedObjectArray<GLInstanceVertex>& verticesOut, btAlignedObjectArray<int>& indicesOut, btAlignedObjectArray<BulletURDFTexture>& texturesOut, struct b3ImportMeshData& meshData) const
{ {
BT_PROFILE("convertURDFToVisualShapeInternal"); BT_PROFILE("convertURDFToVisualShapeInternal");
@@ -920,7 +932,7 @@ void BulletURDFImporter::convertURDFToVisualShapeInternal(const UrdfVisual* visu
{ {
case UrdfGeometry::FILE_OBJ: case UrdfGeometry::FILE_OBJ:
{ {
b3ImportMeshData meshData;
if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(visual->m_geometry.m_meshFileName, meshData, m_data->m_fileIO)) if (b3ImportMeshUtility::loadAndRegisterMeshFromFileInternal(visual->m_geometry.m_meshFileName, meshData, m_data->m_fileIO))
{ {
if (meshData.m_textureImage1) if (meshData.m_textureImage1)
@@ -1150,16 +1162,49 @@ int BulletURDFImporter::convertLinkVisualShapes(int linkIndex, const char* pathP
btTransform childTrans = vis.m_linkLocalFrame; btTransform childTrans = vis.m_linkLocalFrame;
btHashString matName(vis.m_materialName.c_str()); btHashString matName(vis.m_materialName.c_str());
UrdfMaterial* const* matPtr = model.m_materials[matName]; UrdfMaterial* const* matPtr = model.m_materials[matName];
if (matPtr) b3ImportMeshData meshData;
convertURDFToVisualShapeInternal(&vis, pathPrefix, localInertiaFrame.inverse() * childTrans, vertices, indices, textures,meshData);
if (m_data->m_flags&CUF_USE_MATERIAL_COLORS_FROM_MTL)
{ {
UrdfMaterial* const mat = *matPtr; if ((meshData.m_flags & B3_IMPORT_MESH_HAS_RGBA_COLOR) &&
//printf("UrdfMaterial %s, rgba = %f,%f,%f,%f\n",mat->m_name.c_str(),mat->m_rgbaColor[0],mat->m_rgbaColor[1],mat->m_rgbaColor[2],mat->m_rgbaColor[3]); (meshData.m_flags & B3_IMPORT_MESH_HAS_SPECULAR_COLOR))
UrdfMaterialColor matCol; {
matCol.m_rgbaColor = mat->m_matColor.m_rgbaColor; UrdfMaterialColor matCol;
matCol.m_specularColor = mat->m_matColor.m_specularColor;
m_data->m_linkColors.insert(linkIndex, matCol); if (m_data->m_flags&CUF_USE_MATERIAL_TRANSPARANCY_FROM_MTL)
{
matCol.m_rgbaColor.setValue(meshData.m_rgbaColor[0],
meshData.m_rgbaColor[1],
meshData.m_rgbaColor[2],
meshData.m_rgbaColor[3]);
} else
{
matCol.m_rgbaColor.setValue(meshData.m_rgbaColor[0],
meshData.m_rgbaColor[1],
meshData.m_rgbaColor[2],
1);
}
matCol.m_specularColor.setValue(meshData.m_specularColor[0],
meshData.m_specularColor[1],
meshData.m_specularColor[2]);
m_data->m_linkColors.insert(linkIndex, matCol);
}
} else
{
if (matPtr)
{
UrdfMaterial* const mat = *matPtr;
//printf("UrdfMaterial %s, rgba = %f,%f,%f,%f\n",mat->m_name.c_str(),mat->m_rgbaColor[0],mat->m_rgbaColor[1],mat->m_rgbaColor[2],mat->m_rgbaColor[3]);
UrdfMaterialColor matCol;
matCol.m_rgbaColor = mat->m_matColor.m_rgbaColor;
matCol.m_specularColor = mat->m_matColor.m_specularColor;
m_data->m_linkColors.insert(linkIndex, matCol);
}
} }
convertURDFToVisualShapeInternal(&vis, pathPrefix, localInertiaFrame.inverse() * childTrans, vertices, indices, textures);
} }
} }
if (vertices.size() && indices.size()) if (vertices.size() && indices.size())

View File

@@ -88,7 +88,7 @@ public:
virtual int getAllocatedTexture(int index) const; virtual int getAllocatedTexture(int index) const;
virtual void setEnableTinyRenderer(bool enable); virtual void setEnableTinyRenderer(bool enable);
void convertURDFToVisualShapeInternal(const struct UrdfVisual* visual, const char* urdfPathPrefix, const class btTransform& visualTransform, btAlignedObjectArray<struct GLInstanceVertex>& verticesOut, btAlignedObjectArray<int>& indicesOut, btAlignedObjectArray<struct BulletURDFTexture>& texturesOut) const; void convertURDFToVisualShapeInternal(const struct UrdfVisual* visual, const char* urdfPathPrefix, const class btTransform& visualTransform, btAlignedObjectArray<struct GLInstanceVertex>& verticesOut, btAlignedObjectArray<int>& indicesOut, btAlignedObjectArray<struct BulletURDFTexture>& texturesOut, struct b3ImportMeshData& meshData) const;
}; };
#endif //BULLET_URDF_IMPORTER_H #endif //BULLET_URDF_IMPORTER_H

View File

@@ -32,6 +32,8 @@ enum ConvertURDFFlags
CUF_INITIALIZE_SAT_FEATURES = 4096, CUF_INITIALIZE_SAT_FEATURES = 4096,
CUF_USE_SELF_COLLISION_INCLUDE_PARENT = 8192, CUF_USE_SELF_COLLISION_INCLUDE_PARENT = 8192,
CUF_PARSE_SENSORS = 16384, CUF_PARSE_SENSORS = 16384,
CUF_USE_MATERIAL_COLORS_FROM_MTL = 32768,
CUF_USE_MATERIAL_TRANSPARANCY_FROM_MTL = 64738,
}; };
struct UrdfVisualShapeCache struct UrdfVisualShapeCache

View File

@@ -74,16 +74,8 @@ static bool UrdfFindMeshFile(
std::string existing_file; std::string existing_file;
{
std::string attempt = fn;
int f = fileIO->fileOpen(attempt.c_str(), "rb");
if (f>=0)
{
existing_file = attempt;
fileIO->fileClose(f);
}
}
if (existing_file.empty())
{ {
for (std::list<std::string>::iterator x = shorter.begin(); x != shorter.end(); ++x) for (std::list<std::string>::iterator x = shorter.begin(); x != shorter.end(); ++x)
{ {
@@ -100,6 +92,16 @@ static bool UrdfFindMeshFile(
break; break;
} }
} }
if (existing_file.empty())
{
std::string attempt = fn;
int f = fileIO->fileOpen(attempt.c_str(), "rb");
if (f>=0)
{
existing_file = attempt;
fileIO->fileClose(f);
}
}
if (existing_file.empty()) if (existing_file.empty())
{ {

View File

@@ -9,7 +9,7 @@
#include "../Extras/InverseDynamics/btMultiBodyTreeCreator.hpp" #include "../Extras/InverseDynamics/btMultiBodyTreeCreator.hpp"
#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h" #include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
#include "../Importers/ImportMeshUtility/b3ImportMeshUtility.h"
#include "BulletDynamics/MLCPSolvers/btDantzigSolver.h" #include "BulletDynamics/MLCPSolvers/btDantzigSolver.h"
#include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h" #include "BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h"
#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h" #include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h"
@@ -2016,11 +2016,13 @@ struct ProgrammaticUrdfInterface : public URDFImporterInterface
const b3CreateMultiBodyArgs& m_createBodyArgs; const b3CreateMultiBodyArgs& m_createBodyArgs;
mutable b3AlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes; mutable b3AlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
PhysicsServerCommandProcessorInternalData* m_data; PhysicsServerCommandProcessorInternalData* m_data;
int m_flags;
ProgrammaticUrdfInterface(const b3CreateMultiBodyArgs& bodyArgs, PhysicsServerCommandProcessorInternalData* data) ProgrammaticUrdfInterface(const b3CreateMultiBodyArgs& bodyArgs, PhysicsServerCommandProcessorInternalData* data, int flags)
: m_bodyUniqueId(-1), : m_bodyUniqueId(-1),
m_createBodyArgs(bodyArgs), m_createBodyArgs(bodyArgs),
m_data(data) m_data(data),
m_flags(flags)
{ {
} }
@@ -2068,19 +2070,38 @@ struct ProgrammaticUrdfInterface : public URDFImporterInterface
return false; return false;
} }
mutable btHashMap<btHashInt, UrdfMaterialColor> m_linkColors;
virtual bool getLinkColor2(int linkIndex, struct UrdfMaterialColor& matCol) const virtual bool getLinkColor2(int linkIndex, struct UrdfMaterialColor& matCol) const
{ {
if (m_createBodyArgs.m_linkVisualShapeUniqueIds[linkIndex] >= 0)
if (m_flags & URDF_USE_MATERIAL_COLORS_FROM_MTL)
{ {
const InternalVisualShapeHandle* visHandle = m_data->m_userVisualShapeHandles.getHandle(m_createBodyArgs.m_linkVisualShapeUniqueIds[linkIndex]); const UrdfMaterialColor* matColPtr = m_linkColors[linkIndex];
if (visHandle) if (matColPtr)
{ {
for (int i = 0; i < visHandle->m_visualShapes.size(); i++) matCol = *matColPtr;
if ((m_flags&CUF_USE_MATERIAL_TRANSPARANCY_FROM_MTL)==0)
{ {
if (visHandle->m_visualShapes[i].m_geometry.m_hasLocalMaterial) matCol.m_rgbaColor[3] = 1;
}
return true;
}
} else
{
if (m_createBodyArgs.m_linkVisualShapeUniqueIds[linkIndex] >= 0)
{
const InternalVisualShapeHandle* visHandle = m_data->m_userVisualShapeHandles.getHandle(m_createBodyArgs.m_linkVisualShapeUniqueIds[linkIndex]);
if (visHandle)
{
for (int i = 0; i < visHandle->m_visualShapes.size(); i++)
{ {
matCol = visHandle->m_visualShapes[i].m_geometry.m_localMaterial.m_matColor; if (visHandle->m_visualShapes[i].m_geometry.m_hasLocalMaterial)
return true; {
matCol = visHandle->m_visualShapes[i].m_geometry.m_localMaterial.m_matColor;
return true;
}
} }
} }
} }
@@ -2274,7 +2295,21 @@ struct ProgrammaticUrdfInterface : public URDFImporterInterface
{ {
for (int v = 0; v < visHandle->m_visualShapes.size(); v++) for (int v = 0; v < visHandle->m_visualShapes.size(); v++)
{ {
u2b.convertURDFToVisualShapeInternal(&visHandle->m_visualShapes[v], pathPrefix, localInertiaFrame.inverse() * visHandle->m_visualShapes[v].m_linkLocalFrame, vertices, indices, textures); b3ImportMeshData meshData;
u2b.convertURDFToVisualShapeInternal(&visHandle->m_visualShapes[v], pathPrefix, localInertiaFrame.inverse() * visHandle->m_visualShapes[v].m_linkLocalFrame, vertices, indices, textures, meshData);
if ((meshData.m_flags & B3_IMPORT_MESH_HAS_RGBA_COLOR) &&
(meshData.m_flags & B3_IMPORT_MESH_HAS_SPECULAR_COLOR))
{
UrdfMaterialColor matCol;
matCol.m_rgbaColor.setValue(meshData.m_rgbaColor[0],
meshData.m_rgbaColor[1],
meshData.m_rgbaColor[2],
meshData.m_rgbaColor[3]);
matCol.m_specularColor.setValue(meshData.m_specularColor[0],
meshData.m_specularColor[1],
meshData.m_specularColor[2]);
m_linkColors.insert(linkIndex, matCol);
}
} }
if (vertices.size() && indices.size()) if (vertices.size() && indices.size())
@@ -4462,6 +4497,7 @@ bool PhysicsServerCommandProcessor::processCreateVisualShapeCommand(const struct
} }
else else
{ {
visualShape.m_geometry.m_localMaterial.m_matColor.m_rgbaColor.setValue(1,1,1,1);
} }
if (hasSpecular) if (hasSpecular)
{ {
@@ -6641,7 +6677,14 @@ bool PhysicsServerCommandProcessor::processCreateMultiBodyCommand(const struct S
{ {
m_data->m_sdfRecentLoadedBodies.clear(); m_data->m_sdfRecentLoadedBodies.clear();
ProgrammaticUrdfInterface u2b(clientCmd.m_createMultiBodyArgs, m_data); int flags = 0;
if (clientCmd.m_updateFlags & MULT_BODY_HAS_FLAGS)
{
flags = clientCmd.m_createMultiBodyArgs.m_flags;
}
ProgrammaticUrdfInterface u2b(clientCmd.m_createMultiBodyArgs, m_data, flags);
bool useMultiBody = true; bool useMultiBody = true;
if (clientCmd.m_updateFlags & MULT_BODY_USE_MAXIMAL_COORDINATES) if (clientCmd.m_updateFlags & MULT_BODY_USE_MAXIMAL_COORDINATES)
@@ -6649,12 +6692,7 @@ bool PhysicsServerCommandProcessor::processCreateMultiBodyCommand(const struct S
useMultiBody = false; useMultiBody = false;
} }
int flags = 0;
if (clientCmd.m_updateFlags & MULT_BODY_HAS_FLAGS)
{
flags = clientCmd.m_createMultiBodyArgs.m_flags;
}
bool ok = processImportedObjects("memory", bufferServerToClient, bufferSizeInBytes, useMultiBody, flags, u2b); bool ok = processImportedObjects("memory", bufferServerToClient, bufferSizeInBytes, useMultiBody, flags, u2b);

View File

@@ -819,6 +819,8 @@ enum eURDF_Flags
URDF_INITIALIZE_SAT_FEATURES = 4096, URDF_INITIALIZE_SAT_FEATURES = 4096,
URDF_USE_SELF_COLLISION_INCLUDE_PARENT = 8192, URDF_USE_SELF_COLLISION_INCLUDE_PARENT = 8192,
URDF_PARSE_SENSORS = 16384, URDF_PARSE_SENSORS = 16384,
URDF_USE_MATERIAL_COLORS_FROM_MTL = 32768,
URDF_USE_MATERIAL_TRANSPARANCY_FROM_MTL = 64738,
}; };
enum eUrdfGeomTypes //sync with UrdfParser UrdfGeomTypes enum eUrdfGeomTypes //sync with UrdfParser UrdfGeomTypes

View File

@@ -6,7 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include "../../../CommonInterfaces/CommonFileIOInterface.h" #include "../../../CommonInterfaces/CommonFileIOInterface.h"
#include "../../../Utils/b3ResourcePath.h" #include "../../../Utils/b3ResourcePath.h"
#include "Bullet3Common/b3HashMap.h"
#ifndef B3_EXCLUDE_DEFAULT_FILEIO #ifndef B3_EXCLUDE_DEFAULT_FILEIO
#include "../../../Utils/b3BulletDefaultFileIO.h" #include "../../../Utils/b3BulletDefaultFileIO.h"
@@ -30,13 +30,258 @@ struct WrapperFileHandle
int m_childFileHandle; int m_childFileHandle;
}; };
struct InMemoryFile
{
char* m_buffer;
int m_fileSize;
};
struct InMemoryFileAccessor
{
InMemoryFile* m_file;
int m_curPos;
};
struct InMemoryFileIO : public CommonFileIOInterface
{
b3HashMap<b3HashString,InMemoryFile*> m_fileCache;
InMemoryFileAccessor m_fileHandles[B3_MAX_FILEIO_INTERFACES];
InMemoryFileIO()
{
for (int i=0;i<B3_FILEIO_MAX_FILES;i++)
{
m_fileHandles[i].m_curPos = 0;
m_fileHandles[i].m_file = 0;
}
}
virtual ~InMemoryFileIO()
{
clearCache();
}
void clearCache()
{
for (int i=0;i<m_fileCache.size();i++)
{
InMemoryFile** memPtr = m_fileCache.getAtIndex(i);
if (memPtr && *memPtr)
{
InMemoryFile* mem = *memPtr;
freeBuffer(mem->m_buffer);
delete (mem);
}
}
}
char* allocateBuffer(int len)
{
char* buffer = 0;
if (len)
{
buffer = new char[len];
}
return buffer;
}
void freeBuffer(char* buffer)
{
delete[] buffer;
}
virtual int registerFile(const char* fileName, char* buffer, int len)
{
InMemoryFile* f = new InMemoryFile();
f->m_buffer = buffer;
f->m_fileSize = len;
b3HashString key(fileName);
m_fileCache.insert(key,f);
return 0;
}
void removeFileFromCache(const char* fileName)
{
InMemoryFile* f = getInMemoryFile(fileName);
if (f)
{
m_fileCache.remove(fileName);
freeBuffer(f->m_buffer);
delete (f);
}
}
InMemoryFile* getInMemoryFile(const char* fileName)
{
InMemoryFile** fPtr = m_fileCache[fileName];
if (fPtr && *fPtr)
{
return *fPtr;
}
return 0;
}
virtual int fileOpen(const char* fileName, const char* mode)
{
//search a free slot
int slot = -1;
for (int i=0;i<B3_FILEIO_MAX_FILES;i++)
{
if (m_fileHandles[i].m_file==0)
{
slot=i;
break;
}
}
if (slot>=0)
{
InMemoryFile* f = getInMemoryFile(fileName);
if (f)
{
m_fileHandles[slot].m_curPos = 0;
m_fileHandles[slot].m_file = f;
} else
{
slot=-1;
}
}
//printf("InMemoryFileIO fileOpen %s, %d\n", fileName, slot);
return slot;
}
virtual int fileRead(int fileHandle, char* destBuffer, int numBytes)
{
if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES)
{
InMemoryFileAccessor& f = m_fileHandles[fileHandle];
if (f.m_file)
{
//if (numBytes>1)
// printf("curPos = %d\n", f.m_curPos);
if (f.m_curPos+numBytes <= f.m_file->m_fileSize)
{
memcpy(destBuffer,f.m_file->m_buffer+f.m_curPos,numBytes);
f.m_curPos+=numBytes;
//if (numBytes>1)
// printf("read %d bytes, now curPos = %d\n", numBytes, f.m_curPos);
return numBytes;
} else
{
if (numBytes!=1)
{
printf("InMemoryFileIO::fileRead Attempt to read beyond end of file\n");
}
}
}
}
return 0;
}
virtual int fileWrite(int fileHandle,const char* sourceBuffer, int numBytes)
{
return 0;
}
virtual void fileClose(int fileHandle)
{
if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES)
{
InMemoryFileAccessor& f = m_fileHandles[fileHandle];
if (f.m_file)
{
m_fileHandles[fileHandle].m_file = 0;
m_fileHandles[fileHandle].m_curPos = 0;
//printf("InMemoryFileIO fileClose %d\n", fileHandle);
}
}
}
virtual bool findResourcePath(const char* fileName, char* resourcePathOut, int resourcePathMaxNumBytes)
{
InMemoryFile* f = getInMemoryFile(fileName);
int fileNameLen = strlen(fileName);
if (f && fileNameLen<(resourcePathMaxNumBytes-1))
{
memcpy(resourcePathOut, fileName, fileNameLen);
resourcePathOut[fileNameLen]=0;
return true;
}
return false;
}
virtual char* readLine(int fileHandle, char* destBuffer, int numBytes)
{
int numRead = 0;
int endOfFile = 0;
if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES )
{
InMemoryFileAccessor& f = m_fileHandles[fileHandle];
if (f.m_file)
{
//return ::fgets(destBuffer, numBytes, m_fileHandles[fileHandle]);
char c = 0;
do
{
int bytesRead = fileRead(fileHandle,&c,1);
if (bytesRead != 1)
{
endOfFile = 1;
c=0;
}
if (c && c!='\n')
{
char a='\r';
if (c!=13)
{
destBuffer[numRead++]=c;
} else
{
destBuffer[numRead++]=0;
}
}
} while (c != 0 && c != '\n' && numRead<(numBytes-1));
}
}
if (numRead==0 && endOfFile)
{
return 0;
}
if (numRead<numBytes)
{
if (numRead >=0)
{
destBuffer[numRead]=0;
}
return &destBuffer[0];
} else
{
if (endOfFile==0)
{
printf("InMemoryFileIO::readLine readLine warning: numRead=%d, numBytes=%d\n", numRead, numBytes);
}
}
return 0;
}
virtual int getFileSize(int fileHandle)
{
if (fileHandle>=0 && fileHandle < B3_FILEIO_MAX_FILES )
{
InMemoryFileAccessor& f = m_fileHandles[fileHandle];
if (f.m_file)
{
return f.m_file->m_fileSize;
}
}
return 0;
}
};
struct WrapperFileIO : public CommonFileIOInterface struct WrapperFileIO : public CommonFileIOInterface
{ {
CommonFileIOInterface* m_availableFileIOInterfaces[B3_MAX_FILEIO_INTERFACES]; CommonFileIOInterface* m_availableFileIOInterfaces[B3_MAX_FILEIO_INTERFACES];
int m_numWrapperInterfaces; int m_numWrapperInterfaces;
WrapperFileHandle m_wrapperFileHandles[B3_MAX_FILEIO_INTERFACES]; WrapperFileHandle m_wrapperFileHandles[B3_MAX_FILEIO_INTERFACES];
InMemoryFileIO m_cachedFiles;
WrapperFileIO() WrapperFileIO()
:m_numWrapperInterfaces(0) :m_numWrapperInterfaces(0)
@@ -47,6 +292,7 @@ struct WrapperFileIO : public CommonFileIOInterface
m_wrapperFileHandles[i].childFileIO=0; m_wrapperFileHandles[i].childFileIO=0;
m_wrapperFileHandles[i].m_childFileHandle=0; m_wrapperFileHandles[i].m_childFileHandle=0;
} }
//addFileIOInterface(&m_cachedFiles);
} }
virtual ~WrapperFileIO() virtual ~WrapperFileIO()
@@ -86,6 +332,7 @@ struct WrapperFileIO : public CommonFileIOInterface
virtual int fileOpen(const char* fileName, const char* mode) virtual int fileOpen(const char* fileName, const char* mode)
{ {
//find an available wrapperFileHandle slot //find an available wrapperFileHandle slot
int wrapperFileHandle=-1; int wrapperFileHandle=-1;
int slot = -1; int slot = -1;
@@ -99,20 +346,76 @@ struct WrapperFileIO : public CommonFileIOInterface
} }
if (slot>=0) if (slot>=0)
{ {
//figure out what wrapper interface to use //first check the cache
//use the first one that can open the file int childHandle = m_cachedFiles.fileOpen(fileName, mode);
for (int i=0;i<B3_MAX_FILEIO_INTERFACES;i++) if (childHandle<0)
{ {
CommonFileIOInterface* childFileIO=m_availableFileIOInterfaces[i]; for (int i=0;i<B3_MAX_FILEIO_INTERFACES;i++)
if (childFileIO)
{ {
int childHandle = childFileIO->fileOpen(fileName, mode); CommonFileIOInterface* childFileIO=m_availableFileIOInterfaces[i];
if (childHandle>=0) if (childFileIO)
{ {
wrapperFileHandle = slot; int childHandle = childFileIO->fileOpen(fileName, mode);
m_wrapperFileHandles[slot].childFileIO = childFileIO; if (childHandle>=0)
m_wrapperFileHandles[slot].m_childFileHandle = childHandle; {
break; int fileSize = childFileIO->getFileSize(childHandle);
char* buffer = 0;
if (fileSize)
{
buffer = m_cachedFiles.allocateBuffer(fileSize);
if (buffer)
{
int readBytes = childFileIO->fileRead(childHandle, buffer, fileSize);
if (readBytes!=fileSize)
{
if (readBytes<fileSize)
{
fileSize = readBytes;
} else
{
printf("WrapperFileIO error: reading more bytes (%d) then reported file size (%d) of file %s.\n", readBytes, fileSize, fileName);
}
}
} else
{
fileSize=0;
}
}
//potentially register a zero byte file, or files that only can be read partially
m_cachedFiles.registerFile(fileName,buffer, fileSize);
childFileIO->fileClose(childHandle);
break;
}
}
}
}
{
int childHandle = m_cachedFiles.fileOpen(fileName, mode);
if (childHandle>=0)
{
wrapperFileHandle = slot;
m_wrapperFileHandles[slot].childFileIO = &m_cachedFiles;
m_wrapperFileHandles[slot].m_childFileHandle = childHandle;
} else
{
//figure out what wrapper interface to use
//use the first one that can open the file
for (int i=0;i<B3_MAX_FILEIO_INTERFACES;i++)
{
CommonFileIOInterface* childFileIO=m_availableFileIOInterfaces[i];
if (childFileIO)
{
int childHandle = childFileIO->fileOpen(fileName, mode);
if (childHandle>=0)
{
wrapperFileHandle = slot;
m_wrapperFileHandles[slot].childFileIO = childFileIO;
m_wrapperFileHandles[slot].m_childFileHandle = childHandle;
break;
}
}
} }
} }
} }
@@ -155,6 +458,9 @@ struct WrapperFileIO : public CommonFileIOInterface
} }
virtual bool findResourcePath(const char* fileName, char* resourcePathOut, int resourcePathMaxNumBytes) virtual bool findResourcePath(const char* fileName, char* resourcePathOut, int resourcePathMaxNumBytes)
{ {
if (m_cachedFiles.findResourcePath(fileName, resourcePathOut, resourcePathMaxNumBytes))
return true;
bool found = false; bool found = false;
for (int i=0;i<B3_MAX_FILEIO_INTERFACES;i++) for (int i=0;i<B3_MAX_FILEIO_INTERFACES;i++)
{ {
@@ -273,7 +579,7 @@ B3_SHARED_API int executePluginCommand_fileIOPlugin(struct b3PluginContext* cont
#ifdef B3_USE_ZIPFILE_FILEIO #ifdef B3_USE_ZIPFILE_FILEIO
if (arguments->m_text) if (arguments->m_text)
{ {
obj->m_fileIO.addFileIOInterface(new ZipFileIO(arguments->m_text)); obj->m_fileIO.addFileIOInterface(new ZipFileIO(arguments->m_text, &obj->m_fileIO));
} }
#else #else
printf("eZipFileIO is not enabled in this build.\n"); printf("eZipFileIO is not enabled in this build.\n");

View File

@@ -10,7 +10,7 @@ struct ZipFileIO : public CommonFileIOInterface
unzFile m_fileHandles[B3_ZIP_FILEIO_MAX_FILES ]; unzFile m_fileHandles[B3_ZIP_FILEIO_MAX_FILES ];
int m_numFileHandles; int m_numFileHandles;
ZipFileIO(const char* zipfileName) ZipFileIO(const char* zipfileName, CommonFileIOInterface* wrapperFileIO)
:m_zipfileName(zipfileName), :m_zipfileName(zipfileName),
m_numFileHandles(0) m_numFileHandles(0)
{ {
@@ -37,6 +37,7 @@ struct ZipFileIO : public CommonFileIOInterface
virtual int fileOpen(const char* fileName, const char* mode) virtual int fileOpen(const char* fileName, const char* mode)
{ {
//search a free slot //search a free slot
int slot = -1; int slot = -1;
for (int i=0;i<B3_ZIP_FILEIO_MAX_FILES ;i++) for (int i=0;i<B3_ZIP_FILEIO_MAX_FILES ;i++)
@@ -58,6 +59,7 @@ struct ZipFileIO : public CommonFileIOInterface
slot = -1; slot = -1;
} else } else
{ {
int result = 0; int result = 0;
result = unzGetGlobalInfo(zipfile, &m_global_info ); result = unzGetGlobalInfo(zipfile, &m_global_info );
if (result != UNZ_OK) if (result != UNZ_OK)
@@ -66,9 +68,6 @@ struct ZipFileIO : public CommonFileIOInterface
unzClose(zipfile); unzClose(zipfile);
zipfile = 0; zipfile = 0;
slot = -1; slot = -1;
} else
{
m_fileHandles[slot] = zipfile;
} }
} }
if (slot >=0) if (slot >=0)
@@ -82,20 +81,28 @@ struct ZipFileIO : public CommonFileIOInterface
{ {
printf("unzGetCurrentFileInfo() != UNZ_OK (%d)\n", result); printf("unzGetCurrentFileInfo() != UNZ_OK (%d)\n", result);
slot=-1; slot=-1;
unzClose(zipfile);
zipfile = 0;
} }
else else
{ {
result = unzOpenCurrentFile(zipfile); result = unzOpenCurrentFile(zipfile);
if (result == UNZ_OK) if (result == UNZ_OK)
{ {
printf("zipFile::fileOpen %s in mode %s in fileHandle %d\n", fileName, mode, slot);
m_fileHandles[slot] = zipfile;
} else } else
{ {
slot=-1; slot=-1;
unzClose(zipfile);
zipfile = 0;
} }
} }
} else } else
{ {
slot=-1; slot=-1;
unzClose(zipfile);
zipfile = 0;
} }
} }
} }
@@ -137,6 +144,7 @@ struct ZipFileIO : public CommonFileIOInterface
unzFile f = m_fileHandles[fileHandle]; unzFile f = m_fileHandles[fileHandle];
if (f) if (f)
{ {
printf("zipFile::fileClose slot %d\n", fileHandle);
unzClose(f); unzClose(f);
m_fileHandles[fileHandle]=0; m_fileHandles[fileHandle]=0;
} }

View File

@@ -149,7 +149,14 @@ struct b3BulletDefaultFileIO : public CommonFileIOInterface
if (f) if (f)
{ {
char* txt = ::fgets(destBuffer, numBytes, m_fileHandles[fileHandle]); char* txt = ::fgets(destBuffer, numBytes, m_fileHandles[fileHandle]);
destBuffer[strcspn(destBuffer, "\r\n")] = 0; for (int i=0;i<numBytes;i++)
{
if (destBuffer[i]=='\r'||destBuffer[i]=='\n' || destBuffer[i]==0)
{
destBuffer[i] = 0;
break;
}
}
return txt; return txt;
} }
} }

View File

@@ -9850,7 +9850,9 @@ initpybullet(void)
PyModule_AddIntConstant(m, "URDF_ENABLE_CACHED_GRAPHICS_SHAPES", URDF_ENABLE_CACHED_GRAPHICS_SHAPES); PyModule_AddIntConstant(m, "URDF_ENABLE_CACHED_GRAPHICS_SHAPES", URDF_ENABLE_CACHED_GRAPHICS_SHAPES);
PyModule_AddIntConstant(m, "URDF_ENABLE_SLEEPING", URDF_ENABLE_SLEEPING); PyModule_AddIntConstant(m, "URDF_ENABLE_SLEEPING", URDF_ENABLE_SLEEPING);
PyModule_AddIntConstant(m, "URDF_INITIALIZE_SAT_FEATURES", URDF_INITIALIZE_SAT_FEATURES); PyModule_AddIntConstant(m, "URDF_INITIALIZE_SAT_FEATURES", URDF_INITIALIZE_SAT_FEATURES);
PyModule_AddIntConstant(m, "URDF_USE_MATERIAL_COLORS_FROM_MTL", URDF_USE_MATERIAL_COLORS_FROM_MTL);
PyModule_AddIntConstant(m, "URDF_USE_MATERIAL_TRANSPARANCY_FROM_MTL", URDF_USE_MATERIAL_TRANSPARANCY_FROM_MTL);
PyModule_AddIntConstant(m, "ACTIVATION_STATE_ENABLE_SLEEPING", eActivationStateEnableSleeping); PyModule_AddIntConstant(m, "ACTIVATION_STATE_ENABLE_SLEEPING", eActivationStateEnableSleeping);
PyModule_AddIntConstant(m, "ACTIVATION_STATE_DISABLE_SLEEPING", eActivationStateDisableSleeping); PyModule_AddIntConstant(m, "ACTIVATION_STATE_DISABLE_SLEEPING", eActivationStateDisableSleeping);
PyModule_AddIntConstant(m, "ACTIVATION_STATE_WAKE_UP", eActivationStateWakeUp); PyModule_AddIntConstant(m, "ACTIVATION_STATE_WAKE_UP", eActivationStateWakeUp);