Feedback on C4D Plugin – Mapping Textures to a Pixel Grid (Cinema 4D 2024 SDK)
-
Hey everyone,
I've been working on a Cinema 4D plugin that maps and arranges textures onto a pixel grid. The goal is to make it easier to create voxel-style or Minecraft-like models by linking real-world units (e.g., centimeters) to pixels. (for example, 1 pixel = 6.25 cm)
Right now, I’ve left out most of the other planned features, since I mainly want to confirm whether I’m heading in the right direction with my current approach or if I’ve gone off track somewhere.
I’m still fairly new to the Cinema 4D SDK (using the Cinema 4D 2024 SDK and the cinema namespace), so I’d really appreciate any feedback on whether this implementation makes sense and if I’m structuring it correctly.
using namespace cinema; // Function to create the vox UV islands maxon::Result<void> VoxUvIslandCommand::CreateVoxUVIslands(Float pixelSize) { // Implement a customizable pixel grid that has the grid set to 128x128, 256X256 or 512x512 for optimal packaging // A pixel should match a set size in the 3d world like 6.25 cm // Allocate the document BaseDocument* doc = AutoAlloc(GetActiveDocument()); // Allocate the objects needed to create the UV islands AutoAlloc<BaseObject> selectedObject; AutoAlloc<BaseBitmap> bitmap; AutoAlloc<BaseTag> foundTag; AutoAlloc<UVWTag> foundUVWTag; if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::FAILED; selectedObject = AutoAlloc(doc->GetActiveObject()); if (!selectedObject) return maxon::FAILED; // Get the UV data from the selected object foundUVWTag = AutoAlloc((UVWTag*)selectedObject->GetTag(Tuvw)); // Check if the UVW tag exists, otherwise create it if (!foundUVWTag) { } // Check if the UVW tag is valid if (foundUVWTag->GetType() != Tuvw) return maxon::FAILED; Int32 dataCount = foundUVWTag->GetDataCount(); // Get the UV data from the UVW tag bitmap = AutoAlloc((BaseBitmap*)foundUVWTag->GetObject()); return maxon::OK; }
A huge thanks in advance to anyone willing to take a look. Any feedback and/or suggestions are greatly appreciated!
-
Hey @Pheolix,
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: How to Ask Questions.
About your First Question
Your code looks generally good, especially for someone who is starting out with the API you did really well. With that being said, I do not really understand what you want to do:
... plugin that maps and arranges textures onto a pixel grid. The goal is to make it easier to create voxel-style or Minecraft-like models by linking real-world units (e.g., centimeters) to pixels. (for example, 1 pixel = 6.25 cm)
A few pointers:
- A
CommandData
plugin is the perfect choice when you want to manipulate the scene without any restrictions and are fine with always having to press a button run your logic. Scene element plugins, e.g., objects, tags, etc. on the other hand will carry out their logic on their own when a scene update is invoked. But they come with the restriction that their major payload functions (ObjectData::Execucte
,ObjectData::GetVirtualObjects
,TagData::Execute
, etc.) run in their own threads (so that scene execution is parallelized) and therefore are subject to threading restrictions (I am aware that you are on C++, but the Python docs are better on this subject). So, for example, in aTagData::Execute
you would not be allowed to allocate a new UVW tag on the object that is also hosting your plugin tag. But you could implement a button in the description of the tag, which when clicked cerates your setup (becauseTagData::Message
runs on the main thread and you therefore are there allowed to add and remove scene data). WithTagData:Execute
you could then continuously update the UVW tag you are targeting on each scene update (changing parameter values of other scene elements is fine when tags are executed). This workflow is not necessarily better than a command, I am just showing you an option. Commands are also easier to implement for beginners than a scene element. - When you talk about units, you should be aware that both the object and texture coordinate system are unitless. What you see in edit fields, is just smoke and mirrors. We recently talked here about this subject.
- You did get the major gist of our error handling but what you do with
maxon::Failed
is not quite correct. It is meant to test the return value of aResult<T>
for having returned an error instance instead ofT
. When you want to indicate an error, you must return an error, e.g.,:
// Not correct. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::FAILED;T // This is how one indicates that a function failed because something was a nullptr. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::NullptrError(MAXON_SOURCE_LOCATION, "Could not get hold of scene data."_s); // For a function which is of type Result<void>, its also totally fine to do this on an error. void functions // can fail successfully, it is up to you to decide if an error is critical enough to halt execution of if you just // want it to silently terminate. if (!doc || !selectedObject || !bitmap || !foundTag) return maxon::OK; // we are okay with failing here.
For details see Error handling and Error Types
Cheers,
Ferdinand