<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document?]]></title><description><![CDATA[<p dir="auto">Hi,<br />
could you please help me find the recommended way to read vertex color tag's color data at a specific frame (different with current frame) without modifying current document?<br />
I think I should use BaseDocument::GetClone() and change the cloned document's time. However, I didn't find a good way to get the same vertex color tag and the object it belongs from the cloned document.<br />
Could you please give me a help on this?<br />
Thank you!</p>
]]></description><link>http://developers.maxon.net/forum//topic/16033/how-to-get-vertex-color-tag-s-data-for-a-specific-frame-different-with-current-frame-without-modifying-current-document</link><generator>RSS for Node</generator><lastBuildDate>Tue, 17 Mar 2026 15:24:20 GMT</lastBuildDate><atom:link href="http://developers.maxon.net/forum//topic/16033.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 20 Feb 2025 08:10:29 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Fri, 28 Feb 2025 00:36:12 GMT]]></title><description><![CDATA[<p dir="auto">Thank you very much for all your detailed explanation, <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a>!</p>
]]></description><link>http://developers.maxon.net/forum//post/75997</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75997</guid><dc:creator><![CDATA[BruceC]]></dc:creator><pubDate>Fri, 28 Feb 2025 00:36:12 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Wed, 26 Feb 2025 13:10:02 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/brucec">@<bdi>BruceC</bdi></a>,</p>
<blockquote>
<p dir="auto">To get the same tag from the cloned scene, I could use code like below, but I am wondering if there is an existing API to do this, as I think this is a basic need.</p>
</blockquote>
<p dir="auto">Your code is correct as far as I can see that at a glance (the important thing is that you implemented traversal only semi-recursively; that you have a manual loop for <code>GetNext</code>) as you are otherwise will quite quickly run into stack overflows. When you want to make it nicer, you could implement <a href="https://developers.maxon.net/forum/topic/15621/python-api-document-events/8" target="_blank" rel="noopener noreferrer nofollow ugc">fully interative traversal</a>. Because semi-recursive traversal can still produce stack overflows for very deep scene graphs (depth of ~500 nodes or more). Iterative traversal is generally also more performant.</p>
<p dir="auto">But this is all mostly splitting hairs; what you do is fine in 99.9% of the cases.</p>
<p dir="auto">The main question seems to be here if we offer abstracted scene traversal in C++, as we for example do in Python with <code>mxutils.IterateTree</code> and <code>mxutils.RecurseGraph</code>. And the answer is unfortunately still "no".  Maxime and I have talked about this with our core API colleagues more than once. But their stance has been always that doing this is trivial and everyone can do this themselves. In Python we are the system owners/architects; which is why we added there the functions in <code>mxutils</code>. Maxime and I recently talked about the subject again, and this is a good reminder to bring this up again with our core API team.</p>
<p dir="auto">PS: There is <a href="https://developers.maxon.net/docs/cpp/2025_1_0/namespacecinema.html#ade8df54c85f215e44ea6b8cd3c982edd" target="_blank" rel="noopener noreferrer nofollow ugc">IterateBaseList4D</a> which the core team recently added with 2025.0.0, but it is highly specialized and probably not the right fit for you here. The impl. is in the frameworks, so you can check it out.</p>
<blockquote>
<p dir="auto">I found I cannot read the cloned vertex color tag's data from the cloned document, because the owner of the cloned object is not an instance of Opoint [...]</p>
</blockquote>
<p dir="auto">You can always get the data count of a variable tag with <code>VariableTag::GetDataCount</code> (and a vertex color tag inherits from that type). When you want to get the point count from the host object, including cases where the object is a generator (and not just a plain instance of <code>Opolygon</code>), you have to reach into the (deform) cache of the object. For something like an <code>Ocube</code>, this is trivial, as <code>BaseObject::GetCache</code> will there return directly an <code>Opolygon</code> instance. But caches can get very complex and deformations (<code>BaseObject::GetDeformCache</code>) can also play a role. I have once unpacked the subject of caches <a href="https://github.com/Maxon-Computer/Cinema-4D-Python-API-Examples/blob/master/scripts/04_3d_concepts/modeling/geometry/geometry_caches_s26.py" target="_blank" rel="noopener noreferrer nofollow ugc">here</a> for Python, but the same principles apply to C++. Vertex map data counts on generators which target complex cache hierarchies could be tricky to get right from this direction, as our simulation team tends to write pretty sophisticated solutions. I would try the <code>VariableTag::GetDataCount</code> route first when you only want to read things.</p>
<p dir="auto">When you know that the node returned by <code>BaseList2D::GetMain/BaseTag::GetObject</code> is in instance of <code>Opolygon</code> (because you have for exampled tested for this with <code>C4Atom::IsInstanceOf</code>), you can then just static up-cast your node: <code>static_cast&lt;PolygonObject*&gt;(node)</code>.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
<p dir="auto">Here is some example code I have written in Python. Things are bit diffrent there, since in Python there is no <code>GeMarker</code> but only <code>MAXON_CREATOR_ID</code> (which also exists in C++) and in Python we have abstracted scene traversal in the form of <code>mxutils.RecurseGraph</code> and co. But it demonstrates the core principle.</p>
<h4>Result</h4>
<p dir="auto">When we clone the scene without <code>COPYFLAGS_PRIVATE_IDENTMARKER</code>, we are unable to find our object and its tag, when we do clone the scene with that flag, we find them both:<br />
<img src="/forum/assets/uploads/files/1740567520310-0d91929f-82cc-46f9-b1ce-c0baf689da72-image-resized.png" alt="0d91929f-82cc-46f9-b1ce-c0baf689da72-image.png" class=" img-fluid img-markdown" /></p>
<h4>Code</h4>
<pre><code class="language-py">"""Demonstrates how to find the 'same' scene element in a cloned document, when comparing nodes to
an original document.

In Python we can do this via BaseList2D.FindUniqueID() and MAXON_CREATOR_ID. In C++ we can do this
also via GeMarker for which MAXON_CREATOR_ID is just a quasi-alias as it returns the 16 bytes of
the marker of the node it is invoked on.

Must be run with a scene with at least one object with at least one tag.

Warning:

    Be EXTREMLY careful with PRIVATE_IDENTMARKER. It is private for a reason, as one can really 
    screw up things royally with it. Never insert multiple nodes with the same marker into one 
    document. Never insert multiple documents (a `BaseDocument` is also a node) with same 
    marker into Cinema 4D, e.g., via `InsertBaseDocument`. It is fine to have a temporary (non-
    inserted) document which is carbon copy of an inserted document (e.g., the active document).
"""

