简体   繁体   中英

Light/Ray casting in java?

I've been trying to make a dynamic light system in java, without using libraries. For some reason, though, it seems I can't get light to run efficiently. It flickers and lags a ton. I'm doing this with no previous understanding of lighting engines in games, so I'm open to suggestions. Here is my current update method:

public void updateLight( ArrayList<Block> blocks )
    {
        //reset light
        light.reset();
        //add the x and y of this light
        light.addPoint( x, y );

        //precision for loops
        int ires = 1;
        int jres = 2;

        for( int i = 0; i < width; i += ires )
        {
            //get radians of current angle
            float rdir = (float)Math.toRadians( dir + i - width/2 );

            //set up pixel vars
            int px, py;

            for( int j = 0; j < length; j += jres )
            {
                //get position of pixel
                px = (int)ZZmath.getVectorX( x, rdir, j );
                py = (int)ZZmath.getVectorY( y, rdir, j );

                //if point gets found
                boolean foundpoint = false;

                for( int n = 0; n < blocks.size(); n ++ )
                {
                    //check if block is solid
                    //also check that collision is possible really quickly for efficiency
                    if( blocks.get( n ).solid )
                    {
                        //get info on block
                        int bx = blocks.get( n ).x;
                        int by = blocks.get( n ).y;

                        //quick trim
                        if( Math.abs( bx - px ) <= 32 && Math.abs( by - py ) <= 32 )
                        {
                            int bw = blocks.get( n ).w;
                            int bh = blocks.get( n ).h;

                            if( ZZmath.pointInBounds( px, py, bx, by, bw, bh ) )
                            {
                                //add point to polygon
                                light.addPoint( px, py );
                                //found point
                                foundpoint = true;
                            }
                        }
                    }
                }

                //if a point is found, break
                if( foundpoint )
                {
                    break;
                }

                //if at end of loop, add point
                //loose definition of "end" to prevent flickers
                if( j >= length - jres*2 )
                {
                    light.addPoint( px, py );
                }
            }
        }
    }

This modifies a polygon that displays for light. I'll change that later. Any idea of ways I can make this run better? Also, no, no libraries. I don't have anything against them, just don't want to use one now.

You implementation doesn't appear to use much of the stuff I see here:

http://www.cs.utah.edu/~shirley/books/fcg2/rt.pdf

I'd recommend digesting this completely. If your objective is to understand ray tracing deeply, that's how it should be done.

Maybe your objective was to learn by writing your own raytracer. In my experience I would end up rewriting this code several times and still not get it completely right. It's good to get your hands dirty but it's not necessarily the most effective way to go about things.

Overall it looks like you need to study (object oriented) programming concepts, and take a data structures and algorithms course.

The biggest thing is readability. Document your code, for your future self if no one else. This means Clear comments before and during updateLight() . The existing comments are alright (though they paraphrase the code more than justify it), but "really quickly for efficiency" is a lie.

For a small issue of readability that could be a tiny drag on performance, make a local variable for blocks.get(n) . Name it something short but descriptive, save typing and only make one method call to retrieve it.

"if at end of loop": I have no idea which loop you mean, and the for loops have definite ends. A comment }//end for or }//end for width is often helpful.

Checking if the block is solid is unnecessary! Just store your blocks in two lists, and only go through the solid blocks. Even if you have some desire to have flickering blocks, one remove and add is cheaper than O(width*length*numbernotsolid) extra work.

There are many ways you could structure how the blocks are stored to facilitate quick testing. You only want or need to test blocks whose coordinates are near to a particular light. The basic strategy is divide the space into a grid, and sort the blocks based on what section of the grid they fall into. Then when you have light in a particular section of the grid, you know you only need to test blocks in that section (and possibly a neighboring section - there are details depending on their width and the light's).

I have no idea whether that is along the lines of the right approach or not. I don't know much about raytracing, although it is or used to be rather slow. It looks like you have a decent naive implementation. There might be a slightly different naive approach that is faster and some more difficult (to code to completion) algorithms that are moderately yet more fast.

Also, I see no need to do this breadth first. Why not solve for one line (you call them pixels?) at a time. Count the number of times this code calls Math.toRadians . It looks like it's just an extraneous line because you could work along the same angle until ready for the next.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM