Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call generateDecorations twice for fixed and non-fixed geometry #93

Merged
merged 7 commits into from
Sep 20, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ class DecorativeGeometryImplementationGltf(osim.simbody.DecorativeGeometryImplem
groundNode = None # Node corresponding to Model::Ground
modelState = None # reference to state object obtained by initSystem
mapTypesToMaterialIndex = {}

MaterialGrouping = {}
model = None

accessors = None # references to arrays within the gltf structure for convenience
buffers = None
bufferViews = None
Expand Down Expand Up @@ -86,14 +87,30 @@ def implementCircleGeometry(self, arg0):
def implementSphereGeometry(self, arg0):
sphereSource = vtk.vtkSphereSource()
sphereSource.SetRadius(arg0.getRadius()*self.unitConversion)
sphereSource.SetPhiResolution(16)
sphereSource.SetThetaResolution(16)
sphereSource.Update()
polyDataOutput = sphereSource.GetOutput()
self.createGLTFMeshFromPolyData(arg0, "Sphere:", polyDataOutput, self.getMaterialIndexByType())
# print("produce sphere", arg0.getRadius())
return

def implementEllipsoidGeometry(self, arg0):
return _simbody.DecorativeGeometryImplementation_implementEllipsoidGeometry(self, arg0)
sphereSource = vtk.vtkSphereSource()
sphereSource.SetRadius(1.0*self.unitConversion)
sphereSource.SetPhiResolution(16)
sphereSource.SetThetaResolution(16)
# Make a stretching transform to take the sphere into an ellipsoid
stretch = vtk.vtkTransformPolyDataFilter();
stretchSphereToEllipsoid = vtk.vtkTransform();
radiiVec3 = arg0.getRadii()
stretchSphereToEllipsoid.Scale(radiiVec3[0], radiiVec3[1], radiiVec3[2]);
stretch.SetTransform(stretchSphereToEllipsoid);
stretch.SetInputConnection(sphereSource.GetOutputPort());
stretch.Update()
polyDataOutput = stretch.GetOutput()
self.createGLTFMeshFromPolyData(arg0, "Ellipsoid:", polyDataOutput, self.getMaterialIndexByType())
return

def implementFrameGeometry(self, arg0):
# print("produce frame", arg0.getAxisLength())
Expand Down Expand Up @@ -150,8 +167,17 @@ def createGLTFMeshFromPolyData(self, arg0, gltfName, polyDataOutput, materialInd
self.mapMobilizedBodyIndexToNodes[arg0.getBodyId()].children.append(nodeIndex)

def implementTorusGeometry(self, arg0):
return _simbody.DecorativeGeometryImplementation_implementTorusGeometry(self, arg0)

torus=vtk.vtkParametricTorus();
torusSource = vtk.vtkParametricFunctionSource();
torusSource.SetParametricFunction(torus);
torusMapper=vtk.vtkPolyDataMapper();
torusMapper.SetInputConnection(torusSource.GetOutputPort());
torus.SetRingRadius(arg0.getTorusRadius()+arg0.getTubeRadius());
torus.SetCrossSectionRadius(arg0.getTubeRadius());
polyDataOutput = torusSource.GetOutput();
self.createGLTFMeshFromPolyData(arg0, "Torus:", polyDataOutput, self.getMaterialIndexByType())
return

def implementArrowGeometry(self, arg0):
return _simbody.DecorativeGeometryImplementation_implementArrowGeometry(self, arg0)

Expand Down Expand Up @@ -196,6 +222,13 @@ def addDefaultMaterials(self):
# 3 shiny green material for forces
# 4 shiny blue material for experimental markers
# 5 shiny orange material for IMUs
self.MaterialGrouping["ContactHalfSpace"] = "Wrapping"
self.MaterialGrouping["ContactSphere"] = "Wrapping"
self.MaterialGrouping["ContactMesh"] = "Wrapping"
self.MaterialGrouping["WrapSphere"] = "Wrapping"
self.MaterialGrouping["WrapCylinder"] = "Wrapping"
self.MaterialGrouping["WrapEllipsoid"] = "Wrapping"
self.MaterialGrouping["WrapTorus"] = "Wrapping"
self.mapTypesToMaterialIndex["Mesh"] = self.addMaterialToGltf("default", [.87, .78, .6, 1.0])
self.mapTypesToMaterialIndex["Wrapping"] = self.addMaterialToGltf("obstacle", [0, .9, .9, 0.7])
self.mapTypesToMaterialIndex["Marker"] = self.addMaterialToGltf("markerMat", [1.0, .6, .8, 1.0])
Expand All @@ -216,7 +249,11 @@ def addMaterialToGltf(self, matName, color4):

def getMaterialIndexByType(self):
componentType = self.currentComponent.getConcreteClassName()
mat = self.mapTypesToMaterialIndex.get(componentType)
materialGrouping = self.MaterialGrouping.get(componentType)
if (materialGrouping is not None):
mat = self.mapTypesToMaterialIndex.get(materialGrouping)
else:
mat = self.mapTypesToMaterialIndex.get(componentType)
if (mat is not None):
return mat
else:
Expand All @@ -226,7 +263,6 @@ def setNodeTransformFromDecoration(self, node: Node, mesh: Mesh, decorativeGeome
bd = decorativeGeometry.getBodyId()
bdNode = self.mapMobilizedBodyIndexToNodes[bd]
nodeIndex = len(self.nodes)
meshIndex = len(self.meshes)
self.meshes.append(mesh)
bdNode.children.append(nodeIndex)
nodeForDecoration = Node(name=""+bd.getName()+decorativeGeometry.getIndexOnBody())
Expand Down Expand Up @@ -259,17 +295,21 @@ def addMeshForPolyData(self, polyData: vtk.vtkPolyData, mat: int):
tris.Update()
triPolys = tris.GetOutput()

meshBufferIndex = len(self.buffers)
# This follows vtkGLTFExporter flow
pointData = triPolys.GetPoints().GetData();
self.writeBufferAndView(pointData, ARRAY_BUFFER)
bounds = triPolys.GetPoints().GetBounds()
# create accessor
pointAccessor = Accessor()
pointAccessor.bufferView= len(self.bufferViews)-1
pointAccessor.byteOffset = 0
pointAccessor.type = VEC3
pointAccessor.componentType = FLOAT
pointAccessor.count = pointData.GetNumberOfTuples()
maxValue = [bounds[1], bounds[3], bounds[5]]
minValue = [bounds[0], bounds[2], bounds[4]]
pointAccessor.min = minValue
pointAccessor.max = maxValue
self.accessors.append(pointAccessor)
pointAccessorIndex = len(self.accessors)-1

Expand All @@ -295,7 +335,6 @@ def addMeshForPolyData(self, polyData: vtk.vtkPolyData, mat: int):
primitive.material = mat
meshPolys = triPolys.GetPolys()
ia = vtk.vtkUnsignedIntArray()
cellData = meshPolys.GetData()
idList = vtk.vtkIdList()
while meshPolys.GetNextCell(idList):
# do something with the cell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ def convertOsim2Gltf(osimModelFilePath, geometrySearchPath) :
sizeBefore = adg.size()
# print(comp.getAbsolutePathString())
comp.generateDecorations(True, mdh, state, adg);
# we don't know how to handle muscles for now so will leave off, verify everything else displays ok
if (comp.getConcreteClassName()!= "GeometryPath"):
comp.generateDecorations(False, mdh, state, adg);
sizeAfter = adg.size()
if (sizeAfter > sizeBefore):
decorativeGeometryImp.setCurrentComponent(comp)
Expand Down
4 changes: 4 additions & 0 deletions src/components/Components/VisualizationControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ const VisualizationControl : React.FC<VisualizationControlProps> = (props:Visual
<FormControlLabel control={<Checkbox />} label={t('visualizationControl.joints')} />
<FormControlLabel control={<Checkbox checked={curState.getLayerVisibility(1)}/>} label={t('visualizationControl.bodies')}
onChange={()=>{curState.toggleLayerVisibility(1); setCameraLayerMask(curState.cameraLayersMask)}} />
<FormControlLabel control={<Checkbox checked={curState.getLayerVisibility(7)}/>} label={t('visualizationControl.wrapObjects')}
onChange={()=>{curState.toggleLayerVisibility(7); setCameraLayerMask(curState.cameraLayersMask)}} />
<FormControlLabel control={<Checkbox checked={curState.getLayerVisibility(8)}/>} label={t('visualizationControl.contactObjects')}
onChange={()=>{curState.toggleLayerVisibility(8); setCameraLayerMask(curState.cameraLayersMask)}} />
<FormControlLabel control={<Checkbox checked={curState.getLayerVisibility(4)}/>} label={t('visualizationControl.markers')}
onChange={()=>{curState.toggleLayerVisibility(4); setCameraLayerMask(curState.cameraLayersMask)}}/>
</FormGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/OpenSimControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const OpenSimControl = () => {
curState.takeSnapshot = false;
}
else if (curState.cameraLayersMask !== camera.layers.mask) {
for (let layernumber =0; layernumber < 6; layernumber++){
for (let layernumber =0; layernumber < 31; layernumber++){
let newState = curState.getLayerVisibility(layernumber)
if (newState)
camera.layers.enable(layernumber)
Expand Down
10 changes: 9 additions & 1 deletion src/components/pages/OpenSimScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ const OpenSimScene: React.FC<OpenSimSceneProps> = ({ currentModelPath, supportCo
["World", 3],
["Marker", 4],
["ExpMarker", 5],
["expForce", 6]
["expForce", 6],
["WrapSphere", 7],
["WrapCylinder", 7],
["WrapEllipsoid", 7],
["WrapTorus", 7],
["wrapObject", 7],
["ContactSphere", 8],
["ContactMesh", 8],
["ContactHalfSpace", 8]
]);

const mapObjectToLayer = (obj3d: Object3D)=>{
Expand Down
2 changes: 2 additions & 0 deletions src/internationalization/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ i18next
wcs: "WCS",
joints: "Joints",
bodies: "Bodies",
wrapObjects: "WrapObjects",
contactObjects: "Contacts",
markers: "Markers",
speed: "Speed"
},
Expand Down
Loading