Register to reply

Graphics acceleration in java

by matiasmorant
Tags: acceleration, graphics, java
Share this thread:
matiasmorant
#1
Jan4-12, 09:14 PM
P: 39
I have made a java code which displays a blue sphere and lets you control with the mouse where its illumination comes from. (its actually a circle and some parts are painted white/blue/black depending on the mouse position to make it look 3D)

here is the code


import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;

public class esfera extends JFrame{

double azimuth=3*Math.PI/4, inclination=Math.PI/4; //angle coordinates for the 'light source'

private BufferedImage image = new BufferedImage(800,800,BufferedImage.TYPE_INT_RGB); //the image storing the sphere drawing

public esfera(){ //initializer adding a listener to mouse motion
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
azimuth=((800-e.getX())/800.00)*Math.PI;
inclination=(e.getY()/800.00)*Math.PI;
repaint();
}
});}

public void paint(Graphics g){ //does the whole painting

g.drawImage(image,0,0,null); //paint the current image to the frame

for(int i=0;i<800;i++){ //make next image, pixel by pixel
for(int j=0;j<800;j++){
image.setRGB(i,j,color((i-400)/200.00,(400-j)/200.00));
}
}
}

public int color(double x, double y){ //this is what color each pixel should be painted in order to make the picture look like a sphere
double clr;
double z = Math.sqrt(1-(x*x+y*y));
double angle = Math.acos(Math.cos(inclination)*y+Math.sin(inclination)*(Math.sin(azimu th)*z+Math.cos(azimuth)*x));

if(x*x+y*y>1) clr=0;
else if (angle>Math.PI/2) clr=0;
else if (angle>Math.PI/4)clr=255*(2-angle/(Math.PI/4));
else{ int white =((int)(255*(1-angle/(Math.PI/4)))<<8)+((int)(255*(1-angle/(Math.PI/4)))<<16);
clr=white+255;}

return (int)clr;

}

public static void main(String[] args){ //the main method of course

esfera frame = new esfera();
frame.setSize(800,800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

}

it works ok. the only problem is that when you move the mouse it takes too long to update the screen with the next picture.(so the 'light source' seems to be jumping from one place to another if you move the mouse too fast)


the question is: how can I fix this problem?


i have been reading about VolatileImage but it seems that you can't write a VolatileImage pixel by pixel, so it's not what i need.

i have also read about BufferStrategy, but i'm not sure if it could help me or not, (didn't completely understand how to use it neither)


could you help me please??? i've been trying to solve it all day...
Phys.Org News Partner Science news on Phys.org
Security CTO to detail Android Fake ID flaw at Black Hat
Huge waves measured for first time in Arctic Ocean
Mysterious molecules in space
Mark44
#2
Jan4-12, 10:46 PM
Mentor
P: 21,215
Java is probably not the best choice for drawing figures on the screen that need to be frequently updated. The reason for this is that your code gets compiled into Java byte codes that are then translated into machine instructions at run time. For graphics programming, compiled languages rather than interpreted languages (like Java) are usually preferred.

The way programmers did things in the "old days" was to work with several screen buffers that they would swap into and out of screen memory. While one buffer was being updated, another screen buffer that was ready to be viewed was swapped into memory. I don't know if you could do this in Java.
AlephZero
#3
Jan5-12, 10:45 AM
Engineering
Sci Advisor
HW Helper
Thanks
P: 6,957
Java has a "double buffering" option that lets you create the next image completely before you display it. That will get rid of any "flickering" as you move the images but it won't make the app run faster. http://docs.oracle.com/javase/tutori...doublebuf.html

You could do some optimisation on color() and the way you call image.setRGB().

A simple speed-up for color() would be to do the test
if(x*x+y*y>1) clr=0;
first, before you calculate the expensive square roots and trig functions.
Also asimuth and incliation don't change, so you don't need to recalculate the same sines and cosines 640,000 times for each pixel of the image

If that isn't enough, you could limit the number of calls to color().

Apparently everything outside of the sphere is black, so you could set the complete image to black with one call, not pixel by pixel. Then you could limit the for loops to cover the image. Something like
Find imin and imax that cover the image
for i  = imin to imax {
    find jmin and jmax that cover line i of the image
    for j = jmin to jmax {
       color(.....)
    }
}

matiasmorant
#4
Jan5-12, 03:29 PM
P: 39
Graphics acceleration in java

it originally took 500-600-ms to update the image
doing the if(x*x+y*y>1) clr=0; test first, it only took 300-250ms
avoiding the recalculation of asimuth and incliation, 200-225 ms

the image is initializated to black by default, so recalculating pixel by pixel only the smallest square fitting the sphere, it takes 125 ms to update

