Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (495)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Live Shapes transformations  (Read 1172 times)
0 Members and 1 Guest are viewing this topic.
Offline virgus

Junior Newbie





« Posted 2003-09-27 21:02:48 »

Hi all,

I'm writing a vector based draw program. I use Shape as common type for my draw elements: Rectangle, Oval, and GeneralPath for freehand drawing. User can also move, rotate and resize such elements in wysiwyg fashion.
When he drags the mouse to modify an element, I update the canvas.
My two problems are:

  • the amount of cpu it takes to render elements to the canvas (30% CPU on win2k AthlonXP1900+ 512Mb)
  • the gc that pauses every 4 seconds the rendering process (I'm using jdk 1.4.1_03)


Can you please help me ?

Here is the rotation code:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
public final void rotate(Drawable d, double a) {
            DrawableState state = d.state;
            Rectangle actualWorkingBounds = state.actualWorkingBounds;
            state.rotation += a;
            trans.setToIdentity();
            trans.rotate(a, state.center.getX(), state.center.getY());
            d.working.transform(trans);
            actualWorkingBounds.setRect(d.working.getBounds());
            state.location.setLocation(actualWorkingBounds.getX(), actualWorkingBounds.getY());
      }

where d.working is a GeneralPath and trans is an AffineTransform.

Here is the rendering code (inside a Canvas subclass):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
public final void repaintNow(Rectangle clip) {
   int x, y, w, h;
   Graphics2D g = buffer.createGraphics();
   g.setClip(clip.x,clip.y,clip.width,clip.height);
   g.setColor(Color.white);
   g.fillRect(clip.x,clip.y,clip.width,clip.height);
   g.setRenderingHints(renderingHints);
   for(int k = size; k >= 0 ; k--) {
      if(controller.getTotalBounds(draws[k]).intersects  (clip)) {
         draws[k].paint(g);
      }
   }
   g.dispose();
   getGraphics().drawImage(buffer, 0, 0, null);
   try{ Thread.sleep(14); } catch (Exception exn){}
}

where buffer is a BufferedImage created with:
1  
buffer = getGraphicsConfiguration().createCompatibleImage(dimension.width, dimension.height);

When user drags I call the rotate code and the repaintNow one.

Thanks A LOT guys.

------------------------------------------------------------
Beware of bugs in the above code;
I have only proved it correct, not tried it!
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #1 - Posted 2003-09-29 12:25:53 »

Many questions.. hopefully leading to something helpful:

How many Shapes are you drawing when you see the 30% CPU load?  How much does adding a shape affect this?
Have you tried incremental garbage collection? (-incgc)
Why do you have a sleep() in your repaintNow routine?
When are you calling repaintNow?
Are you using Swing?
Have you tried calling it only from paint(Graphics g) and simply requesting repaints when the user draws?
Have you disabled Swing's double buffering for this component, since you are doing your own?

Offline virgus

Junior Newbie





« Reply #2 - Posted 2003-09-29 12:56:16 »

First, answers:

  •  300 shapes
  •  No, can you explain me what differences I'll see if I use incgc ?
  • I call sleep because if I don't, dragging takes 99% of cpu and I need some cpu (30%) to do other things (streaming audio/video)...
  • I call repaintNow every time "mouseDragged" is called
  • yes I use Swing
  • I've noticed that calling repaint is not as accurate as I need... sometimes the shape remains 2-3 pixels far from cursor when user stops dragging
  • yes, I disabled it


Now, what I done to solve my problems:

  • now buffer is a VolatileImage (createCompatibleVolatileImage)
  • I've removed all Point and Rectangle instances. Now I use only plain float variables
  • Now I drawImage only the dirty region from the buffer to the screen (I use the "drawImage" with 11 args)
  • Now I use AWT (a Canvas)

with such modifications I've obtained 10% cpu with 300 arbitrary shapes (very complex freehanded shapes) and (surprise) the gc is sleeping for all the time.
I think that the use of Rectangle and Point was my real problem in the transformation methods (rotate, translate,...)

BUT, I'm not convinced that this is the BEST performance I can obtain... so if you want to give me some help, I'll post the code.

Thanks a lot !

------------------------------------------------------------
Beware of bugs in the above code;
I have only proved it correct, not tried it!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #3 - Posted 2003-09-29 13:58:44 »

-incgcc would have spread out the GC work so you didn't get that huge stop-the-world pause.  It looks like that isn't happening now so just keep it in mind if GC pauses return.

Quote
I've noticed that calling repaint is not as accurate as I need... sometimes the shape remains 2-3 pixels far from cursor when user stops dragging

This is something I have never seen.  My first thought would be that there was a bug in your redraw code.
By using repaint() you might avoid a few paints because multiple repaint requests could be collapsed into a single one.  This is specially true while the user is dragging the mouse and generating a lot of repaints.

Does the sleep cause the mouse motion to be less smooth or lagged?

You could do something else to put a cap on how often repaint is called so that drawing doesn't hog the CPU from your other operations.  Use a timer maybe to trigger repaints, stop the timer if there hasn't been any changes to the shapes since the last repaint.

Have you profiled the code?
-Xprof

Can you upgrade to 1.4.2?

Getting rid of many temporary objects like Point and Rectangle is good in general, in terms of GC.  You might also choose to reuse objects of this type, particularly with APIs that give you the option of supplying a Point to be filled in as opposed to needing to create a new one to return the data.

With buffer being Volatile you should be careful about the rendering hints you use..  anti-aliasing might cause reads from the video memory which are very slow, it could be better to not try accelerating this image, depending on how it is used.

Offline virgus

Junior Newbie





« Reply #4 - Posted 2003-09-29 15:12:14 »

I'll see if the "repaint" problem is a bug in my code... if so I'll switch to repaint so that, as you told, multiple paints can collapse.

Well, 1.4.2 gives me 2 problems:

  • a bug in an image loading for filechooser (this bug prevents the application to start-up as I load everything on startup): I think it's some corruption of rt.jar (I've downloaded it 3 times, so now I'll wait 1.5.... Sad )
  • some strange bug in Socket streams: with the same code I have Exceptions if I use 1.4.2 and all goes right if I use 1.4.1_03... code is really tested and I'm quite sure is a jre bug (application terminates with an exception outside the jvm)


About the Point/Rectangle question... I think that accessing a plain variable is way faster than calling a method or accessing a public member. If you think how many times you have to do it in a 30 fps animation...
I know this difference is not the real reason of a performing application BUT if I can do it better I do that way.

In your opinion, can I take some advantage if I use Volatile only with non transparent/non antialiased shapes as a sort of "triple buffer"?

Last point...
I want to reimplement GeneralPath so that I can expose the vector of coordinates (I want to manipulate it one by one, as in every vector draw application!), but I cannot/I don't want to reimplements 2 classes it uses: Crossings and Curves: these classes do the REAL work in methods like "intersects"... do you know a library (java2d compatible) that I can use ?

**Real last point**:
I've read many posts about BufferStrategy and it's use in games, where the scene update occour in a loop and is not event-driven. Do you think such thing can help me ?

2^180 Thanks !

------------------------------------------------------------
Beware of bugs in the above code;
I have only proved it correct, not tried it!
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #5 - Posted 2003-09-29 15:51:41 »

I honestly don't know the answers to most of your other questions, but I was going to mention the idea of BufferStrategy and a game-loop style interface.  The reason being that you can more easily control your frame rate and therefore make sure that you are giving enough time to the A/V Streaming.  In fact the video that you are streaming might fit well with that style.

Volatile image might be a benefit if you don't have the antialiasing.. I would try to get some real measurements.

As for the GeneralPath - Would you be able to use a substitute even if you could make one?  The insides of Shape aren't going to construct one of your path objects for you.  It's also a final class so you can't even make a subclass to peek at protected data or override some methods to intercept data.

your really need access to these members.  If you made a class in the same package you could read them directly... but making stuff in the java.* package is a security problem.

1  
2  
3  
4  
    byte[] pointTypes;
    float[] pointCoords;
    int numTypes;
    int numCoords;


there might be a reflection trick to use to access those fields.

Probably best though to maintain the control points in your own data structure.

Offline virgus

Junior Newbie





« Reply #6 - Posted 2003-09-29 16:15:32 »

You're right BUT GeneralPath is nothing more than an implementation of Shape.... so if I have these functionalities of Crossings and Curves, I can can implement Shape by myself Smiley)))

Well, I'll do some testing about "repaint" and I'll post the results.

thanks.

------------------------------------------------------------
Beware of bugs in the above code;
I have only proved it correct, not tried it!
Offline swpalmer

JGO Coder




Where's the Kaboom?


« Reply #7 - Posted 2003-09-29 23:52:10 »

Ah, implement the Shape interface yourself.  More work, but it could pay off.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Dwinin (28 views)
2014-09-12 09:08:26

Norakomi (57 views)
2014-09-10 13:57:51

TehJavaDev (73 views)
2014-09-10 06:39:09

Tekkerue (37 views)
2014-09-09 02:24:56

mitcheeb (57 views)
2014-09-08 06:06:29

BurntPizza (44 views)
2014-09-07 01:13:42

Longarmx (27 views)
2014-09-07 01:12:14

Longarmx (34 views)
2014-09-07 01:11:22

Longarmx (34 views)
2014-09-07 01:10:19

mitcheeb (40 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!