Skip to content

Commit a30a3d9

Browse files
author
Cyrille Favreau
authored
Merge pull request #390 from favreau/master
Created USD (Universal Scene Description) file exporter (Work in progress)
2 parents 1389151 + 26d503f commit a30a3d9

File tree

20 files changed

+381
-50
lines changed

20 files changed

+381
-50
lines changed

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@
1313
[submodule "platform/deps/MorphIO"]
1414
path = platform/deps/MorphIO
1515
url = https://github.com/BlueBrain/MorphIO.git
16+
[submodule "platform/deps/USD"]
17+
path = platform/deps/USD
18+
url = https://github.com/PixarAnimationStudios/USD.git
19+
[submodule "platform/deps/OpenSubdiv"]
20+
path = platform/deps/OpenSubdiv
21+
url = https://github.com/PixarAnimationStudios/OpenSubdiv.git

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ find_package(CGAL)
4646
find_package(LASlib OPTIONAL_COMPONENTS)
4747
find_package(MorphIO OPTIONAL_COMPONENTS)
4848
find_package(HighFive OPTIONAL_COMPONENTS)
49+
find_package(pxr)
50+
4951

5052
set(BIOEXPLORER_SOURCE_DIRS ${PROJECT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/generated)
5153

@@ -57,6 +59,10 @@ if(MorphIO_FOUND)
5759
message(STATUS "[Core] MorphIO module enabled")
5860
endif()
5961

62+
if(pxr_FOUND)
63+
message(STATUS "[Core] Pixar Universal Scene Description module enabled")
64+
endif()
65+
6066
# Find the Intel C++ compiler
6167
find_program(CMAKE_CXX_COMPILER NAMES icpc)
6268
if(CMAKE_CXX_COMPILER)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ References:
197197
* [Age and sex do not affect the volume, cell numbers, or cell size of the suprachiasmatic nucleus of the rat: An unbiased stereological](https://doi.org/10.1002/cne.903610404)
198198
* [Community-based Reconstruction and Simulation of a Full-scale Model of Region CA1 of Rat Hippocampus](https://www.biorxiv.org/content/10.1101/2023.05.17.541167v1)
199199
* [Modeling and Simulation of Neocortical Micro- and Mesocircuitry. Part II: Physiology and Experimentation](https://www.biorxiv.org/content/10.1101/2023.05.17.541168v2)
200+
* [Community-based reconstruction and simulation of a full-scale model of the rat hippocampus CA1 region](https://journals.plos.org/plosbiology/article?id=10.1371/journal.pbio.3002861)
200201

201202
### Astrocytes
202203

bioexplorer/backend/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ set(${NAME}_SOURCES
6262
science/io/db/DBConnector.cpp
6363
science/io/cache/MemoryCache.cpp
6464
science/io/filesystem/MorphologyLoader.cpp
65+
science/io/filesystem/USDExporter.cpp
6566
science/molecularsystems/EnzymeReaction.cpp
6667
science/molecularsystems/Molecule.cpp
6768
science/molecularsystems/Membrane.cpp
@@ -98,6 +99,7 @@ set(${NAME}_PUBLIC_HEADERS
9899
science/io/CacheLoader.h
99100
science/io/cache/MemoryCache.h
100101
science/io/filesystem/MorphologyLoader.h
102+
science/io/filesystem/USDExporter.h
101103
science/io/db/DBConnector.h
102104
science/common/Assembly.h
103105
science/common/Node.h
@@ -169,6 +171,10 @@ if(MorphIO_FOUND)
169171
include_directories(${HDF5_INCLUDE_DIRS})
170172
endif()
171173

174+
if(pxr_FOUND)
175+
list(APPEND ${NAME}_PRIVATE_MODULE_LIBRARIES ${PXR_LIBRARIES})
176+
endif()
177+
172178
# ==============================================================================
173179
# OSPRay module
174180
# ==============================================================================

bioexplorer/backend/plugins/Sonata/plugin/neuroscience/common/MorphologyLoader.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -750,21 +750,6 @@ void MorphologyLoader::_importMorphologyFromURI(const Gid& gid, const PropertyMa
750750
float srcRadius = _getCorrectedRadius(properties, srcDiameter);
751751
float dstRadius = _getCorrectedRadius(properties, dstDiameter);
752752

753-
#if 0
754-
const float maxRadiusChange = 0.1f;
755-
if (sampleLength > 0.0001f && s != nbSamples - 1 &&
756-
dampenBranchThicknessChangerate)
757-
{
758-
const float radiusChange =
759-
std::min(std::abs(dstRadius - srcRadius),
760-
sampleLength * maxRadiusChange);
761-
if (srcRadius < dstRadius)
762-
srcRadius = dstRadius - radiusChange;
763-
else
764-
srcRadius = dstRadius + radiusChange;
765-
}
766-
#endif
767-
768753
// Add Geometry
769754
if (s > 0)
770755
{
@@ -1161,8 +1146,7 @@ ModelDescriptorPtr MorphologyLoader::importFromStorage(const std::string& path,
11611146
// the UI
11621147
PropertyMap props = _defaults;
11631148
props.merge(properties);
1164-
// TODO: This needs to be done to work around wrong types coming from
1165-
// the UI
1149+
// TODO: This needs to be done to work around wrong types coming from the UI
11661150

11671151
auto model = _scene.createModel();
11681152
auto modelContainer = importMorphology(0, props, path, 0, SynapsesInfo());

bioexplorer/backend/science/BioExplorerPlugin.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
#include <science/morphologies/SpikeSimulationHandler.h>
3636
#include <science/vasculature/VasculatureLoader.h>
3737

38+
#ifdef USE_PIXAR
39+
#include <science/io/filesystem/USDExporter.h>
40+
#endif // USE_PIXAR
41+
3842
#include <platform/core/common/ActionInterface.h>
3943
#include <platform/core/common/Properties.h>
4044
#include <platform/core/common/scene/ClipPlane.h>
@@ -348,6 +352,13 @@ void BioExplorerPlugin::init()
348352
actionInterface->registerRequest<FileAccessDetails, Response>(endPoint, [&](const FileAccessDetails &payload)
349353
{ return _exportToXYZ(payload); });
350354

355+
#ifdef USE_PIXAR
356+
endPoint = PLUGIN_API_PREFIX + "export-to-universal-scene-description-file";
357+
PLUGIN_REGISTER_ENDPOINT(endPoint);
358+
actionInterface->registerRequest<FileAccessDetails, Response>(endPoint, [&](const FileAccessDetails &payload)
359+
{ return _exportToUSDFile(payload); });
360+
#endif // USE_PIXAR
361+
351362
#ifdef USE_LASLIB
352363
endPoint = PLUGIN_API_PREFIX + "export-to-las";
353364
PLUGIN_REGISTER_ENDPOINT(endPoint);
@@ -418,8 +429,7 @@ void BioExplorerPlugin::init()
418429
endPoint = PLUGIN_API_PREFIX + "get-model-transformation";
419430
PLUGIN_REGISTER_ENDPOINT(endPoint);
420431
actionInterface->registerRequest<ModelIdDetails, ModelTransformationDetails>(
421-
endPoint,
422-
[&](const ModelIdDetails &payload) -> ModelTransformationDetails
432+
endPoint, [&](const ModelIdDetails &payload) -> ModelTransformationDetails
423433
{ return _getModelTransformation(payload); });
424434

425435
endPoint = PLUGIN_API_PREFIX + "get-model-bounds";
@@ -491,8 +501,7 @@ void BioExplorerPlugin::init()
491501

492502
endPoint = PLUGIN_API_PREFIX + "get-vasculature-info";
493503
PLUGIN_REGISTER_ENDPOINT(endPoint);
494-
actionInterface->registerRequest<NameDetails, Response>(endPoint,
495-
[&](const NameDetails &payload) -> Response
504+
actionInterface->registerRequest<NameDetails, Response>(endPoint, [&](const NameDetails &payload) -> Response
496505
{ return _getVasculatureInfo(payload); });
497506

498507
endPoint = PLUGIN_API_PREFIX + "set-vasculature-report";
@@ -1133,6 +1142,21 @@ Response BioExplorerPlugin::_exportToLas(const LASFileAccessDetails &payload)
11331142
}
11341143
#endif
11351144

1145+
#ifdef USE_PIXAR
1146+
Response BioExplorerPlugin::_exportToUSDFile(const FileAccessDetails &payload)
1147+
{
1148+
Response response;
1149+
try
1150+
{
1151+
auto &scene = _api->getScene();
1152+
filesystem::USDExporter exporter(scene);
1153+
exporter.exportToFile(payload.filename);
1154+
}
1155+
CATCH_STD_EXCEPTION()
1156+
return response;
1157+
}
1158+
#endif // USE_PIXAR
1159+
11361160
Response BioExplorerPlugin::_addGrid(const AddGridDetails &payload)
11371161
{
11381162
Response response;

bioexplorer/backend/science/BioExplorerPlugin.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,12 @@ class BioExplorerPlugin : public core::ExtensionPlugin
6464
details::Response _exportToFile(const details::FileAccessDetails &payload);
6565
details::Response _importFromFile(const details::FileAccessDetails &payload);
6666
details::Response _exportToXYZ(const details::FileAccessDetails &payload);
67+
#ifdef USE_LASLIB
6768
details::Response _exportToLas(const details::LASFileAccessDetails &payload);
69+
#endif // USE_LASLIB
70+
#ifdef USE_PIXAR
71+
details::Response _exportToUSDFile(const details::FileAccessDetails &payload);
72+
#endif // USE_PIXAR
6873

6974
// DB
7075
details::Response _exportBrickToDatabase(const details::DatabaseAccessDetails &payload);

bioexplorer/backend/science/common/SDFGeometries.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ Vector4fs SDFGeometries::_getProcessedSectionPoints(const MorphologyRepresentati
6060
{
6161
case MorphologyRepresentation::bezier:
6262
{
63-
const uint64_t nbBezierPoints = std::max(static_cast<size_t>(3), points.size() / 10);
64-
const float step = 1.f / static_cast<float>(nbBezierPoints);
65-
for (float i = 0; i <= 1.f; i += step)
63+
const float step = 1.f / (static_cast<float>(points.size()) / 2.0);
64+
for (float i = 0; i < 1.f + step; i += step)
6665
localPoints.push_back(getBezierPoint(points, i));
6766
break;
6867
}
@@ -80,6 +79,7 @@ Vector4fs SDFGeometries::_getProcessedSectionPoints(const MorphologyRepresentati
8079
default:
8180
{
8281
localPoints = points;
82+
break;
8383
}
8484
}
8585
return localPoints;

bioexplorer/backend/science/common/ThreadSafeContainer.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace common
3131
{
3232
using namespace core;
3333

34-
const float equalityEpsilon = 1e-6f;
34+
const float equalityEpsilon = 1e-3f;
3535

3636
ThreadSafeContainer::ThreadSafeContainer(Model& model, const double alignToGrid, const Vector3d& position,
3737
const Quaterniond& rotation, const Vector3d& scale)
@@ -94,6 +94,7 @@ uint64_t ThreadSafeContainer::addCone(const Vector3f& sourcePosition, const floa
9494
getAlignmentToGrid(_alignToGrid, Vector3f(_position + _rotation * Vector3d(sourcePosition)) * scale);
9595
const Vector3f scaledDstPosition =
9696
getAlignmentToGrid(_alignToGrid, Vector3f(_position + _rotation * Vector3d(targetPosition)) * scale);
97+
9798
if (useSdf)
9899
{
99100
const Vector3f scaledDisplacement{displacement.x * scale.x, displacement.y / scale.x, displacement.z};
@@ -109,13 +110,12 @@ uint64_t ThreadSafeContainer::addCone(const Vector3f& sourcePosition, const floa
109110
}
110111
if (fabs(sourceRadius - targetRadius) < equalityEpsilon)
111112
{
112-
const auto scaledSrcRadius = sourceRadius * scale.x;
113-
const auto scaledDstRadius = targetRadius * scale.x;
114-
_bounds.merge(scaledSrcPosition + scaledSrcRadius);
115-
_bounds.merge(scaledSrcPosition - scaledSrcRadius);
116-
_bounds.merge(scaledDstPosition + scaledDstRadius);
117-
_bounds.merge(scaledDstPosition - scaledDstRadius);
118-
return _addCylinder(materialId, {scaledSrcPosition, scaledDstPosition, sourceRadius * scale.x, userDataOffset});
113+
const auto scaledRadius = sourceRadius * scale.x;
114+
_bounds.merge(scaledSrcPosition + scaledRadius);
115+
_bounds.merge(scaledSrcPosition - scaledRadius);
116+
_bounds.merge(scaledDstPosition + scaledRadius);
117+
_bounds.merge(scaledDstPosition - scaledRadius);
118+
return _addCylinder(materialId, {scaledSrcPosition, scaledDstPosition, scaledRadius, userDataOffset});
119119
}
120120

121121
const auto scaledSrcRadius = sourceRadius * scale.x;
@@ -124,8 +124,8 @@ uint64_t ThreadSafeContainer::addCone(const Vector3f& sourcePosition, const floa
124124
_bounds.merge(scaledSrcPosition - scaledSrcRadius);
125125
_bounds.merge(scaledDstPosition + scaledDstRadius);
126126
_bounds.merge(scaledDstPosition - scaledDstRadius);
127-
return _addCone(materialId, {scaledSrcPosition, scaledDstPosition, sourceRadius * scale.x, targetRadius * scale.x,
128-
userDataOffset});
127+
return _addCone(materialId,
128+
{scaledSrcPosition, scaledDstPosition, scaledSrcRadius, scaledDstRadius, userDataOffset});
129129
}
130130

131131
void ThreadSafeContainer::addConeOfSpheres(const Vector3f& sourcePosition, const float sourceRadius,

bioexplorer/backend/science/io/filesystem/MorphologyLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ SectionMap MorphologyLoader::getNeuronSections(const std::string& filename,
8383
loadSection(section, sections, sectionTypes);
8484
return sections;
8585
#else
86-
PLUGIN_THROW("BioExplorer was not compiler with MorphIO");
86+
PLUGIN_THROW("BioExplorer was not compiled with MorphIO");
8787
#endif
8888
}
8989
} // namespace filesystem

0 commit comments

Comments
 (0)