Frame Selected Object



  • On 09/05/2014 at 15:06, xxxxxxxx wrote:

    I'm trying to render the active object isolated from all other objects of the document.
    To do so, from inside my plugin, I created a new document, created a clone of the intended object and inserted it in the new document. Then I performed a render of that object and finally, get rid of that document.
    It all works fine, except that I can't seem to perform a "Frame Selected Object" on the object that is inside the new document. When I run that command, the current object, still in my current object gets framed.
    I'm using this code:

    doc = documents.GetActiveDocument()
    new_doc=c4d.documents.BaseDocument()
    rd = new_doc.GetActiveRenderData().GetData()
    new_tree=node.GetClone()
    new_doc.InsertObject(new_tree)
    xres = 128
    yres = 128
    bmp = bitmaps.BaseBitmap()
    bmp.Init(x=xres, y=yres, depth=24)
    rd[c4d.RDATA_XRES]=xres
    rd[c4d.RDATA_YRES]=yres
    new_doc.SetSelection(new_tree,c4d.SELECTION_NEW)
    c4d.CallCommand(12151) # Frame Selected Objects
    res = documents.RenderDocument(new_doc, rd, bmp, c4d.RENDERFLAGS_EXTERNAL)
    if res==c4d.RENDERRESULT_OK:
        bitmaps.ShowBitmap(bmp)
    new_doc.Flush()

    How can I frame just the cloned object, inside the new document?



  • On 10/05/2014 at 00:05, xxxxxxxx wrote:

    How do you think the CallCommand would know that it should use your
    new document? It operates always on the active scene only.

    -Niklas



  • On 10/05/2014 at 01:11, xxxxxxxx wrote:

    I thought it would operate like how you say, but I tried the "shot in the dark" of selecting the newly inserted object and hopped that it would affect the last selected object ;-)
    So, it must be made by hand, adjusting the virtual camera of the new document?
    Does anyone now how to calculate the placement and orientation of the camera to frame an object?



  • On 10/05/2014 at 03:15, xxxxxxxx wrote:

    You didn't make the new_doc the current document. ;)
    Insert it and make it the active document.



  • On 10/05/2014 at 03:54, xxxxxxxx wrote:

    Thank you, Niklas. It worked!!!
    However, the object is not being framed correctly.
    My code is this:

    doc = documents.GetActiveDocument()
    new_doc=c4d.documents.BaseDocument()
    rd = new_doc.GetActiveRenderData()
    rdc = rd.GetData()
    new_tree=node.GetClone()
    new_doc.InsertObject(new_tree)
    xres = 256
    yres = 256
    bmp = bitmaps.BaseBitmap()
    bmp.Init(x=xres, y=yres, depth=24)
    rdc[c4d.RDATA_XRES]=xres
    rdc[c4d.RDATA_YRES]=yres
    rd.SetData(rdc)
    c4d.documents.SetActiveDocument(new_doc)
    new_doc.SetActiveRenderData(rd)
    c4d.EventAdd(c4d.EVENT_FORCEREDRAW)
    new_doc.SetSelection(new_tree,c4d.SELECTION_NEW)
    c4d.CallCommand(12151) # Frame Selected Objects
    res = documents.RenderDocument(new_doc, rdc, bmp, c4d.RENDERFLAGS_EXTERNAL)
    c4d.documents.SetActiveDocument(doc)
    if res==c4d.RENDERRESULT_OK:
        bitmaps.ShowBitmap(bmp)
    new_doc.Flush()

    The render shows a clipped object :-(



  • On 10/05/2014 at 05:33, xxxxxxxx wrote:

    Already tried with:

    c4d.CallCommand(12148) # Frame Geometry

    and with

    c4d.CallCommand(12288) # Frame All

    To no avail :-(



  • On 10/05/2014 at 11:29, xxxxxxxx wrote:

    Ok, never mind. I created my own framing code. It works for what I need.



  • On 11/05/2014 at 04:26, xxxxxxxx wrote:

    Hi Rui,

    # Copyright (c) 2014  Niklas Rosenstein
    #
    # Permission is hereby granted, free of charge, to any person obtaining a copy
    # of this software and associated documentation files (the "Software"), to deal
    # in the Software without restriction, including without limitation the rights
    # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    # copies of the Software, and to permit persons to whom the Software is
    # furnished to do so, subject to the following conditions:
    #
    # The above copyright notice and this permission notice shall be included in
    # all copies or substantial portions of the Software.
    #
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    # THE SOFTWARE.
    r"""
    This script shows how to frame the current object and then render
    it into a 256x256 image without loosing information such as the
    object's materials. Absolutely non-destructive and memory-optimized.
    
    Changelog:
    v 0.1.0 (May 11, 2014)
        Initial version
    """
    
    import c4d
    
    class Remember(object) :
        r""" Remembers the hierarchy position of a node and can restore
        it at a later time. A ``root_routine`` is required when the node
        was the first and only node in the list. """
    
        def \__init\_\_(self, node) :
            super(Remember, self).\__init\_\_()
            self.parent = node.GetUp()
            self.pred = node.GetPred()
    
        def restore(self, node, root_routine) :
            node.Remove()
            if self.pred:
                node.InsertAfter(self.pred)
            elif self.parent:
                node.InsertUnder(self.parent)
            else:
                root_routine(node)
    
    class DocumentContext(object) :
        r""" Context manager for a temporary document that will be inserted
        when entering the context and \*killed\* when leaving the context. The
        document can and must not be used after the context was left.
    
        Inside the context, the document is inserted and active. """
    
        def \__init\_\_(self, doc=None) :
            if not doc:
                doc = c4d.documents.BaseDocument()
            elif not isinstance(doc, c4d.documents.BaseDocument) :
                raise TypeError('expected BaseDocument')
    
            super(DocumentContext, self).\__init\_\_()
            self.doc = doc
    
        def \__enter\_\_(self) :
            c4d.documents.InsertBaseDocument(self.doc)
            c4d.documents.SetActiveDocument(self.doc)
            return self.doc
    
        def \__exit\_\_(self, exc_type, exc_value, exc_tb) :
            c4d.documents.KillDocument(self.doc)
    
    def render_object(op, width, height) :
        r""" Renders the object \*op\* with the specified resolution. Returns
        the resulting :class:`c4d.bitmaps.BaseBitmap`. It tries to keep the
        memory overhead at a minimum by stripping down op's document before
        cloning it. """
    
        doc = op.GetDocument()
        if not doc:
            raise ValueError('op is not in a document')
    
        # Remember the original position of \*op\* in the hierarchy and
        # remove it from the tree.
        location = Remember(op)
        op.Remove()
    
        # Put all the objects in the document into a Null-Object that
        # we will keep separate.
        root_null = c4d.BaseObject(c4d.Onull)
        for obj in reversed(doc.GetObjects()) :
            obj.Remove()
            obj.InsertUnder(root_null)
    
        # Insert it into the document again. Then we clone it to get a 
        # document with all the materials that the object referenced.
        doc.InsertObject(op)
        new_doc = doc.GetClone(c4d.COPYFLAGS_0)
    
        # Restore the structure of the original document.
        for obj in reversed(root_null.GetChildren()) :
            obj.Remove()
            doc.InsertObject(obj)
        root_null.Remove()
        location.restore(op, root_routine=doc.InsertObject)
    
        # Frame the object and render the new document.
        with DocumentContext(new_doc) :
            new_doc.SetActiveObject(new_doc.GetFirstObject())
            force_redraw() # Redraw is required to create the Geometry
            c4d.CallCommand(12151) # Frame Selected Objects
            return render_document(new_doc, width, height)
    
    def render_document(doc, width, height, depth=24) :
        r""" Renders \*doc\* with the specified width and height. """
    
        bmp = c4d.bitmaps.BaseBitmap()
        bmp.Init(x=width, y=width, depth=depth)
        
        rdc = doc.GetActiveRenderData().GetData()
        rdc[c4d.RDATA_XRES] = width
        rdc[c4d.RDATA_YRES] = height
        
        c4d.documents.RenderDocument(doc, rdc, bmp, c4d.RENDERFLAGS_EXTERNAL)
        return bmp
    
    def force_redraw() :
        r""" Force a redraw for the current document. """
    
        flags = c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_FORCEFULLREDRAW
        c4d.DrawViews(flags) 
    
    def main() :
        if not op:
            c4d.gui.MessageDialog("Please select one object.")
            return
    
        bmp = render_object(op, 256, 256)
        c4d.bitmaps.ShowBitmap(bmp)
    
    main()
    

    This should help you.
    -Niklas



  • On 11/05/2014 at 06:49, xxxxxxxx wrote:

    Thank you Niklas. I learned a lot with this code.


Log in to reply