import c4d
import mxutils

from mxutils import CheckType

doc: c4d.documents.BaseDocument  # The currently active document.

def main() -&gt; None:
    """Called by Cinema 4D when the script is being executed.
    """
    # Get the first object and its first tag in the scene or halt when there is none.
    obj: c4d.BaseObject = CheckType(doc.GetFirstObject())
    tag: c4d.BaseTag = CheckType(obj.GetFirstTag())

    # Get the MAXON creator IDs of the object and the tag, i.e., the 16 bytes stored by the 
    # respective GeMarkers of the object and the tag. In Python GeMarker is not exposed, but
    # in C++ we can take both the direct GeMarker route and the a bit more indirect route via
    # MAXON_CREATOR_ID.
    objUuid: bytes = bytes(CheckType(obj.FindUniqueID(c4d.MAXON_CREATOR_ID)))
    tagUuid: bytes = bytes(CheckType(tag.FindUniqueID(c4d.MAXON_CREATOR_ID)))

    print(f"{objUuid.hex() = }")
    print(f"{tagUuid.hex() = }")

    def SearchDocument(domain: c4d.documents.BaseDocument) -&gt; None:
        """Searches the passed document for objects and tags that have the same #MAXON_CREATOR_ID
        as the first object and the first tag in the currently active document.
        """
        node: c4d.BaseList2D
        for node in mxutils.RecurseGraph(
            domain, False, True, True, branchFilter=[c4d.Obase, c4d.Tbase], stopBranchingEarly=True):
            nodeUuid: bytes = bytes(CheckType(node.FindUniqueID(c4d.MAXON_CREATOR_ID)))
            if (node.CheckType(c4d.Obase)): # the yielded node is an object
                print(f"\t{node.GetName() = } {nodeUuid.hex() == objUuid.hex() = }")
            elif (node.CheckType(c4d.Tbase)): # the yielded node is a tag
                print(f"\t{node.GetName() = } {nodeUuid.hex() == tagUuid.hex() = }")

    # Now clone the document without #PRIVATE_IDENTMARKER, i.e., cloning entities will be treated
    # as plainly instantiating them, and each node will get a new UUID. We will search the document
    # for matches but will find None.
    clone: c4d.documents.BaseDocument = CheckType(doc.GetClone(c4d.COPYFLAGS_0))
    print(f"Matches in: {clone = }")
    SearchDocument(clone)

    # Now clone the document with #PRIVATE_IDENTMARKER, i.e., cloning entities will be treated as
    # truly cloning them, and each node will get the same UUID. We will search the document for 
    # matches and will find them.
    #
    # NEVER INSERT DOCUMENTS cloned with #COPYFLAGS_PRIVATE_IDENTMARKER into
    # Cinema 4D. Never insert a node with a marker/MAXON_CREATOR_ID into  a document
    # which already holds a node with such marker: I.e., never clone a node from a document
    # with that flag and then insert the result. Crashes are the 'best' outcome here, you could
    # seriously courrupt user scenes like this.
    hardClone: c4d.documents.BaseDocument = CheckType(doc.GetClone(c4d.COPYFLAGS_PRIVATE_IDENTMARKER))
    print(f"Matches in: {hardClone = }")
    SearchDocument(hardClone)


if __name__ == '__main__':
    main()
</code></pre>
]]></description><link>http://developers.maxon.net/forum//post/75976</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75976</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Wed, 26 Feb 2025 13:10:02 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Tue, 25 Feb 2025 04:11:37 GMT]]></title><description><![CDATA[<p dir="auto">Thank you, @ferdinand.<br />
No worries at all, I know you must be very busy, just take your time. I appreciate all the help!<br />
Cheers!</p>
]]></description><link>http://developers.maxon.net/forum//post/75964</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75964</guid><dc:creator><![CDATA[BruceC]]></dc:creator><pubDate>Tue, 25 Feb 2025 04:11:37 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Mon, 24 Feb 2025 10:08:54 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/brucec">@<bdi>BruceC</bdi></a>,</p>
<p dir="auto">since I am probably not going to find the time to answer (2) today (sorry), I'll at least answer this:</p>
<blockquote>
<p dir="auto">I'm wondering the example you mentioned here, do you mean create a hidden vertex color tag to cache the data?</p>
</blockquote>
<p dir="auto">No, I did not mean a hidden vertex tag, as a vertex tag could not hold all that data (regularly). In principle, the cache could be just some field on some data structure, e.g., <code>HashMap&lt;Int32, Block&lt;ColorA&gt;&gt; _cacheForSomeVertexTag</code> - a hashmap that associates frame numbers with arrays of colors, the colors of the vertex map at that frame. To fill that array, you either need a "bake vertex colors" command, similarly to how you can bake Pyro, particles, RBD, and SBD in Cinema 4D. Or when reaching into the past while rendering is enough, you could do the "en passant" solution I mentioned above. There is a lot of room for improvement here for doing this more cleverly than a brutish "bake vertex colors" command.</p>
<p dir="auto">Such data would be of course volatile, i.e., would vanish when the user saves and closes a document. To change that, you would have to implement a node, e.g., a <code>VertexColorCache</code> tag, so that you can serialize that data with the scene. Technically speaking, you could also just inject your cache data into the data of a vertex color tag, but I would strongly advise against that. If you want to, you can then hide your <code>VertexColorCache</code> from the users view. Cinema 4D also hides quite a few caches from the users view, but I personally think that it would make more sense in this case to let the user have access. But I do not know as well as you do what you are trying to achieve, so I might be wrong.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum//post/75957</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75957</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Mon, 24 Feb 2025 10:08:54 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Mon, 24 Feb 2025 06:08:43 GMT]]></title><description><![CDATA[<blockquote>
<p dir="auto">The most common "pro" solution to that is caching. E.g., that you write yourself a vertex color cache in your case.</p>
</blockquote>
<p dir="auto">I'm wondering the example you mentioned here, do you mean create a hidden vertex color tag to cache the data?</p>
]]></description><link>http://developers.maxon.net/forum//post/75955</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75955</guid><dc:creator><![CDATA[BruceC]]></dc:creator><pubDate>Mon, 24 Feb 2025 06:08:43 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Sun, 23 Feb 2025 23:00:21 GMT]]></title><description><![CDATA[<p dir="auto">Thanks for your reply, <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a></p>
<blockquote>
<p dir="auto">Never user pointers to long term keep track of scene elements. Something not being nullptr does not mean you point to valid data. The node you point to could be long deleted, and then you point to garbage and access attempts will then result in access violations and a crash. Either use a BaseLink to store a reference to a scene element, or use a weak pointer. I.e., a pointer which becomes invalid when the pointed data is being deleted. You can for example see here how to use a maxon::WeakRawPtr.</p>
</blockquote>
<p dir="auto">True, I didn't really use the pointer to long term keep track of the linked vertex color tag. Although the plugin remembers the vertex color tag's pointer, but it's just used to compare if the vertex tag link parameter changes. i.e. before reading data from the vertex color tag, the plugin always read the vertex color tag link parameter.</p>
<blockquote>
<p dir="auto">The solution to this can be registering a plugin ID, e.g., ID_FOO_PLUGIN_IS_COMPUTE_PASS. When you then clone your document, or execute the passes on an existing document, you write under that ID for example a bool into the data container of the document. Your tags Execute(tag, ...) then gets the document from tag and checks for that flag being present, to stop what it does that causes the infinite update loop.</p>
</blockquote>
<p dir="auto">Thank you very much, this works! Glad to learn this trick!</p>
<blockquote>
<p dir="auto">You can of course also jump to a previous point, but then you do not have to sim from NOW to FUTURE but from 0 to PREVIOUS</p>
</blockquote>
<p dir="auto">Thanks!</p>
<blockquote>
<p dir="auto">The most common "pro" solution to that is caching.</p>
</blockquote>
<p dir="auto">Yes, the linked vertex color tag's data is cached to avoid reading its data again and again as long as the vertex color tag doesn't change.</p>
<p dir="auto">And for the question 3) I asked in the previous reply. I found after I use the trick to avoid infinite update loop, the problem is gone, owner of the cloned object is an instance of Opoint again. Do you know what the reason could be?</p>
<p dir="auto">Thank you!</p>
]]></description><link>http://developers.maxon.net/forum//post/75954</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75954</guid><dc:creator><![CDATA[BruceC]]></dc:creator><pubDate>Sun, 23 Feb 2025 23:00:21 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Fri, 21 Feb 2025 18:06:55 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/brucec">@<bdi>BruceC</bdi></a>,</p>
<p dir="auto">uff, that is a  lot of points. I'll try to comb through most of it, but I do not have that much time today. Feel free to ask for clarifications where I left out things.</p>
<blockquote>
<p dir="auto">Currently, I do this in the tag plugin's Execute() function. The tag plugin remembers the vertex color tag's pointer (initialized as <code>nullptr</code>) and dirty checksum (by <code>C4DAtom::GetDirty()</code>, and initialized as 0).</p>
</blockquote>
<p dir="auto">Never user pointers to long term keep track of scene elements. Something not being <code>nullptr</code> does not mean you point to valid data. The node you point to could be long deleted, and then you point to garbage and access attempts will then result in access violations and a crash. Either use a <code>BaseLink</code> to store a reference to a scene element, or use a weak pointer. I.e., a pointer which becomes invalid when the pointed data is being deleted. You can for example see <a href="https://github.com/Maxon-Computer/Cinema-4D-Cpp-API-Examples/blob/01580c54c2a8d222ce4b431a8a54acfac3a8a6ad/plugins/example.migration_2024/source/oboundingbox.cpp#L269" target="_blank" rel="noopener noreferrer nofollow ugc">here</a> how to use a <code>maxon::WeakRawPtr</code>.</p>
<blockquote>
<p dir="auto">However, I found <code>ExecutePasses()</code> called in <code>PrerollToTime()</code> triggers the tag plugin's <code>Execute()</code> function (I think this is the cloned tag in the cloned document), and <code>Execute()</code> function tries to read the linked vertex color tag at the speficied frame again, so <code>PrerollToTime()</code> -&gt; <code>ExecutePasses()</code> is called again, and triggers a new cloned tag in a new cloned document to run its <code>Execute()</code>, and so on.</p>
</blockquote>
<p dir="auto">Yes, that is true and a common problem (not only in Cinema 4D). The superficial reason is that my preroll code example also passes <code>True</code> for the third argument <code>expressions</code> (effectively API slang for tags). When you would pass there <code>false</code>, your tag would not be executed again. But also all other tags would not be executed (which is likely not what you want). The solution to this can be registering a plugin ID, e.g., <code>ID_FOO_PLUGIN_IS_COMPUTE_PASS</code>. When you then clone your document, or execute the passes on an existing document, you write under that ID for example a bool into the data container of the document. Your tags <code>Execute(tag, ...)</code> then gets the document from <code>tag</code> and checks for that flag being present, to stop what it does that causes the infinite update loop. When operating on a document not owned by you, you would then delete that flag or set it to false after you manually invoked the passes, so that future updates made by Cinema 4D (which owns and operates the document) then take the 'normal' route.</p>
<p dir="auto">The better solution is to generally design things in a manner that such infinite update loops cannot happen in the first place. I do not understand your problem well enough to give more concrete advice here. These scenarios are also not always avoidable.</p>
<blockquote>
<p dir="auto">According to the sample code PrerollToTime(), the lastFrame (the target frame) must not be earlier than the current scene's time.</p>
</blockquote>
<p dir="auto">The preroll function was just an example, not something you must follow to the letter. There is also a little bug I just see now, it should be of course <code>if (lastFrame &lt; firstFrame - 1)</code>. But the general idea is, that when you have a scene with simulations, i.e., stuff like Pyro or particles, where the state of the current frame depends on the last frame, you must basically cycle through all the correct scene states to get to that state. You can of course also jump to a previous point, but then you do not have to sim from <code>NOW</code> to <code>FUTURE</code> but from <code>0</code> to <code>PREVIOUS</code>.</p>
<p dir="auto">Prerolling is not necessary when the scene does not contain any simulations, e.g., just key framed position animations, all simulations are cached, or you do not care about simulations and their impact on the rest of scene. Given what kind of plugins you do develop, you likely want to preroll.</p>
<table class="table table-bordered table-striped">
<tbody>
<tr>
<td><img src="http://developers.maxon.net/forum/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=0b8ddba251d" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title=":warning:" alt="⚠" /> <em>Just to stress this again: Prerolling can be extremely expensive. When the user has a scene with 300 frames of Pyro simulations worth 30 minutes of computing, and you try to preroll half of it, your preroll function will run for 15 minutes.</em></td>
</tr>
</tbody>
</table>
<p dir="auto">What to do here, really depends on the exact case. Generally you try to avoid having to reach into the future or the past, as this is often a big no-no. The most common "pro" solution to that is caching. E.g., that you write yourself a vertex color cache in your case. When you only need to reach into the past, and this only applies in rendering, you could also effectively hide this from the user, as you must have passed and naturally calculated that value before (and therefore need no explicit cache recording).</p>
<p dir="auto">Will answer the (2) portion on Monday, running a bit out of Friday time right now.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum//post/75949</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75949</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Fri, 21 Feb 2025 18:06:55 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Fri, 21 Feb 2025 02:52:34 GMT]]></title><description><![CDATA[<p dir="auto">Thank you for the reply, <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/ferdinand">@<bdi>ferdinand</bdi></a>,</p>
<ol>
<li>
<p dir="auto">Thanks for the <code>PrerollToTime()</code> function! I didn't know that I need to <code>ExecutePasses()</code> for each frame until the <code>lastFrame</code>.</p>
<p dir="auto">I'm writing a tag plugin that has a parameter which is a link to an existing vertex color tag, and a parameter to allow user specify a frame number. These two parameters work together, so the plugin will get the data from the vertex color tag at the specific frame, and use the data to do the rendering across all frames.</p>
<ul>
<li>
<p dir="auto">1.1 Because the tag plugin depends the linked vertex color tag, so whenever there is a change in the vertex color tag, the plugin needs to update its internal data based on the updated vertex color tag. Currently, I do this in the tag plugin's Execute() function. The tag plugin remembers the vertex color tag's pointer (initialized as <code>nullptr</code>) and dirty checksum (by <code>C4DAtom::GetDirty()</code>, and initialized as 0). So <code>Execute()</code> checks if the vertex color tag read from the link parameter changes or the vertex color tag's dirty checksum changes, if it changes, the vertex color tag's data at the specified frame will be read again.</p>
<p dir="auto">However, I found <code>ExecutePasses()</code> called in <code>PrerollToTime()</code> triggers the tag plugin's <code>Execute()</code> function (I think this is the cloned tag in the cloned document), and <code>Execute()</code> function tries to read the linked vertex color tag at the speficied frame again, so <code>PrerollToTime()</code> -&gt; <code>ExecutePasses()</code> is called again, and triggers a new cloned tag in a new cloned document to run its <code>Execute()</code>, and so on.</p>
<p dir="auto">This makes me wonder if I'm not using the correct way to check if the linked vertex color tag's change. Could you please help find out what's C4D's recommended way to handle such case?</p>
</li>
<li>
<p dir="auto">1.2 According to the sample code <code>PrerollToTime()</code>, the <code>lastFrame</code> (the target frame) must not be earlier than the current scene's time. This means if the scene's current time is later than the frame number (say, user slides the timeline to frame 10, but the frame number parameter is set to 5), there will be no way to get the desired data from the vertex color tag, right?  How does C4d handle this kind of situation? Or there is no such situation at all in native C4d?</p>
</li>
</ul>
</li>
<li>
<p dir="auto">To get the same tag from the cloned scene, I could use code like below, but I am wondering if there is an existing API to do this, as I think this is a basic need.</p>
</li>
</ol>
<pre><code class="language-cpp">BaseObject* getObjectByMarker(const BaseDocument&amp; doc, const GeMarker&amp; objMarker, BaseObject* start = nullptr)
{
    for (BaseObject* obj = start ? start : doc.GetFirstObject(); obj != nullptr; obj = obj-&gt;GetNext())
    {
        if (obj-&gt;GetMarker().IsEqual(objMarker))
        {
            return obj;
        }
        else
        {
            // check children
            BaseObject* childObj = obj-&gt;GetDown();
            if (childObj)
            {
                BaseObject* found = getObjectByMarker(doc, objMarker, childObj);
                if (found)
                {
                    return found;
                }
            }
        }
    }
    return nullptr;
}

