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

    Blit to MultipassBitmap GeClipMap not working

    Cinema 4D SDK
    r20 c++
    2
    15
    1.7k
    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.
    • C4DSC
      C4DS
      last edited by C4DS

      In continuation to the MultipassBitmap problem I had with R16, it now seems I might have related issues with R20.

      Following is the full implementation of a dummy plugin to reproduce the issue.

      It's a Command plugin, when executed it will create a single layer bitmap, and a multi layer one. Both will be displayed into the Picture Viewer.
      Both bitmaps will have a background, on top of that a red diagonal cross, on top of that a green circle at the center, on top of that a blue rectangle in the top left quarter of the bitmap. And finally, on top of that a bitmap (the plugin's icon) being blitted in the top left corner.
      The single layer bitmap will have all drawing in a single "layer", while the multi layer bitmap does have each different drawing context in a separate layer.

      The single layer bitmap is drawn without any issue, but the multi layer one has issues when blitting.
      I get a "Cinema 4D has triggered a breakpoint" when performing the Blit() for the MultipassBitmap ... and resulting bitmap has no blitted bitmap. Still, the same method is used to blit on regular BaseBitmap, and this works as expected and does not report any problem.

      I can only assume I am doing something wrong, but I cannot figure out what exactly.

      // ========================
      // Cinema 4D C++ plugin
      //
      // PluginName: Test
      // Dummy "empty" plugin
      // ========================
      
      // Main.cpp
      
      #include "c4d.h"
      #include "lib_clipmap.h"
      
      // Dummy IDs - for demonstration purposes only
      #define MYCOMMAND_PLUGIN_ID	1000000
      
      // ====================================
      // CommandData
      // ====================================
      
      class MyCommand : public CommandData
      {
      	INSTANCEOF(MyCommand, CommandData)
      
      public:
      	virtual Bool Execute(BaseDocument* doc);
      
      	// Custom methods
      
      protected:
      	void DrawBackground(GeClipMap* clipmap);
      	void DrawCross(GeClipMap* clipmap);
      	void DrawCircle(GeClipMap* clipmap);
      	void DrawRectangle(GeClipMap* clipmap);
      	void DrawBitmap(GeClipMap* clipmap);
      
      	Bool WriteSingleLayer();
      	Bool WriteMultiLayer();
      };
      
      Bool MyCommand::Execute(BaseDocument* doc)
      {
      	WriteSingleLayer();
      	WriteMultiLayer();
      
      	return TRUE;
      }
      
      
      void MyCommand::DrawBackground(GeClipMap* clipmap)
      {
      	Vector color(128);
      	clipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255);
      	clipmap->FillRect(0, 0, clipmap->GetBw() - 1, clipmap->GetBh() - 1);
      }
      
      void MyCommand::DrawCross(GeClipMap* clipmap)
      {
      	Vector color(255,0,0);
      	clipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255);
      	clipmap->Line(0, 0, clipmap->GetBw() - 1, clipmap->GetBh() - 1);
      	clipmap->Line(0, clipmap->GetBh() - 1, clipmap->GetBw() - 1, 0);
      }
      
      void MyCommand::DrawCircle(GeClipMap* clipmap)
      {
      	Vector color(0,255,0);
      	clipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255);
      	clipmap->FillEllipse(100, 100, clipmap->GetBw() - 101, clipmap->GetBh() - 101);
      }
      
      void MyCommand::DrawRectangle(GeClipMap* clipmap)
      {
      	Vector color(0,0,255);
      	clipmap->SetColor(SAFEINT32(color.x), SAFEINT32(color.y), SAFEINT32(color.z), 255);
      	clipmap->FillRect(0, 0, clipmap->GetBw() / 2, clipmap->GetBh() / 2);
      }
      
      void MyCommand::DrawBitmap(GeClipMap* clipmap)
      {
      	AutoBitmap bitmap("icon.png"_s);
      	if (bitmap)
      	{
      		// use a clipmap for drawing/blitting the bitmap
      		AutoAlloc<GeClipMap> bitmapClipmap;
      		if (!bitmapClipmap)
      			return;
      		if (bitmapClipmap->Init(bitmap) != IMAGERESULT::OK)
      			return;
      
      		clipmap->Blit(0, 0, *bitmapClipmap, 0, 0, bitmapClipmap->GetBw() - 1, bitmapClipmap->GetBh() - 1, GE_CM_BLIT::COPY);
      	}
      }
      
      
      Bool MyCommand::WriteSingleLayer()
      {
      	AutoAlloc<BaseBitmap> outputBitmap;
      	if (!outputBitmap)
      		return false;
      	const Int32 bitdepth = 32;
      	const Int32 bitmapSize = 512;
      	IMAGERESULT res = outputBitmap->Init(bitmapSize, bitmapSize, bitdepth);
      	if (res != IMAGERESULT::OK)
      		return false;
      
      	AutoAlloc<GeClipMap> clipMap;
      	if (clipMap)
      	{
      		res = clipMap->Init(outputBitmap);
      		if (res != IMAGERESULT::OK)
      			return false;
      
      		clipMap->BeginDraw();
      
      		DrawBackground(clipMap);
      		DrawCross(clipMap);
      		DrawCircle(clipMap);
      		DrawRectangle(clipMap);
      		DrawBitmap(clipMap);
      
      		clipMap->EndDraw();
      	}
      
      	// open the resulting bitmap into the Picture Viewer
      	ShowBitmap(outputBitmap);
      
      	return true;
      }
      
      Bool MyCommand::WriteMultiLayer()
      {
      	const Int32 bitdepth = 32;
      	const Int32 bitmapSize = 512;
      	const COLORMODE colorMode = COLORMODE::ARGB;
      	MultipassBitmap* multiBitmap = MultipassBitmap::Alloc(bitmapSize, bitmapSize, colorMode);
      	if (!multiBitmap)
      		return false;
      
      	// get the first layer which is automatically created at allocation time
      	MultipassBitmap* layer = multiBitmap->GetLayerNum(0);
      	if (!layer)
      	{
      		MultipassBitmap::Free(multiBitmap);
      		return false;
      	}
      	layer->SetParameter(MPBTYPE::NAME, "Background");
      	layer->SetParameter(MPBTYPE::SAVE, true);
      	layer->SetParameter(MPBTYPE::SHOW, true);
      	// draw onto this layer via a ClipMap
      	AutoAlloc<GeClipMap> clipMap;
      	if (clipMap && (clipMap->Init(layer) == IMAGERESULT::OK))
      	{
      		clipMap->BeginDraw();
      
      		DrawBackground(clipMap);
      
      		clipMap->EndDraw();
      	}
      
      	// reuse the clipMap used for the background layer (reinit for each layer)
      
      	MultipassBitmap* crossLayer = multiBitmap->AddLayer(nullptr, colorMode);
      	if (crossLayer)
      	{
      		crossLayer->SetParameter(MPBTYPE::NAME, "Cross"_s);
      		crossLayer->SetParameter(MPBTYPE::SAVE, true);
      		crossLayer->SetParameter(MPBTYPE::SHOW, true);
      		//crossLayer->SetParameter(MPBTYPE::BLENDMODE, LAYER_NORMAL);
      
      		if (clipMap->Init(crossLayer) == IMAGERESULT::OK)
      		{
      			clipMap->BeginDraw();
      
      			DrawCross(clipMap);
      
      			clipMap->EndDraw();
      		}
      	}
      
      	MultipassBitmap* circleLayer = multiBitmap->AddLayer(nullptr, colorMode);
      	if (circleLayer)
      	{
      		circleLayer->SetParameter(MPBTYPE::NAME, "Circle"_s);
      		circleLayer->SetParameter(MPBTYPE::SAVE, true);
      		circleLayer->SetParameter(MPBTYPE::SHOW, true);
      		//circleLayer->SetParameter(MPBTYPE::BLENDMODE, LAYER_NORMAL);
      
      		if (clipMap->Init(circleLayer) == IMAGERESULT::OK)
      		{
      			clipMap->BeginDraw();
      
      			DrawCircle(clipMap);
      
      			clipMap->EndDraw();
      		}
      	}
      
      	MultipassBitmap* rectangleLayer = multiBitmap->AddLayer(nullptr, colorMode);
      	if (rectangleLayer)
      	{
      		rectangleLayer->SetParameter(MPBTYPE::NAME, "Rectangle"_s);
      		rectangleLayer->SetParameter(MPBTYPE::SAVE, true);
      		rectangleLayer->SetParameter(MPBTYPE::SHOW, true);
      		//rectangleLayer->SetParameter(MPBTYPE::BLENDMODE, LAYER_NORMAL);
      
      		if (clipMap->Init(rectangleLayer) == IMAGERESULT::OK)
      		{
      			clipMap->BeginDraw();
      
      			DrawRectangle(clipMap);
      
      			clipMap->EndDraw();
      		}
      	}
      
      	MultipassBitmap* bitmapLayer = multiBitmap->AddLayer(nullptr, colorMode);
      	if (bitmapLayer)
      	{
      		bitmapLayer->SetParameter(MPBTYPE::NAME, "Bitmap"_s);
      		bitmapLayer->SetParameter(MPBTYPE::SAVE, true);
      		bitmapLayer->SetParameter(MPBTYPE::SHOW, true);
      		//bitmapLayer->SetParameter(MPBTYPE::BLENDMODE, LAYER_NORMAL);
      
      		if (clipMap->Init(bitmapLayer) == IMAGERESULT::OK)
      		{
      			clipMap->BeginDraw();
      
      			DrawBitmap(clipMap);	// <--- performing the blit function reports a "Cinema 4D has triggered a breakpoint"
      
      			clipMap->EndDraw();
      		}
      	}
      
      	// open the resulting bitmap into the Picture Viewer
      	ShowBitmap(multiBitmap);
      
      	MultipassBitmap::Free(multiBitmap);
      	return true;
      }
      
      
      
      
      
      Bool RegisterMyCommand(void)
      {
      	return RegisterCommandPlugin(MYCOMMAND_PLUGIN_ID, "Test"_s, 0, AutoBitmap("icon.png"_s), "Test"_s, NewObjClear(MyCommand));
      }
      
      // ====================================
      // Plugin Main 
      // ====================================
      Bool PluginStart(void)
      {
      	ApplicationOutput("Test"_s);
      	RegisterMyCommand();
      
      	return TRUE;
      }
      void PluginEnd(void)
      {
      }
      Bool PluginMessage(Int32 id, void * data)
      {
      	switch (id) {
      	case C4DPL_INIT_SYS:
      		if (!g_resource.Init())
      			return FALSE;
      		return TRUE;
      	case C4DMSG_PRIORITY:
      		return TRUE;
      	case C4DPL_BUILDMENU:
      		break;
      	case C4DPL_ENDACTIVITY:
      		return TRUE;
      	}
      	return FALSE;
      }
      
      
      
      1 Reply Last reply Reply Quote 0
      • r_giganteR
        r_gigante
        last edited by

        Hi Daniel, thanks for reaching out us.

        Thanks a lot for the testing plugin but, unfortunately, even using your code I haven’t been able to reproduce it.
        Compiling your plugin with both our testing revision as well as with the official one I didn’t experienced Cinema triggering the breakpoint.

        I’ve tested on Cinema r20.057, Xcode 9.3 and High Sierra 10.13.6.

        Can you share some detail on your dev. environment? This might help me to match exact your configuration and get luckier in reproducing the issue.

        Best, Riccardo

        C4DSC 1 Reply Last reply Reply Quote 1
        • r_giganteR
          r_gigante
          last edited by

          Hi Daniel,
          I just want to rectify my previous post and I confirm that I’m able to reproduce the issue on Windows 10 and Visual Studio 2015.

          I’ll dig down further to see what is causing the different behavior between Mac and Windows and I let you know asap.

          Best, Riccardo

          C4DSC 1 Reply Last reply Reply Quote 2
          • C4DSC
            C4DS @r_gigante
            last edited by

            @r_gigante
            Sorry I didn't post any platform related information, or even added a windows tag. As I thought this wasn't a platform dependent issue, I did omit any (so I thought) irrelevant tags.

            Just to add, I still am on R20.030 ... for no particular reason. Will need to update to the latest version when I find the time.

            1 Reply Last reply Reply Quote 0
            • C4DSC
              C4DS @r_gigante
              last edited by

              @r_gigante
              I can confirm no problems exist on macOS, the output contains the blitted bitmap, as expected.
              I thus assume the provided implementation is OK, and should work on Windows ... in theory.
              Looking forward to you conclusion.

              1 Reply Last reply Reply Quote 0
              • r_giganteR
                r_gigante
                last edited by

                Hi Daniel,

                I filed a bug report with regard to this unexpected behavior. I will keep you updated on resolution.

                Best, Riccardo

                1 Reply Last reply Reply Quote 1
                • C4DSC
                  C4DS
                  last edited by

                  I was doing a search through the forum related to AutoBitmap and came along this topic.
                  What's the current status regarding R20.059, was it fixed in the latest update?
                  And what about R21?

                  1 Reply Last reply Reply Quote 0
                  • r_giganteR
                    r_gigante
                    last edited by

                    Hi Daniel, thanks for following up.

                    Honestly, and I would say with huge surprise, I can't reproduce anymore the issue at this time. I've tried rerunning your code on:

                    • R20.011
                    • R20.030
                    • R20.059
                    • R21.022
                      and on none of these I was able to hit the break point on Windows 10.

                    Can you kindly check again and see if it's still the case on your side? I would really like to dive more and understand what's happened in the meantime.

                    Cheers, R

                    C4DSC 1 Reply Last reply Reply Quote 0
                    • C4DSC
                      C4DS @r_gigante
                      last edited by

                      @r_gigante
                      I will try to check again, later today.
                      However, I noticed you mentioned -early in the thread- you could reproduce it with Visual Studio 2015.
                      Might it be the case you are currently using 2017 instead, and therefore don't encounter the issue anymore?
                      For R20 I am still developing with 2015 on my laptop (windows 8.1) and use another machine (windows 10) for R21 with Visual Studio 2017.
                      I will try to check on both development environments.

                      r_giganteR 1 Reply Last reply Reply Quote 0
                      • r_giganteR
                        r_gigante @C4DS
                        last edited by

                        @C4DS I've used VS2015 as well to run the tests.

                        Cheers

                        C4DSC 1 Reply Last reply Reply Quote 0
                        • C4DSC
                          C4DS @r_gigante
                          last edited by

                          @r_gigante

                          Tested on R20.057 with VS2015 on Windows 8.1 -> still get the exception, and no output
                          Tested on R21.026 with VS2017 on Windows 10 -> same exception, and no output.

                          1 Reply Last reply Reply Quote 0
                          • r_giganteR
                            r_gigante
                            last edited by r_gigante

                            Hi Daniel, I should strongly apologize here because due to an overlook of mine I forget to copy the test bitmap in the resource folder resulting in the code not to be executed and the breakpoint not to be hit.

                            Sorry about that.

                            I've looked more in detail and in order to get it done you have to actually set the draw mode to GE_CM_DRAWMODE::BLEND by calling

                            		// use a clipmap for drawing/blitting the bitmap
                            		AutoAlloc<GeClipMap> bitmapClipmap;
                            		if (!bitmapClipmap)
                            			return;
                            		if (bitmapClipmap->Init(bitmap) != IMAGERESULT::OK)
                            			return;
                            		clipmap->SetDrawMode(GE_CM_DRAWMODE::BLEND, GE_CM_SRC_MAX_OPACITY);
                            		clipmap->Blit(0, 0, *bitmapClipmap, 0, 0, bitmapClipmap->GetBw() - 1, bitmapClipmap->GetBh() - 1, GE_CM_BLIT::COPY);
                            
                            

                            This will ensure that upon calling the GE_CM_BLIT::COPY the GeClipMap->Blit() function using GE_CM_BLIT::COPY works properly.

                            Unfortunately this doesn't completely solve the issue, because it seems that initing a GeClipMap with a MultipassBitmap created via AddLayer has some issue I still need to investigate.

                            I'll get back on Monday, hopefully, with more details.

                            Again sorry for the confusion and have a nice weekend!

                            C4DSC 1 Reply Last reply Reply Quote 1
                            • C4DSC
                              C4DS @r_gigante
                              last edited by

                              @r_gigante

                              Without the line

                              clipmap->SetDrawMode(GE_CM_DRAWMODE::BLEND, GE_CM_SRC_MAX_OPACITY);
                              

                              I could continue after the "Cinema 4D has triggered a breakpoint" messagebox, now with that extra line I get a plain access violation. (tried on R20 with VS2015)

                              1 Reply Last reply Reply Quote 0
                              • r_giganteR
                                r_gigante
                                last edited by

                                Exactly, that's what I meant by

                                initing a GeClipMap with a MultipassBitmap created via AddLayer has some issue"

                                Without clipmap->SetDrawMode(GE_CM_DRAWMODE::BLEND, GE_CM_SRC_MAX_OPACITY); you hit a default case in a switch statement which fires a critical stop whilst using it you actually try to blit to the GeClipMap but now you end up in a memory issue.

                                I'll get back to you later next week
                                Cheers, R

                                C4DSC 1 Reply Last reply Reply Quote 1
                                • C4DSC
                                  C4DS @r_gigante
                                  last edited by C4DS

                                  @r_gigante
                                  While doing some code cleanup to add new features to a plugin, I noticed some comments regarding this particular topic. The comment mentioned the need for a workaround since the Blit() functionality on Windows was faulty.

                                  Problem with Blit() and MultipassBitmap still occurs after switching to Visual Studio 2017, Windows 10, running R20.059

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