🔒 Locked
[java] Special effects in Java
Advertisement
Original Post
it's actually a problem traversing the image when the ray-tracing comes into effect. In DirectX i had to use a locked texture, meaning i was traversing bits, not pixels. i have no idea how to finish off the applet. I'll show you what i have at the end of this message. Basically i can get the picture to stay stable (not go haywire), but when i mouseover it doesn't start the water effect (like it should).
-Akujin
[edited by - akujin13 on January 16, 2003 9:49:07 PM]
-Akujin
[edited by - akujin13 on January 16, 2003 9:49:07 PM]
What is the switchPix method supposed to do? It doesn't compile because you're trying to assign an int to an int[], and I can't guess what it is you're trying to accomplish.
Edit: I'm assuming that switchPix is to transfer the contents of wNewSrc to wSrc. It compiles now, and I get a gradient of blue across the applet. Nothing seems to be happening. Which method seems to be giving problems?
[edited by - NuffSaid on January 15, 2003 10:56:08 AM]
Edit: I'm assuming that switchPix is to transfer the contents of wNewSrc to wSrc. It compiles now, and I get a gradient of blue across the applet. Nothing seems to be happening. Which method seems to be giving problems?
[edited by - NuffSaid on January 15, 2003 10:56:08 AM]
yeah, switchPix takes the modified souce (wNewSrc) and switches it with the buffer the MemoryImageSource uses (wSrc).
by the way, i wasn''t trying to assine the int to an int[], the forum though i was trying to set the text to italic (how stupid to use brackets as tags in a programming forum).
it seems the probem has to be either with the bottom half of process(), or with createDrop(). I can''t figure out which though.
-Akujin
by the way, i wasn''t trying to assine the int to an int[], the forum though i was trying to set the text to italic (how stupid to use brackets as tags in a programming forum).
it seems the probem has to be either with the bottom half of process(), or with createDrop(). I can''t figure out which though.
-Akujin
quote:
Original post by Akujin13
by the way, i wasn''t trying to assine the int to an int[], the forum though i was trying to set the text to italic (how stupid to use brackets as tags in a programming forum).
Hrm... almost as stupid as not using the several available methods to format your code and prevent this non-issue from becoming a problem and then complaining :D
yeah, i realise it''s faster, but it''s also unstable in the older versions of the JVM, along with horribly slow in the new 1.4.1_01 JRE (of corse, everything runs slow on that version, it''s horrible for realtime effects).
I''m trying to make the effect work for everyone, regardless of Java version.
The problem isn''t with that anyways, it''s with either createDrop() or somewhere in process(). i have a feeling it is in the bottom half of process(), where the displacement table is accessed, however i can''t seem to find the exact problem.
-Akujin
I''m trying to make the effect work for everyone, regardless of Java version.
The problem isn''t with that anyways, it''s with either createDrop() or somewhere in process(). i have a feeling it is in the bottom half of process(), where the displacement table is accessed, however i can''t seem to find the exact problem.
-Akujin
all right then, here is the complete code, with no subtractions:
THERE.
-Akujin
import java.awt.*;
import java.awt.image.*;
import java.awt.Event;
public class water extends java.applet.Applet
implements Runnable {
int XSIZE;
int YSIZE;
int SIZE;
int[] wHeight;
int[] wSrc;
int[] wNewSrc;
int[] wDisplace;
Image wOriginalImage;
Image wImage;
Thread motor;
MemoryImageSource wImgSrc;
public void init() {
YSIZE = getSize().height;
XSIZE = getSize().width;
SIZE = XSIZE * YSIZE;
wSrc = new int[SIZE];
wNewSrc = new int[SIZE];
MakeDisplacementTable(1024, 1.33f, 0.5f);
image_init();
}
void image_init() {
int curr = 0;
int curr1 = 0;
for (int y = 0; y < YSIZE; y++) {
curr1 = 0;
for (int x = 0; x < XSIZE; x++) {
wNewSrc[curr++] = 0xff000000 | 0 << 16 | 0 << 8 | curr1++;
if (curr1 == 255) curr1 = 0;
}
}
switchPix();
wImgSrc = new MemoryImageSource(XSIZE, YSIZE, wSrc, 0, XSIZE);
wImgSrc.setAnimated(true);
wImage = createImage(wImgSrc);
}
void MakeDisplacementTable(int ArraySize, float RefractionIndex, float Depth) {
wDisplace = new int[ArraySize];
for (int i=-ArraySize/2; i < (ArraySize/2) - 1; i++) {
float heightdiff = i * Depth;
float angel = (float)Math.atan(heightdiff);
float beamangel = (float)Math.asin(Math.sin(angel) / RefractionIndex);
wDisplace[i+(ArraySize/2)] = (int)(Math.tan(beamangel) * heightdiff);
}
}
void process() {
for (int y = 0; y < YSIZE; y++) {
for (int x = 0; x < XSIZE; x++) {
int value;
int xm1 = x-1; if (xm1 < 0) xm1 = 0;
int xm2 = x-2; if (xm2 < 0) xm2 = 0;
int ym1 = y-1; if (ym1 < 0) ym1 = 0;
int ym2 = y-2; if (ym2 < 0) ym2 = 0;
int xp1 = x+1; if (xp1 >= XSIZE) xp1 = XSIZE-1;
int xp2 = x+2; if (xp2 >= XSIZE) xp2 = XSIZE-1;
int yp1 = y+1; if (yp1 >= YSIZE) yp1 = YSIZE-1;
int yp2 = y+2; if (yp2 >= YSIZE) yp2 = YSIZE-1;
value = wSrc[((y) * XSIZE)+xm1];
value += wSrc[((y) * XSIZE)+xp1];
value += wSrc[((ym1) * XSIZE)+x];
value += wSrc[((yp1) * XSIZE)+x];
value /= 2;
value -= wNewSrc[(y*XSIZE)+x];
value = (int)((float)value / 1.05f);
wNewSrc[(y*XSIZE)+x] = value;
}
}
}
void text_draw() {
int dest_index = 0;
for (int y=0; y < YSIZE; y++) {
for (int x = 0; x < XSIZE; x++) {
int xdiff = (x == XSIZE-1) ? 0 : wNewSrc[(y*XSIZE)+x+1] - wNewSrc[(y*XSIZE)+x];
int ydiff = (y == YSIZE-1) ? 0 : wNewSrc[((y+1)*XSIZE)+x] - wNewSrc[(y*XSIZE)+x];
int xdisplace = wDisplace[(xdiff+256) % 512];
int ydisplace = wDisplace[(ydiff+256) % 512];
if (xdiff < 0) {
if (ydiff < 0) {
if (y-ydisplace < 0 || y-ydisplace >= SIZE || x-xdisplace < 0 || x-xdisplace >= SIZE)
wNewSrc[dest_index++] = wSrc[0];
else
wNewSrc[dest_index++] = wSrc[((y-ydisplace)*XSIZE)+x-xdisplace];
}
else {
if (y+ydisplace < 0 || y+ydisplace >= SIZE || x-xdisplace < 0 || x-xdisplace >= SIZE)
wNewSrc[dest_index++] = wSrc[0];
else
wNewSrc[dest_index++] = wSrc[((y+ydisplace)*XSIZE)+x-xdisplace];
}
}
else {
if (ydiff < 0) {
if (y-ydisplace < 0 || y-ydisplace >= SIZE || x+xdisplace < 0 || x+xdisplace >= SIZE)
wNewSrc[dest_index++] = wSrc[0];
else
wNewSrc[dest_index++] = wSrc[((y-ydisplace)*XSIZE)+x+xdisplace];
}
else {
if (y+ydisplace < 0 || y+ydisplace >= SIZE || x+xdisplace < 0 || x+xdisplace >= SIZE)
wNewSrc[dest_index++] = wSrc[0];
else
wNewSrc[dest_index++] = wSrc[((y+ydisplace)*XSIZE)+x+xdisplace];
}
}
}
dest_index += XSIZE;
}
}
void CreateDrop(int X, int Y, int Size, int SplashStrength) {
for (int x = X-Size; x <= X+Size; x++) {
for (int y = Y-Size; y <= Y+Size; y++) {
if (x < 0 || x >= XSIZE || y < 0 || y >= YSIZE) { break; }
int s_x = (x-X)*(x-X);
int s_y = (y-Y)*(y-Y);
int s_size = Size * Size;
if (s_x+s_y <= s_size) {
wNewSrc[(y*XSIZE)+x] += (int)((float)SplashStrength*Math.sqrt(s_x+s_y));
}
System.err.println("DROP");
}
}
}
void switchPix() {
for (int i = 0; i < wNewSrc.length; i++) {
wSrc[i] = wNewSrc[i];
}
}
public void start() {
motor = new Thread(this);
motor.setPriority(1);
motor.start();
}
public void stop() {
System.err.println("Thread has stopped");
motor = null;
}
public void run() {
System.gc();
do {
process();
text_draw();
try {
Thread.sleep(15L);
} catch (Exception e) { }
switchPix();
wImgSrc.newPixels();
repaint();
} while (motor != null);
}
public boolean mouseMove(Event evt, int x, int y) {
CreateDrop(x, y, 25, 25);
return true;
}
public void update(Graphics g) {
paint(g);
}
public void paint(Graphics g) {
g.drawImage(wImage, 0, 0, null);
}
}
THERE.
-Akujin
Hey, I''ve just run a benchmark that does some copying, and Array copy IS slower, probably because it is a Native method and thus calling it repeatedly many times in a loop is detrimental.
Still haven''t figured out what''s wrong with your code. What does hte original code for those 2 functions look like?
Still haven''t figured out what''s wrong with your code. What does hte original code for those 2 functions look like?
the directx code for those functions looks like this:
i think i did a good enough job of porting it, but obviously not.
-Akujin
void CreateWaterDroplet(int iX, int iY, int iSize, int iSplashStrength,
int *waterbuf, int iWaterWidth, int iWaterHeight)
{
for (int x=iX-iSize; x <= iX+iSize; x++) {
for (int y=iY-iSize; y <= iY+iSize; y++) {
// make sure we''re in bounds
if (x < 0 || x >= iWaterWidth || y < 0 || y >= iWaterHeight) continue;
// see if the point at (x,y) is within the circle of radius size
int square_x = (x-iX)*(x-iX);
int square_y = (y-iY)*(y-iY);
int square_size = iSize*iSize;
if (square_x+square_y <= square_size) {
// it''s within the size circle! apply it to the water buffer.
waterbuf[(y*iWaterWidth)+x] += (int)((float)iSplashStrength)*sqrt(square_x+square_y);
}
}
}
}
HRESULT PutWaterOntoTexture(int *waterbuf, int iWaterWidth, int iWaterHeight,
char *lutDisplacement,
LPDIRECT3DDEVICE8 pd3dDevice,
LPDIRECT3DTEXTURE8 pSrcTex,
LPDIRECT3DTEXTURE8 pDestTex)
{
HRESULT hr;
// lock texture
D3DLOCKED_RECT rect_src, rect_dest;
::ZeroMemory(▭_src, sizeof(rect_src));
::ZeroMemory(▭_dest, sizeof(rect_dest));
if (FAILED(hr = pSrcTex->LockRect(0, ▭_src, NULL, 0))) return(hr);
if (FAILED(hr = pDestTex->LockRect(0, ▭_dest, NULL, 0))) return(hr);
// our texture surface is now locked, and we can use the pitch to traverse it.
DWORD *pSrc = (DWORD *)(rect_src.pBits);
DWORD *pDest= (DWORD *)(rect_dest.pBits);
int dest_index=0;
int src_pitch = rect_src.Pitch/4; // in DWORDS
// this could be optimized a LOT. It''s this way so you can learn the technique.
for (int y=0; y < iWaterHeight; y++) {
for (int x=0; x < iWaterWidth; x++) {
int xdiff = (x == iWaterWidth-1) ? 0 : waterbuf[(y*iWaterWidth)+x+1] - waterbuf[(y*iWaterWidth)+x];
int ydiff = (y == iWaterHeight-1) ? 0 : waterbuf[((y+1)*iWaterWidth)+x] - waterbuf[(y*iWaterWidth)+x];
int xdisp = lutDisplacement[(xdiff+256) % 512];
int ydisp = lutDisplacement[(ydiff+256) % 512];
if (xdiff < 0) {
if (ydiff < 0) {
if (y-ydisp < 0 || y-ydisp >= TEXTURESIZE || x-xdisp < 0 || x-xdisp >= TEXTURESIZE)
pDest[dest_index++] = pSrc[0];
else
pDest[dest_index++] = pSrc[((y-ydisp)*src_pitch)+x-xdisp];
}
else {
if (y+ydisp < 0 || y+ydisp >= TEXTURESIZE || x-xdisp < 0 || x-xdisp >= TEXTURESIZE)
pDest[dest_index++] = pSrc[0];
else
pDest[dest_index++] = pSrc[((y+ydisp)*src_pitch)+x-xdisp];
}
}
else {
if (ydiff < 0) {
if (y-ydisp < 0 || y-ydisp >= TEXTURESIZE || x+xdisp < 0 || x+xdisp >= TEXTURESIZE)
pDest[dest_index++] = pSrc[0];
else
pDest[dest_index++] = pSrc[((y-ydisp)*src_pitch)+x+xdisp];
}
else {
if (y+ydisp < 0 || y+ydisp >= TEXTURESIZE || x+xdisp < 0 || x+xdisp >= TEXTURESIZE)
pDest[dest_index++] = pSrc[0];
else
pDest[dest_index++] = pSrc[((y+ydisp)*src_pitch)+x+xdisp];
}
}
}
// next line
dest_index += (rect_dest.Pitch - (TEXTURESIZE*4))/4;
}
// unlock texture surface
if (FAILED(hr = pSrcTex->UnlockRect(0))) return(hr);
if (FAILED(hr = pDestTex->UnlockRect(0))) return(hr);
return S_OK;
i think i did a good enough job of porting it, but obviously not.
-Akujin
First, don''t use deprecated methods. mouseMove is deprecated, use MouseMotionListener instead.
Second, when I run the program, I get the following exception:
This is line 117:
int ydisplace = wDisplace[(ydiff+256) % 512];
As soon as you get an exception, your program will grind to a halt, even though it looks like it is still running. To prove it stopped, I set up this:
It prints thread 1 and thread 2, but stops there, because the error is in text_draw().
Also, make sure you always check your console output when you are having problems. That is the only place where exceptions are printed.
First make it work,
then make it fast.
--Brian Kernighan
"I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book
Second, when I run the program, I get the following exception:
java.lang.ArrayIndexOutOfBoundsException: -306
at water.text_draw(water.java:117)
at water.run(water.java:203)
at java.lang.Thread.run(Thread.java:536)
This is line 117:
int ydisplace = wDisplace[(ydiff+256) % 512];
As soon as you get an exception, your program will grind to a halt, even though it looks like it is still running. To prove it stopped, I set up this:
public void run() {
System.gc();
do {
System.out.println("thread 1");
process();
System.out.println("thread 2");
text_draw();
System.out.println("thread 3");
try {
Thread.sleep(15L);
} catch (Exception e) { }
switchPix();
System.out.println("thread 4");
wImgSrc.newPixels();
System.out.println("thread 5");
repaint();
System.out.println("thread 6");
} while (running);
}
It prints thread 1 and thread 2, but stops there, because the error is in text_draw().
Also, make sure you always check your console output when you are having problems. That is the only place where exceptions are printed.
First make it work,
then make it fast.
--Brian Kernighan
"I’m happy to share what I can, because I’m in it for the love of programming. The Ferraris are just gravy, honest!" --John Carmack: Forward to Graphics Programming Black Book
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement