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

Introduce a set of Cpp examples for the new volumetric extension #400

Merged
merged 13 commits into from
Dec 16, 2024
Merged
22 changes: 21 additions & 1 deletion SDK/Examples/Cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required (VERSION 2.6)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

if (WIN32)
set(LSUFFIX "dll")
Expand All @@ -16,6 +16,7 @@ else()
endif()

add_definitions( -DTEXTURESPATH="${CMAKE_CURRENT_SOURCE_DIR}/../Files/Textures/" )
add_definitions( -DVOLUME_IMAGES_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../Files/volumetricImages/" )

project(Examples)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../Bindings/Cpp)
Expand Down Expand Up @@ -61,6 +62,25 @@ CopySharedLibrary(Example_Slice)
add_executable(Example_BeamLattice Source/BeamLattice.cpp)
CopySharedLibrary(Example_BeamLattice)

add_executable(Example_VolumeSphere Source/VolumeCreateSphere.cpp)
CopySharedLibrary(Example_VolumeSphere)

add_executable(Example_VolumeGyroid Source/VolumeGyroid.cpp)
CopySharedLibrary(Example_VolumeGyroid)

add_executable(Example_VolumeCylinder Source/VolumeCreateCylinder.cpp)
CopySharedLibrary(Example_VolumeCylinder)

add_executable(Example_VolumeTorus Source/VolumeCreateTorus.cpp)
CopySharedLibrary(Example_VolumeTorus)

add_executable(Example_VolumeCombineFunctions Source/VolumeCombineFunctions.cpp)
CopySharedLibrary(Example_VolumeCombineFunctions)

add_executable(Example_VolumeImageStack Source/VolumeImageStack.cpp)
CopySharedLibrary(Example_VolumeImageStack)


if (${MSVC})
IF(${CMAKE_VERSION} VERSION_LESS 3.6.3)
MESSAGE ("Note: You need to manually select a StartUp-project in Visual Studio.")
Expand Down
28 changes: 28 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeCombineFunctions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "lib3mf_implicit.hpp"
#include <iostream>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

auto funcA = model->AddImplicitFunction();
auto funcB = model->AddImplicitFunction();
funcA->SetDisplayName("FunctionA");
funcB->SetDisplayName("FunctionB");

auto inputA = funcA->AddInput("x", "Position X", Lib3MF::eImplicitPortType::Scalar);
auto sinNode = funcA->AddSinNode("sinA", Lib3MF::eImplicitNodeConfiguration::ScalarToScalar, "Sine Node", "group");
funcA->AddLink(inputA, sinNode->GetInputA());
funcA->AddOutput("outputA", "Output A", Lib3MF::eImplicitPortType::Scalar);

auto inputB = funcB->AddInput("y", "Position Y", Lib3MF::eImplicitPortType::Scalar);
auto cosNode = funcB->AddCosNode("cosB", Lib3MF::eImplicitNodeConfiguration::ScalarToScalar, "Cosine Node", "group");
funcB->AddLink(inputB, cosNode->GetInputA());
funcB->AddOutput("outputB", "Output B", Lib3MF::eImplicitPortType::Scalar);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("CombinedFunctions.3mf");

std::cout << "Saved CombinedFunctions.3mf" << std::endl;
return 0;
}
23 changes: 23 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeCreateCylinder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "lib3mf_implicit.hpp"
#include <iostream>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

auto newFunction = model->AddImplicitFunction();
newFunction->SetDisplayName("Cylinder");

auto input = newFunction->AddInput("pos", "Position", Lib3MF::eImplicitPortType::Vector);
auto cylinderNode = newFunction->AddLengthNode("cylinderNode", "Length", "group");
newFunction->AddLink(input, cylinderNode->GetInputA());

auto output = newFunction->AddOutput("shape", "Cylinder Shape", Lib3MF::eImplicitPortType::Scalar);
newFunction->AddLink(cylinderNode->GetOutputResult(), output);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("Cylinder.3mf");

std::cout << "Saved Cylinder.3mf" << std::endl;
return 0;
}
30 changes: 30 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeCreateSphere.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "lib3mf_implicit.hpp"
#include <iostream>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

auto newFunction = model->AddImplicitFunction();
newFunction->SetDisplayName("Sphere");

auto input = newFunction->AddInput("pos", "position", Lib3MF::eImplicitPortType::Vector);
auto constantNode = newFunction->AddConstantNode("radius", "Sphere Radius", "group");
constantNode->SetConstant(15.0);

auto lengthNode = newFunction->AddLengthNode("distance", "Distance to sphere", "group");
newFunction->AddLink(input, lengthNode->GetInputA());

auto subtractNode = newFunction->AddSubtractionNode("offset", Lib3MF::eImplicitNodeConfiguration::ScalarToScalar, "Offset Radius", "group");
newFunction->AddLink(lengthNode->GetOutputResult(), subtractNode->GetInputA());
newFunction->AddLink(constantNode->GetOutputValue(), subtractNode->GetInputB());

auto output = newFunction->AddOutput("shape", "Signed Distance Field", Lib3MF::eImplicitPortType::Scalar);
newFunction->AddLink(subtractNode->GetOutputResult(), output);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("ImplicitSphere.3mf");

std::cout << "Saved ImplicitSphere.3mf" << std::endl;
return 0;
}
30 changes: 30 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeCreateTorus.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "lib3mf_implicit.hpp"
#include <iostream>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

auto torusFunction = model->AddImplicitFunction();
torusFunction->SetDisplayName("Torus");

auto input = torusFunction->AddInput("pos", "Position", Lib3MF::eImplicitPortType::Vector);
auto lengthNode = torusFunction->AddLengthNode("length", "Length", "group");
torusFunction->AddLink(input, lengthNode->GetInputA());

auto radiusNode = torusFunction->AddConstantNode("radius", "Radius", "group");
radiusNode->SetConstant(10.0);

auto subtractNode = torusFunction->AddSubtractionNode("subtract", Lib3MF::eImplicitNodeConfiguration::ScalarToScalar, "Subtract Radius", "group");
torusFunction->AddLink(lengthNode->GetOutputResult(), subtractNode->GetInputA());
torusFunction->AddLink(radiusNode->GetOutputValue(), subtractNode->GetInputB());

auto output = torusFunction->AddOutput("shape", "Torus Shape", Lib3MF::eImplicitPortType::Scalar);
torusFunction->AddLink(subtractNode->GetOutputResult(), output);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("Torus.3mf");

std::cout << "Saved Torus.3mf" << std::endl;
return 0;
}
28 changes: 28 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeGyroid.cpp
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version crashes at least on windows with msvc. AddLink(...) only works with l-values, an act issue I could not resolve.

cosNode is missing an input.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might work:

int main() {
    Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
    auto model = wrapper->CreateModel();

    auto gyroidFunction = model->AddImplicitFunction();
    gyroidFunction->SetDisplayName("Gyroid");

    auto input = gyroidFunction->AddInput("pos", "position", Lib3MF::eImplicitPortType::Vector);
    auto sinNode = gyroidFunction->AddSinNode("sin", Lib3MF::eImplicitNodeConfiguration::VectorToVector, "Sine of Position", "group");
    auto cosNode = gyroidFunction->AddCosNode("cos", Lib3MF::eImplicitNodeConfiguration::VectorToVector, "Cosine of Transformed Position", "group");

    auto dotNode = gyroidFunction->AddDotNode("dot", "Dot Product", "group");
    auto sinInputA = sinNode->GetInputA();
    gyroidFunction->AddLink(input, sinInputA);

    auto cosInputA = cosNode->GetInputA();
    gyroidFunction->AddLink(input, cosInputA);
    auto dotInputA = dotNode->GetInputA();
    auto dotInputB = dotNode->GetInputB();

    auto cosResult = cosNode->GetOutputResult();
    auto sinResult = sinNode->GetOutputResult();
    gyroidFunction->AddLink(cosResult, dotInputB);
    gyroidFunction->AddLink(sinResult, dotInputA);

    auto output = gyroidFunction->AddOutput("shape", "Signed Distance Field", Lib3MF::eImplicitPortType::Scalar);
    auto dotResult = dotNode->GetOutputResult();
    gyroidFunction->AddLink(dotResult, output);

    auto writer = model->QueryWriter("3mf");
    writer->WriteToFile("Gyroid.3mf");

    std::cout << "Saved Gyroid.3mf" << std::endl;
    return 0;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just created a PR to ACT for the fix: PR in ACT

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@3dJan How come the unit tests run then ? They also link to the same library right ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vijaiaeroastro The unit tests don't use the return value directly, but store the return value, a shared_ptr, in a variable. That keeps the shared_ptr alive, otherwise it would currently go out of scope without the suggested fix. The API tries to access the already stored raw pointer and fails. See also my comment in PR in ACT.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "lib3mf_implicit.hpp"
#include <iostream>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

auto gyroidFunction = model->AddImplicitFunction();
gyroidFunction->SetDisplayName("Gyroid");

auto input = gyroidFunction->AddInput("pos", "position", Lib3MF::eImplicitPortType::Vector);
auto sinNode = gyroidFunction->AddSinNode("sin", Lib3MF::eImplicitNodeConfiguration::VectorToVector, "Sine of Position", "group");
auto cosNode = gyroidFunction->AddCosNode("cos", Lib3MF::eImplicitNodeConfiguration::VectorToVector, "Cosine of Transformed Position", "group");

auto dotNode = gyroidFunction->AddDotNode("dot", "Dot Product", "group");
gyroidFunction->AddLink(input, sinNode->GetInputA());
gyroidFunction->AddLink(cosNode->GetOutputResult(), dotNode->GetInputB());
gyroidFunction->AddLink(sinNode->GetOutputResult(), dotNode->GetInputA());

auto output = gyroidFunction->AddOutput("shape", "Signed Distance Field", Lib3MF::eImplicitPortType::Scalar);
gyroidFunction->AddLink(dotNode->GetOutputResult(), output);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("Gyroid.3mf");

std::cout << "Saved Gyroid.3mf" << std::endl;
return 0;
}
54 changes: 54 additions & 0 deletions SDK/Examples/Cpp/Source/VolumeImageStack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "lib3mf_implicit.hpp"
#include <iostream>
#include <filesystem>

int main() {
Lib3MF::PWrapper wrapper = Lib3MF::CWrapper::loadLibrary();
auto model = wrapper->CreateModel();

constexpr int layers = 11;

auto pImageStack = model->AddImageStack(821, 819, layers);

// Resolve the path to the volumetricImages folder relative to the source file
std::string sVolumeImagesFolder = VOLUME_IMAGES_PATH;
std::filesystem::path sourceDir(sVolumeImagesFolder);
sourceDir = std::filesystem::canonical(sourceDir);

if (!std::filesystem::exists(sourceDir)) {
std::cerr << "Error: Base folder not found - " << sourceDir << "\n";
return 1;
}

for (int i = 0; i < layers; ++i) {
std::string sNumber = "_";
if (i + 1 < 10) sNumber += "0";
sNumber += std::to_string(i + 1);

std::string internalPath = "/volume/layer" + sNumber + ".png";
std::filesystem::path filePath = sourceDir / ("img" + sNumber + ".png");

if (!std::filesystem::exists(filePath)) {
std::cerr << "Error: File not found - " << filePath << "\n";
return 1;
}

pImageStack->CreateSheetFromFile(i, internalPath, filePath.string());
}

// Set up a function from the image stack
auto funcFromImageStack = model->AddFunctionFromImage3D(pImageStack.get());
funcFromImageStack->SetDisplayName("Function from Image Stack");

// Example of setting tile styles (can be customized)
funcFromImageStack->SetTileStyles(
Lib3MF::eTextureTileStyle::Wrap,
Lib3MF::eTextureTileStyle::Clamp,
Lib3MF::eTextureTileStyle::Mirror);

auto writer = model->QueryWriter("3mf");
writer->WriteToFile("ImageStack.3mf");

std::cout << "Saved ImageStack.3mf\n";
return 0;
}
2 changes: 1 addition & 1 deletion SDK/Examples/CppDynamic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Interface version: 2.2.0
cmake_minimum_required(VERSION 3.5)

project(Example_ExtractInfo)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../Bindings/CppDynamic)

if (WIN32)
Expand Down
Binary file added SDK/Examples/Files/volumetricImages/img_01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_02.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_03.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_04.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_05.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_06.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_07.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_08.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_09.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SDK/Examples/Files/volumetricImages/img_11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.