Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Feedback on C4D Plugin – Mapping Textures to a Pixel Grid (Cinema 4D 2024 SDK)

    Cinema 4D SDK
    s24 c++ 2024 windows
    2
    2
    32
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      Pheolix
      last edited by

      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!

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @Pheolix
        last edited by ferdinand

        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:

        1. 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 a TagData::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 (because TagData::Message runs on the main thread and you therefore are there allowed to add and remove scene data). With TagData: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.
        2. 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.
        3. 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 a Result<T> for having returned an error instance instead of T. 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

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • First post
          Last post