Notifications
Clear all

[Closed] Viewport Sketch Tool using GDI+

Here is a Viewport Sketch Tool different than the others. It doesn’t uses the viewport drawing MAXScript capabilities but the .NET GDI+ library.
It simply draws in a bitmap displayed in the current selected viewport.
The main drawback is the flickering. So you can disable the drawing in the viewport when desired.

SketchTool.zip

This tool is in Beta stage. I will add an animation mode (sketch for each frame) and try to solve the flickering problem.

11 Replies

awesome yannick, i love the gdi+ methods you’ve used.

I was just posting on another thread about the use of dispose() as a way of clearing unmanaged resources. Is GDI+ the only real time you have to worry about doing this yourself and why do i get errors occasionaly calling this function even on objects that list it as a method?

i’ve also been working on some ui GDI+ stuff here if you were interested! – http://lonerobot.com/BotNetGDI.html

Hi Pete,

Thanks for the feedback.

I’ve never heard about this problems with the Dispose() function in Max.
When I read your post about this problem in the other thread, I remembered that I didn’t release my pen in DrawSketch(). So I added the call to Dispose() but there’s no error when running…
I ran your sample with Brush1 but got no error under Max 2009.

I browse your website regularly and all your articles are very interesting!

hi yannick,

thanks! re – dispose – that is bonkers, its working okay for me now! typical! Perhaps in the past i was trying to dispose something that had already been removed!

BTW, what are your thoughts on the reason for the flickering? I’ve had to look at this myself for the custom UI controls i’ve been writing. seems to be a combination of double buffering and overiding the protected onbackgroundpaint event stabilises the control for me.

In fact the problem I have is I’m drawing directly in the viewport window creating a Graphics from its handle. I can’t use the .NET double buffer because the viewport isn’t a Windows Forms Control.
I’m doing a simple double buffer using a GDI+ bitmap. I draw the sketch to a bitmap (with transparency) and display it in the viewport graphics.
And I don’t use a redraw view callback but a .NET timer because Max isn’t aware of what I’m doing in the viewport window.

brilliant, i love it! i will have a proper look over the weekend. great work, yannick!

Hi Yannick,
first and foremost I find your script brilliant, even if I’m not able to understand dotNet code at a glance. This is definitely a good push to start studying it along with C++ (I’m interested in MaxScript extensions through SDK like AVGuard and yours).

I wish to point out some issues found running the script in 3ds Max 9 x64 on an Athlon x2 5000+

  • As the script is started and the panel is displayed, the cpu load jumps from 5% (idle) to about 25% without doing anything else, and drops to idle again as the panel is closed.

  • The cpu load grows up to 50% (1 cpu full load) after the first stroke without doing anything else. The brush gets slower and slower by adding strokes. After a while it draws quite large segments, if moved at normal speed.

  • The cpu load drops to about 25% as the view is cleared.

Thank you for your effort and creative ideas.

  • Enrico

Hi Enrico,

In fact, when the tool is run, I initialize the drawing in the current active viewport.
What’s the size of your viewport window ?
Have you tried to restart Max and your computer ?

EDIT:
Also, try to change the interval value in millisecs for the timer in the line:

vptTimer.Interval = 1

Set a value of 10 or 100 to test.

 PEN

Nice work, this is a keep for my library.

Hi Yannick,
I got a chance to run some tests. I disabled or uninstalled any other plugin/script to get a fresh Max start. The system (Win XP 64) has been restarted. 3ds Max has been restarted after each script modification. The 3dsmax process is at cpu full load at 50% since it is a dual core processor.

Viewport sizes

Without panel docked
Not maximized: 542×421 px
Maximized: 1092×849 px

With panel docked
Not maximized: 499×421 px
Maximized: 1006×849 px

vptTimer.Interval = 1

Panel closed:
3dsmax process cpu load = idle (0%)

Panel opened:
3dsmax process cpu load = almost idle (2% – 5%) not maximized viewport
3dsmax process cpu load = about half load (20% – 25%) maximized viewport

Panel opened, after a single quite long scribble, brush size 1:
3dsmax process cpu load = full load (48% – 50%) at any viewport size

Panel opened, after a single quite long scribble, “Disable” checkbutton pressed:
3dsmax process cpu load = idle (0%)

Panel opened, after a single long scribble, “Disable” checkbutton released:
3dsmax process cpu load = full load (48% – 50%)

Panel opened, after a single quite long scribble, viewport cleared:
3dsmax process cpu load = almost idle (2% – 4%) not maximized viewport
3dsmax process cpu load = less than half load (15% – 20%) maximized viewport

Panel closed:
3dsmax process cpu load = idle (0%)

vptTimer.Interval = 10

Panel closed:
3dsmax process cpu load = idle (0%)

Panel opened:
3dsmax process cpu load = almost idle (2% – 4%) not maximized viewport
3dsmax process cpu load = about half load (20% – 25%) maximized viewport

Panel opened, after a single long scribble, brush size 1:
3dsmax process cpu load = full load (48% – 50%) at any viewport size

Note:
More scribbling is required to reach the full load with timer interval set to 10

Panel opened, after a single long scribble, “Disable” checkbutton pressed:
3dsmax process cpu load = idle (0%)

Panel opened, after a single long scribble, “Disable” checkbutton released:
3dsmax process cpu load = full load (48% – 50%)

Panel opened, after a single long scribble, viewport cleared:
3dsmax process cpu load = almost idle (2% – 3%) not maximized viewport
3dsmax process cpu load = less than half load (15% – 20%) maximized viewport

Panel closed:
3dsmax process cpu load = idle (0%)

vptTimer.Interval = 100

Panel closed:
3dsmax process cpu load = idle (0%)

Panel opened:
3dsmax process cpu load = almost idle (0% – 1%) not maximized viewport
3dsmax process cpu load = almost idle (0% – 2%) maximized viewport

Panel opened, after a single very long scribble, brush size 1:
3dsmax process cpu load = full load (48% – 50%) at any viewport size

Note:
Even more scribbling is required to reach the full load with timer interval set to 100. The stroke runs smooth for a longer time.

Panel opened, after a single very long scribble, “Disable” checkbutton pressed:
3dsmax process cpu load = idle (0%)

Panel opened, after a single very long scribble, “Disable” checkbutton released:
3dsmax process cpu load = full load (48% – 50%)

Panel opened, after a single very long scribble, viewport cleared:
3dsmax process cpu load = almost idle (0% – 1%) not maximized viewport
3dsmax process cpu load = almost idle (0% – 2%) maximized viewport

Panel closed:
3dsmax process cpu load = idle (0%)

Additional notes:

At start, brush runs smooth despite the cpu load, performances degrade as the stroke goes on.

Brush size affects the stroke length before reaching the sluggish point when it is behind the mouse cursor and draws visible segments. The smaller the brush the longer the stroke and vice versa.

The difference in 3dsmax process cpu load at initialization and after clearing viewport could be given by the fact that at initialization the viewport space is slightly bigger since the panel isn’t already docked, while after clearing it gets the actual viewport size, but I don’t know what’s really going on under the hood, so it’s only a guess.

I hope this helps. I’m interested in this procedure alternative to gw viewport drawing, and will delve into it as soon as possible. Thank you.

  • Enrico
Page 1 / 2