예제 #1
0
        // 0 < distance <= infinity
        // 0 <= split < 1
        // split = 2f means no collision
        internal void GetCollisionData(WallData *wall, out float cur_dist, out float cur_split)
        {
            // Medium performance impact.
            float
                drx = wall->geom_direction.x,
                dry = wall->geom_direction.y;

            float det = direction.x * dry - direction.y * drx; // Caching can only be used here

            if (det == 0)                                      // Parallel
            {
                cur_dist  = float.PositiveInfinity;
                cur_split = 2f;
                return;
            }

            float spldet = direction.x * (start.y - wall->geom_start.y) - direction.y * (start.x - wall->geom_start.x);
            float dstdet = wall->geom_direction.x * (start.y - wall->geom_start.y) - wall->geom_direction.y * (start.x - wall->geom_start.x);
            float spltmp = spldet / det;
            float dsttmp = dstdet / det;

            if (spltmp < 0 || spltmp >= 1 || dsttmp <= 0) // dsttmp = 0 means column height = x/0.
            {
                cur_dist  = float.PositiveInfinity;
                cur_split = 2f;
                return;
            }
            cur_split = spltmp;
            cur_dist  = dsttmp;
        }
예제 #2
0
        internal Texture texture; // Yes, by value.

        internal static WallData *Create(Vector start, Vector end, Texture texture)
        {
            WallData *result = (WallData *)Marshal.AllocHGlobal(sizeof(WallData));

            result->texture        = texture;
            result->geom_direction = end - start;
            result->geom_start     = start;
            return(result);
        }
예제 #3
0
        internal static WallData *Create(Vector start, float angle, float length, Texture texture)
        {
            WallData *result = (WallData *)Marshal.AllocHGlobal(sizeof(WallData));
            Vector    dir    = new Vector(angle) * length;

            result->texture        = texture;
            result->geom_direction = dir;
            result->geom_start     = start;
            return(result);
        }
예제 #4
0
        private WallData *NearestWallTest(SceneData *map, out float nearest_dist, out float nearest_hratio)
        {
            nearest_dist   = float.PositiveInfinity;
            nearest_hratio = 2f;
            WallData * nearest = null;
            WallData **pptr    = map->walls;

            while (*pptr != null)
            {
                //Medium performance impact.
                GetCollisionData(*pptr, out float cur_dist, out float cur_split);
                if (cur_dist < nearest_dist)
                {
                    nearest_hratio = cur_split;
                    nearest_dist   = cur_dist;
                    nearest        = *pptr;
                }
                pptr++;
            }
            return(nearest);
        }
예제 #5
0
        internal WallData *NearestWall(SceneData *map, out float nearest_dist, out float nearest_ratio)
        {
            nearest_dist  = float.PositiveInfinity;
            nearest_ratio = 2f;
            int        wallcount = map->wall_count;
            WallData **cur       = map->walls;
            WallData * nearest   = null;

            for (int i = 0; i < wallcount; i++)
            {
                //walls cannot be null.
                GetCollisionData(*cur, out float cur_dist, out float cur_ratio);
                if (cur_dist < nearest_dist)
                {
                    nearest_ratio = cur_ratio;
                    nearest_dist  = cur_dist;
                    nearest       = *cur;
                }
                cur++;
            }
            return(nearest);
        }
예제 #6
0
        private unsafe static void CLRRender(PixelBuffer target, SceneData *scene)        // Must be changed
        {
            //Caching frequently used values.
            uint *  buffer     = target.uint0;
            int     width      = target.width;
            int     height     = target.height;
            Texture background = scene->background;

            if (ParallelRendering)
            {
                Parallel.For(0, width, Loop);
            }
            else
            {
                for (int i = 0; i < width; i++)
                {
                    Loop(i);
                }
            }

            void Loop(int ray_id)
            //for (int ray_id = 0; ray_id < rendererData->bitmap_width; ray_id++)
            {
                //Caching
                float ray_cos   = cache->cosines[ray_id];
                float ray_angle = cache->angles[ray_id] + scene->activeObserver->rotation;
                Ray   ray       = new Ray(scene->activeObserver->position, ray_angle);

                //Cast the ray towards every wall.
                WallData *nearest = ray.NearestWall(scene, out float nearest_dist, out float nearest_ratio);

                if (nearest_ratio != 2f)
                {
                    float columnHeight = (cache->colHeight1 / (ray_cos * nearest_dist)); //Wall column size in pixels

                    float column_start      = (height - columnHeight) / 2f;
                    float column_end        = (height + columnHeight) / 2f;
                    int   draw_column_start = (int)column_start;
                    int   draw_column_end   = (int)column_end;
                    if (draw_column_start < 0)
                    {
                        draw_column_start = 0;
                    }
                    if (draw_column_end > height)
                    {
                        draw_column_end = height;
                    }

                    for (int line = 0; line < draw_column_start; line++)
                    {
                        //PURPOSELY REPEATED CODE!
                        float background_hratio = ray_angle / 360 + 1; //Temporary bugfix to avoid hratio being < 0
                        float screenVratio      = (float)line / height;
                        float background_vratio = (1 - ray_cos) / 2 + ray_cos * screenVratio;
                        uint  color             = background.MapPixel(background_hratio, background_vratio);
                        buffer[width * line + ray_id] = color;
                    }
                    for (int line = draw_column_start; line < draw_column_end; line++)
                    {
                        float vratio = (line - column_start) / columnHeight;
                        uint  pixel  = nearest->texture.MapPixel(nearest_ratio, vratio);
                        buffer[width * line + ray_id] = pixel;
                    }
                    for (int line = draw_column_end; line < height; line++)
                    {
                        //PURPOSELY REPEATED CODE!
                        float background_hratio = ray_angle / 360 + 1; //Temporary bugfix to avoid hratio being < 0
                        float screenVratio      = (float)line / height;
                        float background_vratio = (1 - ray_cos) / 2 + ray_cos * screenVratio;
                        uint  color             = background.MapPixel(background_hratio, background_vratio);
                        buffer[width * line + ray_id] = color;
                    }
                }
                else
                {
                    for (int line = 0; line < height; line++)
                    {
                        //Critical performance impact.
                        //PURPOSELY REPEATED CODE!
                        float background_hratio = ray_angle / 360 + 1;
                        float screenVratio      = (float)line / height;
                        float background_vratio = (1 - ray_cos) / 2 + ray_cos * screenVratio;
                        uint  color             = background.MapPixel(background_hratio, background_vratio);
                        buffer[width * line + ray_id] = color;
                    }
                }
            }
        }
예제 #7
0
 internal void Add(WallData *wall)
 {
     walls[wall_count++] = wall;
     walls[wall_count]   = null;
 }
예제 #8
0
 internal static void Delete(WallData *item)
 {
     Marshal.FreeHGlobal((IntPtr)item);
 }