BaseTag* getTagByMarker(const BaseDocument&amp; doc, const GeMarker&amp; objMarker, const GeMarker&amp; tagMarker)
{
    BaseObject* obj = getObjectByMarker(doc, objMarker);
    if (obj)
    {
        for (BaseTag* tag = obj-&gt;GetFirstTag(); tag; tag = tag-&gt;GetNext())
        {
            if (tag-&gt;GetMarker().IsEqual(tagMarker))
            {
                return tag;
            }
        }
    }
    return nullptr;
}
</code></pre>
<ol start="3">
<li>
<p dir="auto">I found I cannot read the cloned vertex color tag's data from the cloned document, because the owner of the cloned object is not an instance of <code>Opoint</code>.<br />
According to the <a href="https://developers.maxon.net/docs/Cinema4DCPPSDK/page_manual_vertexcolortag.html" target="_blank" rel="noopener noreferrer nofollow ugc">document</a>, to read data from vertex color tag, I need to get the point count of the <code>polyObject</code> who owns the vertex color tag.</p>
<p dir="auto">To do that, the <code>BaseObject</code> returned from <code>BaseTag::GetObject()</code> will need to be converted to <code>PointObject</code>, then <code>PointObject::GetPointCount()</code> will be used to to get the point count.<br />
However, I found if the tag is from a cloned document, the <code>BaseObject</code> returned from <code>BaseTag::GetObject()</code> is not an instance of <code>Opoint</code>, so it cannot be converted to <code>PointObject</code>.</p>
<p dir="auto">I can confirm that the <code>BaseObject</code> got from the original tag in the original document can be converted to <code>PointObject</code>.</p>
<p dir="auto">I try to use the object from the cloned document, because I think the point count might change in a different frame. (The cloned document is at a different time)</p>
<p dir="auto">BTW, the cloned document is created by <code>doc-&gt;GetClone(COPYFLAGS::PRIVATE_IDENTMARKER, nullptr)</code>.</p>
</li>
</ol>
<p dir="auto">Sorry for the long list, please let me know if I need to split above questions to different topics.<br />
Now, all these questions above make me wonder if the usage is designed appropriately.<br />
Maybe from C4D design's point of view, it is not a proper design to let user specify the time (different with the current frame, and even can be a earlier frame) when the tag's data should be used to render all frames?</p>
<p dir="auto">Thank you!</p>
]]></description><link>http://developers.maxon.net/forum//post/75915</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75915</guid><dc:creator><![CDATA[BruceC]]></dc:creator><pubDate>Fri, 21 Feb 2025 02:52:34 GMT</pubDate></item><item><title><![CDATA[Reply to how to get vertex color tag&#x27;s data for a specific frame (different with current frame) without modifying current document? on Fri, 21 Feb 2025 12:40:18 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/forum/user/brucec">@<bdi>BruceC</bdi></a>,</p>
<p dir="auto">Thank you for reaching out to us. Let's split these effectively two questions into two parts.</p>
<h4>Evaluating a BaseDocument at time #t</h4>
<p dir="auto">When you want to know the state of a scene at a time, #t, you can do this by setting the time of the document (<code>BaseDocument::SetTime</code>) and then executing its passes (<code>BaseDocument::ExecutePasses</code>), which is CInema 4D API slang for updating the scene state. This is configurable and can evaluate animations, build caches, and execute expressions, i.e., do the whole scene evaluation. But when you have a very heavy document, executing the passes is of course a not so cheap operation.</p>
<p dir="auto">A more clever solution can be to manually interpolate animations - when that is all you need - via <code>CCurve.GetValue</code>. But that only works for animations that defined by keyframes and are decomposable into <code>float</code> values. The former is here not given for vertex colors, as you can only animate them procedurally.</p>
<p dir="auto">This is all further complicated in a real life scenario, as being at frame <code>t</code>, then jumping to frame <code>t + 10</code>, and then just executing the passes might not be enough. The reason is because what you to query might be dependent on simulations; and your output will then be wrong when you just execute frame <code>t</code> and <code>t + 10</code>, instead of <code>t</code>, <code>t + 1</code>, ..., <code>t + 10</code>.</p>
<p dir="auto">So, a  preroll function could look like this:</p>
<pre><code class="language-cpp">using namespace cinema;

