These files implement a LDraw™ (.ldr/.mpd) file loader in C/C++ and provide some functionality to enhance the 3D mesh for rendering.
You need to have a LDraw™ Parts Library installed and pass the path at creation time of the loader.
Note: API and featureset are still work in progress in this personal project.
stud.dat
)// The C api is used here, however there is also ldr::Loader which pretty much
// works the same.
// initialize library
LdrLoaderCreateInfo createInfo = {};
// while parts are not directly fixed, we will implicitly create a fixed version
// for renderparts
createInfo.partFixMode = LDR_PART_FIX_NONE;
createInfo.renderpartBuildMode = LDR_RENDERPART_BUILD_ONLOAD;
// required for chamfering
createInfo.partFixTjunctions = LDR_TRUE;
// optionally look for higher subdivided ldraw primitives
createInfo.partHiResPrimitives = LDR_FALSE;
// leave 0 to disable
createInfo.renderpartChamfer = 0.35f;
// installation path of the LDraw Part Library
createInfo.basePath = m_ldrawPath.c_str();
LdrResult result = ldrCreateLoader(&createInfo, &m_loader);
assert(result == LDR_SUCCESS);
if (singleThreaded) {
// load a model, either in the simple (typical singleThreaded) "autoResolve" mode
result = ldrCreateModel(m_loader, m_modelFilename.c_str(), LDR_TRUE, &m_scene.model);
assert(result == LDR_SUCCESS || result == LDR_WARNING_PART_NOT_FOUND);
} else {
// or by passing FALSE to autoResolve allow multi-threaded loading
result = ldrCreateModel(m_loader, m_modelFilename.c_str(), LDR_FALSE, &m_scene.model);
assert(result == LDR_SUCCESS || result == LDR_WARNING_PART_NOT_FOUND);
uint32_t numParts = ldrGetNumRegisteredParts(m_loader);
uint32_t numThreads = std::thread::hardware_concurrency();
uint32_t perThread = (numParts + numThreads - 1) / numThreads;
std::vector<LdrPartID> partIds(numParts);
std::vector<LdrResult> partResults(numParts);
std::vector<std::thread> threads(numThreads);
for (uint32_t i = 0; i < numThreads; i++)
{
threads[i] = std::thread( [&](uint32_t idx){
uint32_t offset = idx * perThread;
uint32_t numLocal = offset > numParts ? 0 : std::min(perThread, numParts - idx * perThread);
if (numLocal){
for (uint32_t p = 0; p < numLocal; p++){
partIds[offset + p] = (LdrPartID)(offset + p);
}
ldrLoadDeferredParts(m_loader, numLocal, &partIds[offset], sizeof(LdrPartID), &partResults[offset]);
}
}, i);
}
for (uint32_t i = 0; i < numThreads; i++){
threads[i].join();
}
// must do manual resolve after parts are loaded
ldrResolveModel(m_loader, m_scene.model);
}
// access the model and part details directly
for (uint32_t i = 0; i < model->num_instances; i++){
const LdrInstance& instance = model->instances[i];
const LdrPart* part = ldrGetPart(m_loader, instance.part);
const LdrRenderPart* rpart = ldrGetRenderPart(m_loader, instance.part);
...
}
// the rendermodel is self-contained
result = ldrCreateRenderModel(m_loader, m_scene.model, LDR_TRUE, &m_scene.renderModel);
// so you can delete the regular model afterwards
ldrDestroyModel(m_loader, m_scene.model);
ldrawloader_viewer is a supplementary project that is used to debug this library.
LDraw™ has many features and enhancements of various complexity (animation, grouping, deformable parts etc.). Some of those features may be added over time, however the goal of the project is mostly to provide easy-to-embed loader for basic use-cases.
Furthermore, the ldraw parts are modelled with varying complexity, and are typically not watertight, contain self-intersections and often have "floating" edges not matching the triangle or quad topology. Therefore the chamfering or per-vertex normal computations may not always yield desired results. Hence there are some "hacks" with magic values in place to workaround some pathologies found in parts so far. A "proper" solution would be deriving the solids through remeshing the parts completely.
The easiest is to embed the files directly, but you could also configure it as library if needed. Furthermore a C interface exists to aid binding to other languages. C++ 11 is required.
In case this is not what you were looking for, here are some other related projects to working with ldr files.
LDraw™ is a trademark owned and licensed by the Estate of James Jessiman, which does not sponsor, endorse, or authorize this project.
LEGO® and the LEGO logo are registered trademarks of The Lego Group, which does not sponsor, endorse, or authorize this site. You can find the official LEGO website at http://www.lego.com.