:O thanks a lot!!
AlephZero
#5
Jan5-12, 04:57 PM
Engineering
Sci Advisor
HW Helper
Thanks
P: 6,957
Quote Quote by matiasmorant View Post
it originally took 500-600-ms to update the image
doing the if(x*x+y*y>1) clr=0; test first, it only took 300-250ms
avoiding the recalculation of asimuth and incliation, 200-225 ms

the image is initializated to black by default, so recalculating pixel by pixel only the smallest square fitting the sphere, it takes 125 ms to update

:O thanks a lot!!
Take-home message: good programming is about attention to detail.

I bet you can make it run quite a bit faster than 8 frames per seond, if you do some more thinking. Hint: there seems to be lot of converting real values to integers and back again...
jedishrfu
#6
Jan5-12, 05:24 PM
P: 2,805
also don't underestimate java as far as speed goes as its JVM and hotspot compiling have really sped things up considerably though it will never match a finally crafted C or asm program.

we use Java a lot for our realtime charting and displays and it works just fine. Ray tracing is very cpu/graphics intense and thats why gamers like to have high performance graphics card with their own built-in graphics cpu and games that support it.
Edgardo
#7
Jan6-12, 02:59 PM
P: 685
Quote Quote by matiasmorant View Post
it originally took 500-600-ms to update the image
doing the if(x*x+y*y>1) clr=0; test first, it only took 300-250ms
avoiding the recalculation of asimuth and incliation, 200-225 ms

the image is initializated to black by default, so recalculating pixel by pixel only the smallest square fitting the sphere, it takes 125 ms to update

:O thanks a lot!!
Can you post your new code?
matiasmorant
#8
Jan10-12, 01:53 PM
P: 39
here's the new code :)

import javax.swing.*;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;

public class esfera extends JFrame{

double azimuth=3*Math.PI/4, inclination=Math.PI/4; //angle coordinates for the 'light source'
double cosAzimuth=Math.cos(azimuth) ,sinAzimuth=Math.sin(azimuth), cosInclination=Math.cos(inclination),sinInclination=Math.sin(inclinatio n);

private BufferedImage image = new BufferedImage(800,800,BufferedImage.TYPE_INT_RGB); //the image storing the sphere drawing

public esfera(){ //initializer adding a listener to mouse motion
addMouseMotionListener(new MouseMotionAdapter(){
public void mouseDragged(MouseEvent e){
azimuth=((800-e.getX())/800.00)*Math.PI;
inclination=(e.getY()/800.00)*Math.PI;
cosAzimuth=Math.cos(azimuth);
sinAzimuth=Math.sin(azimuth);
cosInclination=Math.cos(inclination);
sinInclination=Math.sin(inclination);
repaint();
}
});}

public void paint(Graphics g){ //does the whole painting

g.drawImage(image,0,0,null); //paint the current image to the frame

for(int i=200;i<600;i++){ //make next image, pixel by pixel
for(int j=200;j<600;j++){
image.setRGB(i,j,color((i-400)/200.00,(400-j)/200.00));
}
}
}

public int color(double x, double y){ //this is what color each pixel should be painted in order to make the picture look like a sphere
double clr;

if(x*x+y*y>1) clr=0;
else {
double z = Math.sqrt(1-(x*x+y*y));
double angle = Math.acos(cosInclination*y+sinInclination*(sinAzimuth*z+cosAzimuth*x));

if (angle>Math.PI/2) clr=0;
else if (angle>Math.PI/4)clr=255*(2-angle/(Math.PI/4));
else{ int white =((int)(255*(1-angle/(Math.PI/4)))<<8)+((int)(255*(1-angle/(Math.PI/4)))<<16);
clr=white+255;}

}

return (int)clr;

}

public static void main(String[] args){ //the main method of course

esfera frame = new esfera();
frame.setSize(800,800);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

}
chiro
#9
Jan11-12, 01:20 AM
P: 4,572
I'm surprised there isn't some standard library that has an OpenGL/DirectX type implementation to allow hardware-accelerated 2D and 3D rendering.

Also back in the old days instead of calculating trig functions directly, what we used to do is pre-calculate these into an array and use these values as "look-up" values. The arrays themselves were called "look-up tables". You might be interested in using these, especially in the kind of VM environment that Java is.


Register to reply

Related Discussions
Core Java & J2EE & Advance Java Programming & Computer Science 2
Java Graphics & 2D Help me animate this Engineering, Comp Sci, & Technology Homework 1
Using Graphics in a C++ Code. Programming & Computer Science 16
Graphics with Onboard Intel Extreme Graphics 2 on ASUS P5PE VM Computing & Technology 8
Way to create graphics in C++ Computing & Technology 7