static maxon::Result&lt;void&gt; PrerollToTime(BaseDocument* const doc, const BaseTime&amp; time)
{
  iferr_scope;
  CheckArgument(doc, "doc"_s, "Document is nullptr."_s);

  const Int32 fps = doc-&gt;GetFps();
  const Int32 firstFrame = doc-&gt;GetTime().GetFrame(fps) + 1;
  const Int32 lastFrame = time.GetFrame(fps);
  if (lastFrame &lt; firstFrame - 1)
    return maxon::IllegalArgumentError(
      MAXON_SOURCE_LOCATION, "The target time is before the current time."_s);

  // Loop over all frames we need to reach #t and execute the passes. What to execute for each pass
  // (caches, animations, expressions) depends on what you want to achieve, and will of course have
  // an impact on the performance. Note that things likes cache building can have an impact on
  // animations and expressions, and vice versa. So, when one needs the 'true' scene state, one must
  // often calculate everything.
  for (Int32 frame = firstFrame; frame &lt;= lastFrame; ++frame)
  {
    doc-&gt;SetTime(BaseTime(frame, fps));
    // Execute the passes for everything in the main thread (nullptr), use your thread instead when
    // you have one.
    if (!doc-&gt;ExecutePasses(nullptr, true, true, true, BUILDFLAGS::NONE))
      return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Failed to execute pass."_s);
  }
  
  // For the last frame we should execute the passes twice, so that the scene can settle.
  if (!doc-&gt;ExecutePasses(nullptr, true, true, true, BUILDFLAGS::NONE))
      return maxon::UnexpectedError(MAXON_SOURCE_LOCATION, "Failed to execute pass."_s);

  // The document is now in the state of #time.
  return maxon::OK;
}
</code></pre>
<h4>Finding a scene element #e in two scenes</h4>
<p dir="auto">I am a bit surprised that you ask that, as this is sort of the bread and butter for what you are doing. So, I might be misunderstanding you here. If that is so, please clarify what you mean.</p>
<p dir="auto">The identity of scene elements is expressed in Cinema 4D by <a href="https://developers.maxon.net/docs/cpp/2025_1_0/page_manual_gemarker.html" target="_blank" rel="noopener noreferrer nofollow ugc">GeMarker</a>. Such markers are given when objects are allocated (and by default also when copied) and are a hash of the creating machine's mac address, a timestamp and some secret sauce. An alternative way to retrieve the same data is <a href="https://developers.maxon.net/docs/cpp/2025_1_0/page_manual_baselist2d.html#page_manual_baselist2d_properties_unique_id" target="_blank" rel="noopener noreferrer nofollow ugc">BaseList2D::FindUniqueID(MAXON_CREATOR_ID)</a> which just returns the raw data of the <code>GeMarker</code> obtainable via <code>BaseList2D::GetMarker</code>. When you copy scene elements or whole scenes, by default they are given new markers. You can prevent that with <code>COPYFLAGS::PRIVATE_IDENTMARKER</code>.</p>
<blockquote>
<p dir="auto"><img src="http://developers.maxon.net/forum/assets/plugins/nodebb-plugin-emoji/emoji/android/26a0.png?v=0b8ddba251d" class="not-responsive emoji emoji-android emoji--warning" style="height:23px;width:auto;vertical-align:middle" title=":warning:" alt="⚠" /> Never insert multiple nodes with the same marker into a scene.</p>
</blockquote>
<p dir="auto">An alternative could be to use links, i.e., a <code>BaseLinks</code>, for example in a <code>BaseContainer</code> stored with the document. But that is also just built on top of <code>GeMarker</code>.</p>
<p dir="auto">Cheers,<br />
Ferdinand</p>
]]></description><link>http://developers.maxon.net/forum//post/75913</link><guid isPermaLink="true">http://developers.maxon.net/forum//post/75913</guid><dc:creator><![CDATA[ferdinand]]></dc:creator><pubDate>Fri, 21 Feb 2025 12:40:18 GMT</pubDate></item></channel></rss>