Esempio n. 1
0
void RenderObject(RenderContext *ctx, Rect2Di r, Color c, u32 image_id, u32 spritemapId) {
    bool32 flush = 0;

    u32 id = spritemapId == ASSET_SPRITEMAP ? ctx->atlasId : ctx->fontAtlasId;
    if (ctx->selectedTexture != id) {
        // Draw whatever is in the buffer, and switch texture.
        Draw(ctx);
        SegmentClear(&ctx->vertexBuffer);
        ctx->entriesCount = 0;

        glBindTexture(GL_TEXTURE_2D, id);
        ctx->selectedTexture = id;
        flush = 1;
    }

    // If the buffer is full, push the data to the graphics card and render what we got.
    if (ctx->entriesCount >= ctx->entriesMax) {
        Draw(ctx);
        SegmentClear(&ctx->vertexBuffer);
        ctx->entriesCount = 0;
    }

    AtlasAsset *atlas = spritemapId == ASSET_SPRITEMAP ? ctx->atlas : ctx->fontAtlas;
    AtlasAssetEntry *entry = GetAtlasEntry(atlas, image_id);

    if (!entry) {
        return;
    }
    
    RenderVertex vertices[4];
    vertices[0] = { { (r32)r.x, (r32)r.y, 0.f }, c, { entry->uvOrigin.x, 1.0f - entry->uvOrigin.y } };
    vertices[1] = { { (r32)r.x, (r32)(r.y + r.height), 0.f }, c, { entry->uvOrigin.x, 1.0f - entry->uvEnd.y } };
    vertices[2] = { { (r32)(r.x + r.width), (r32)(r.y + r.height), 0.f }, c, { entry->uvEnd.x, 1.0f - entry->uvEnd.y } };
    vertices[3] = { { (r32)(r.x + r.width), (r32)r.y, 0.f }, c, { entry->uvEnd.x, 1.0f - entry->uvOrigin.y } };

    for (int i = 0; i < 4; ++i) {
        RenderVertex *c_vert = PUSH_STRUCT(&ctx->vertexBuffer, RenderVertex);
        *c_vert = vertices[i];
    }

    ctx->entriesCount++;
    ctx->currFrameObjects++;
}
Esempio n. 2
0
extern void game_update_and_render(Memory* memory, RenderState *renderer, float last_frame_time_seconds, const u8 *keys, SDL_Event e) {
    UNUSED(keys);
    UNUSED(e);
    ASSERT(sizeof(PermanentState) <= memory->permanent_size);
    PermanentState *permanent = (PermanentState *)memory->permanent;
    ASSERT(sizeof(ScratchState) <= memory->scratch_size);
    ScratchState *scratch = (ScratchState *)memory->scratch;
    ASSERT(sizeof(DebugState) <= memory->debug_size);
    DebugState *debug = (DebugState *)memory->debug;
    ASSERT(sizeof(Node16Arena) <= memory->node16_size);
    Node16Arena *node16 = (Node16Arena *)memory->node16;

    ASSERT(sizeof(Node16)  == sizeof(Node16*)*2 + 16);
    ASSERT(sizeof(FoundPathNode) == sizeof(BarNode));


    if (memory->is_initialized == false) {
        initialize_memory(permanent, node16, renderer, memory);
    }


    // dynamic blocks
    for (u32 i = 0; i < permanent->dynamic_block_count; i++) {
        if ( permanent->dynamic_blocks[i].total_frames > 1) {
            permanent->dynamic_blocks[i].frame_duration_left += last_frame_time_seconds;
            if (permanent->dynamic_blocks[i].frame_duration_left >= permanent->dynamic_blocks[i].duration_per_frame) {

                int frame_index = permanent->dynamic_blocks[i].current_frame;

                if (permanent->dynamic_blocks[i].plays_forward == 1) {
                    frame_index +=1;
                    if (frame_index > permanent->dynamic_blocks[i].last_frame)
                        frame_index = permanent->dynamic_blocks[i].first_frame;
                } else {
                    frame_index -= 1;
                    if (frame_index < permanent->dynamic_blocks[i].first_frame)
                        frame_index = permanent->dynamic_blocks[i].last_frame;
                }

                permanent->dynamic_blocks[i].current_frame        = frame_index;
                permanent->dynamic_blocks[i].frame_duration_left  = 0;

                SimpleFrame f = generated_frames[frame_index];
                permanent->dynamic_blocks[i].frame.x_pos          = f.frameX;
                permanent->dynamic_blocks[i].frame.y_pos          = f.frameY;
                permanent->dynamic_blocks[i].frame.width          = f.frameW;
                permanent->dynamic_blocks[i].frame.height         = f.frameH;
                permanent->dynamic_blocks[i].frame.y_internal_off = f.ssH - (f.sssY + f.frameH);
                permanent->dynamic_blocks[i].frame.x_internal_off = f.ssW - (f.sssX + f.frameW);
            }
        }
    }


        permanent->colored_line_count = 0;

#if 1
    {
        permanent->colored_line_count = 0;

        for (u32 i = 0; i < permanent->actor_count; i++) {

            if (permanent->paths[i].Sentinel->Next != permanent->paths[i].Sentinel) {
                float distance = Vector3Distance(permanent->steer_data[i].location, permanent->paths[i].Sentinel->Next->path.node);
                if (distance < 5.f){
                    Node16 *First = permanent->paths[i].Sentinel->Next;
                    permanent->paths[i].Sentinel->Next = First->Next;
                    First->Next = node16->Free->Next;
                    node16->Free->Next = First;
                    First->Prev = node16->Free;
                }
            }


            BEGIN_PERFORMANCE_COUNTER(actors_steering);
            {
                Vector3 seek_force  = seek_return(&permanent->steer_data[i], permanent->paths[i].Sentinel->Next->path.node);
                seek_force = Vector3MultiplyScalar(seek_force, 1);
                actor_apply_force(&permanent->steer_data[i], seek_force);

                permanent->steer_data[i].velocity = Vector3Add(permanent->steer_data[i].velocity, permanent->steer_data[i].acceleration);
                permanent->steer_data[i].velocity = Vector3Limit(permanent->steer_data[i].velocity, permanent->steer_data[i].max_speed);
                permanent->steer_data[i].location = Vector3Add(permanent->steer_data[i].location,   Vector3MultiplyScalar(permanent->steer_data[i].velocity, last_frame_time_seconds));
                permanent->steer_data[i].acceleration = Vector3MultiplyScalar(permanent->steer_data[i].acceleration, 0);

                // left = frame 0, down = frame 1 right = frame 2,up = frame 3
                double angle = (180.0 / PI) * atan2(permanent->steer_data[i].velocity.x, permanent->steer_data[i].velocity.y);
                angle = angle + 180;

                if (angle > 315 || angle < 45) {
                    permanent->anim_data[i].frame = 10; //11
                } else if (angle >= 45 && angle <= 135) {
                    permanent->anim_data[i].frame = 4;// 5
                } else if (angle >=135 && angle <= 225) {
                    permanent->anim_data[i].frame = 6; //7
                } else if (angle > 225 && angle <= 315) {
                    permanent->anim_data[i].frame = 8; //9
                }



                permanent->anim_data[i].frame_duration_left += last_frame_time_seconds;
                if (permanent->anim_data[i].frame_duration_left > 0.1f) {
                    permanent->anim_data[i].frame += 1;
                }
                if (permanent->anim_data[i].frame_duration_left > 0.2f) {
                    permanent->anim_data[i].frame_duration_left = 0;
                }

                END_PERFORMANCE_COUNTER(actors_steering);
            }


#if 1
            if (permanent->paths[i].Sentinel->Next != permanent->paths[i].Sentinel) {
                Node16 * d= permanent->paths[i].Sentinel->Next;
                u32 c = permanent->colored_line_count;
                while (d->Next != permanent->paths[i].Sentinel){

                    //if (d->path.node.z != d->Next->path.node.z) {
                    //    printf("going from %f,%f,[%f] to %f,%f,[%f]\n", d->path.node.x, d->path.node.y, d->path.node.z, d->Next->path.node.x, d->Next->path.node.y, d->Next->path.node.z);
                    //}
                    permanent->colored_lines[c].x1 = getRotatedXFloat(d->path.node.x, d->path.node.y, facing_side, permanent->dims);
                    permanent->colored_lines[c].y1 = getRotatedYFloat(d->path.node.x, d->path.node.y, facing_side, permanent->dims);
                    permanent->colored_lines[c].z1 = d->path.node.z;

                    permanent->colored_lines[c].x2 = getRotatedXFloat(d->Next->path.node.x, d->Next->path.node.y, facing_side, permanent->dims);
                    permanent->colored_lines[c].y2 = getRotatedYFloat(d->Next->path.node.x, d->Next->path.node.y, facing_side, permanent->dims);
                    permanent->colored_lines[c].z2 = d->Next->path.node.z;

                    permanent->colored_lines[c].r = 0.0f;
                    permanent->colored_lines[c].g = 0.0f;
                    permanent->colored_lines[c].b = 0.0f;
                    d = d->Next;
                    c++;
                }
                permanent->colored_line_count = c;
            }
#endif
            ASSERT( permanent->colored_line_count < LINE_BATCH_COUNT * MAX_IN_BUFFER)

            if (permanent->paths[i].Sentinel->Next != permanent->paths[i].Sentinel) {
                continue;
            }



            BEGIN_PERFORMANCE_COUNTER(mass_pathfinding);
            TempMemory temp_mem = begin_temporary_memory(&scratch->arena);
            grid_node * Start = get_node_at(permanent->grid,
                                          permanent->steer_data[i].location.x/permanent->block_size.x,
                                          permanent->steer_data[i].location.y/permanent->block_size.y,
                                          (permanent->steer_data[i].location.z + 10)/permanent->block_size.z_level);
            if (Start->walkable) {
            } else {
                Start = get_neighboring_walkable_node(permanent->grid, Start->X, Start->Y, Start->Z);
                if (!Start->walkable) {
                    Start = get_random_walkable_node(permanent->grid);
                }
            }

            grid_node * End =  get_random_walkable_node(permanent->grid);
            ASSERT(Start->walkable);
            ASSERT(End->walkable);

            path_list * PathRaw = find_path(Start, End, permanent->grid, &scratch->arena);
            path_list *Path = NULL;

            if (PathRaw) {
                //Path = smooth_path(PathRaw,  &scratch->arena, permanent->grid);
                Path = PathRaw;

                if (Path) {
                    path_node * done= Path->Sentinel->Prev;
                    while (done != Path->Sentinel) {

                        Node16 *N = NULL;

                        if ( node16->Free->Next !=  node16->Free) {
                            N = node16->Free->Next;
                            node16->Free->Next = N->Next;
                            node16->Free->Next->Prev = node16->Free;
                        } else {
                            N = PUSH_STRUCT(&node16->arena, Node16);
                        }

                        ActorPath * p = &(permanent->paths[i]);

                        // TODO iam not sure about this, is this the right way to center all positions in the path nodes?
                        // should it be done somewhere else instead?
                        // TODO and why o why does it need something extra when facing Front and not under other circumstances.
                        //float xMult = 0;//facing_side == Front ? 1 :  facing_side == Left ?  -0.5 : 0.5;
                        //float yMult = 0;//facing_side == Front ? 0.5 : 1;
                        N->path.node.x =  (permanent->block_size.x/2) + done->X * permanent->block_size.x;
                        N->path.node.y = (permanent->block_size.y/2) + done->Y * permanent->block_size.y;
                        N->path.node.z = done->Z * permanent->block_size.z_level;


                        
                        /* if (done->Prev != Path->Sentinel) { */
                        /*         // going up */
                        /*         if (done->Z > done->Prev->Z) { */
                        /*             printf("going up\n"); */
                        /*             printf("%d,%d,%d     %d,%d,%d\n", done->X,done->Y,done->Z, done->Prev->X, done->Prev->Y, done->Prev->Z); */
                        /*         } */
                        /*         if (done->Z < done->Prev->Z) { */
                        /*             printf("going down 222\n"); */
                        /*             printf("%d,%d,%d     %d,%d,%d\n", done->X,done->Y,done->Z, done->Prev->X, done->Prev->Y, done->Prev->Z); */
                        /*         } */
                        /* } */
                        /* if (done->Next != Path->Sentinel) { */
                        /*         // going down */
                        /*         if (done->Z < done->Next->Z) { */
                        /*             printf("going down\n"); */
                        /*             printf("%d,%d,%d     %d,%d,%d\n", done->X,done->Y,done->Z, done->Next->X, done->Next->Y, done->Next->Z); */


                        /*         } */
                        /* } */

                        
			// if this is part of a stair move going up east/west



                        // TODO: this routine patches some issues which, IMO would better be solved at the root, dunno how wnad where though./
#if 0 // pathing movemenst going up on east/west stairs




                        
                        
                        if (facing_side == Front) {

                             if (done->Prev != Path->Sentinel) {
                                // going up
                                if (done->Z > done->Prev->Z) {
                                    if (done->X < done->Prev->X){
                                        N->path.node.x += permanent->block_size.x;
                                    } else if (done->X > done->Prev->X){
                                        N->path.node.x -= permanent->block_size.x;
                                    }
                                }
                            }
                            if (done->Next != Path->Sentinel) {
                                // going down
                                if (done->Z < done->Next->Z) {
                                    if (done->X < done->Next->X){
                                        N->path.node.x -= permanent->block_size.x;
                                    } else if (done->X > done->Next->X){
                                        N->path.node.x += permanent->block_size.x;
                                    }
                                }
                            }
                        }

                         if (facing_side == Left) {
                             if (done->Prev != Path->Sentinel) {
                             // going up
                                if (done->Z > done->Prev->Z) {
                                    if (done->Y < done->Prev->Y){
                                         N->path.node.y += permanent->block_size.y;
                                    } else if (done->Y > done->Prev->Y){
                                        N->path.node.y -= permanent->block_size.y;
                                    }
                                }
                             }
                             if (done->Next != Path->Sentinel) {
                                // going down
                                if (done->Z < done->Next->Z) {
                                    if (done->Y < done->Next->Y){
                                        N->path.node.y -= permanent->block_size.y;
                                    } else if (done->Y > done->Next->Y){
                                        N->path.node.y += permanent->block_size.y;
                                    }
                                }
                            }
                        }




                         if (facing_side == Right) {
                             if (done->Prev != Path->Sentinel) {
                             // going up
                                if (done->Z > done->Prev->Z) {
                                    if (done->Y < done->Prev->Y){
                                        N->path.node.y += permanent->block_size.y;
                                    } else if (done->Y > done->Prev->Y){
                                        N->path.node.y -= permanent->block_size.y;
                                    }
                                }
                             }
                             if (done->Next != Path->Sentinel) {
                                // going down
                                if (done->Z < done->Next->Z) {
                                    if (done->Y < done->Next->Y){
                                        N->path.node.y -= permanent->block_size.y;
                                    } else if (done->Y > done->Next->Y){
                                        N->path.node.y += permanent->block_size.y;
                                    }
                                }
                            }
                        }
#endif
                        DLIST_ADDFIRST(p, N);
                        done = done->Prev;
                    }
                }

            }
            END_PERFORMANCE_COUNTER(mass_pathfinding);
            //path_list * Path = ExpandPath(PathSmooth, &scratch->arena);
            BEGIN_PERFORMANCE_COUNTER(grid_cleaning);

            for (int i = 0; i < permanent->grid->width * permanent->grid->height * permanent->grid->depth;i++) {
                permanent->grid->nodes[i].f = 0;
                permanent->grid->nodes[i].g = 0;
                permanent->grid->nodes[i].opened = 0;
                permanent->grid->nodes[i].closed = 0;
                permanent->grid->nodes[i].Next = NULL;
                permanent->grid->nodes[i].parent = NULL;
            }
            END_PERFORMANCE_COUNTER(grid_cleaning);

            end_temporary_memory(temp_mem);

        }
        set_colored_line_batch_sizes(permanent, renderer);
    }
#endif

    BEGIN_PERFORMANCE_COUNTER(actors_data_gathering);
    for (u32 i = 0; i < permanent->actor_count; i++) {
        permanent->actors[i]._location =  getRotatedVec3( permanent->steer_data[i].location, facing_side, permanent->dims, permanent->block_size);

        permanent->actors[i]._palette_index = permanent->anim_data[i].palette_index;
        permanent->actors[i]._frame = permanent->anim_data[i].frame;

        permanent->actors[i].x_off = 0;
        permanent->actors[i].y_off = 0;

        if ( permanent->anim_data[i].frame == 4) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_west_body_000];
        } else if (permanent->anim_data[i].frame == 5) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_west_body_001];
        } else if (permanent->anim_data[i].frame == 6) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_south_body_000];
        } else if (permanent->anim_data[i].frame == 7) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_south_body_001];
        } else if (permanent->anim_data[i].frame == 8) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_east_body_000];
        } else if (permanent->anim_data[i].frame == 9) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_east_body_001];
        } else if (permanent->anim_data[i].frame == 10) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_north_body_000];
        } else if (permanent->anim_data[i].frame == 11) {
            permanent->actors[i].complex = &generated_body_frames[BP_walking_north_body_001];
        }

        /* if ( permanent->anim_data[i].frame % 2 == 0) { */
        /*     permanent->actors[i].complex = &generated_body_frames[BP_total_east_body_000]; */
        /* } else { */
        /*     permanent->actors[i].complex = &generated_body_frames[BP_total_east_body_001]; */
        /* } */
    }


    for (u32 i = permanent->actor_count; i < permanent->actor_count*2; i++) {
        u32 j = i - permanent->actor_count;
        permanent->actors[i]._location = getRotatedVec3( permanent->steer_data[j].location, facing_side, permanent->dims, permanent->block_size);
        permanent->actors[i]._palette_index = (1.0f / 16.0f) * (j % 16);//permanent->anim_data[j].palette_index;
        permanent->actors[i]._frame = permanent->anim_data[j].frame;

        int deltaX = permanent->actors[j].complex->anchorX - permanent->actors[j].complex->pivotX;
        int deltaY = permanent->actors[j].complex->anchorY - permanent->actors[j].complex->pivotY;

        permanent->actors[i].x_off = deltaX;
        permanent->actors[i].y_off = -1 * deltaY;

        if ( permanent->anim_data[j].frame == 4) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_west_head_000];
        } else if (permanent->anim_data[j].frame == 5) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_west_head_000];
        } else if (permanent->anim_data[j].frame == 6) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_south_head_000];
        } else if (permanent->anim_data[j].frame == 7) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_south_head_000];
        } else if (permanent->anim_data[j].frame == 8) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_east_head_000];
        } else if (permanent->anim_data[j].frame == 9) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_east_head_000];
        } else if (permanent->anim_data[j].frame == 10) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_north_head_000];
        } else if (permanent->anim_data[j].frame == 11) {
            permanent->actors[i].complex = &generated_body_frames[BP_facing_north_head_000];
        }


    }


    END_PERFORMANCE_COUNTER(actors_data_gathering);


    BEGIN_PERFORMANCE_COUNTER(actors_sort);
    Actor_quick_sort(permanent->actors, permanent->actor_count*2);
    END_PERFORMANCE_COUNTER(actors_sort);

}
Esempio n. 3
0
internal void initialize_memory( PermanentState *permanent, Node16Arena *node16, RenderState *renderer, Memory* memory) {
    permanent->dynamic_blocks     = (StaticBlock*) PUSH_ARRAY(&permanent->arena, (16384), StaticBlock);
    permanent->static_blocks      = (StaticBlock*) PUSH_ARRAY(&permanent->arena, (16384), StaticBlock);
    permanent->transparent_blocks = (StaticBlock*) PUSH_ARRAY(&permanent->arena, (16384), StaticBlock);
    permanent->actors             = (Actor*) PUSH_ARRAY(&permanent->arena, (16384*4), Actor);
    permanent->paths              = (ActorPath*) PUSH_ARRAY(&permanent->arena, (16384*4), ActorPath);
    permanent->steer_data         = (ActorSteerData*) PUSH_ARRAY(&permanent->arena, (16384*4), ActorSteerData);
    for (int i = 0; i < 16384*4; i++) {
        permanent->steer_data[i].mass      = 1.0f;
        permanent->steer_data[i].max_force = 10;
        permanent->steer_data[i].max_speed = 50 + rand_float() * 80;
    }
    permanent->anim_data = (ActorAnimData*) PUSH_ARRAY(&permanent->arena, (16384*4), ActorAnimData);

    for (int i = 0; i < 16384*4; i++) {
        permanent->anim_data[i].frame = 4;
    }
    for (int i = 0; i < 16384*4; i++) {
        Node16 *Sentinel = (Node16 *) PUSH_STRUCT(&node16->arena, Node16);
        permanent->paths[i].Sentinel            = Sentinel;
        permanent->paths[i].Sentinel->Next      = Sentinel;
        permanent->paths[i].Sentinel->Prev      = Sentinel;
        permanent->actors[i].index              = i;
        permanent->paths[i].Sentinel->path.node = Vector3Make(-999,-999,-999);
    }

    node16->Free = PUSH_STRUCT(&node16->arena, Node16);
    node16->Free->Next = node16->Free;
    node16->Free->Prev = node16->Free;

    permanent->glyphs = (Glyph*) PUSH_ARRAY(&permanent->arena, (16384), Glyph);
    permanent->colored_lines = (ColoredLine*) PUSH_ARRAY(&permanent->arena, (16384), ColoredLine);

    BlockTextureAtlasPosition texture_atlas_data[BlockTotal];
    fill_generated_values(generated_frames);
    fill_generated_complex_values(generated_body_frames);

    texture_atlas_data[Floor]        = convertSimpleFrameToBlockTexturePos(generated_frames[BL_floor_000], 0, 0);
    texture_atlas_data[WallBlock]    = convertSimpleFrameToBlockTexturePos(generated_frames[BL_wall_000], 0, 0);
    texture_atlas_data[WindowBlock]  = convertSimpleFrameToBlockTexturePos(generated_frames[BL_window_000], 0, 0);
    texture_atlas_data[LadderUp]     = convertSimpleFrameToBlockTexturePos(generated_frames[BL_ladder_up_000], 0, 0);
    texture_atlas_data[LadderUpDown] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_ladder_up_down_000], 0, 0);
    texture_atlas_data[LadderDown]   = convertSimpleFrameToBlockTexturePos(generated_frames[BL_ladder_down_000], 0, 0);

    texture_atlas_data[EscalatorDown1S] = texture_atlas_data[EscalatorUp1S] = texture_atlas_data[Stairs1S] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_south_up_000], 0, 0);
    texture_atlas_data[EscalatorDown2S] = texture_atlas_data[EscalatorUp2S] = texture_atlas_data[Stairs2S] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_south_up_000], 0, 24);
    texture_atlas_data[EscalatorDown3S] = texture_atlas_data[EscalatorUp3S] = texture_atlas_data[Stairs3S] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_south_up_000], 0, 48);
    texture_atlas_data[EscalatorDown4S] = texture_atlas_data[EscalatorUp4S] = texture_atlas_data[Stairs4S] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_south_up_000], 0, 72);

    texture_atlas_data[EscalatorDown1N] = texture_atlas_data[EscalatorUp1N] = texture_atlas_data[Stairs1N] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_north_up_000], 0, 0);
    texture_atlas_data[EscalatorDown2N] = texture_atlas_data[EscalatorUp2N] = texture_atlas_data[Stairs2N] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_north_up_000], 0, 24);
    texture_atlas_data[EscalatorDown3N] = texture_atlas_data[EscalatorUp3N] = texture_atlas_data[Stairs3N] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_north_up_000], 0, 48);
    texture_atlas_data[EscalatorDown4N] = texture_atlas_data[EscalatorUp4N] = texture_atlas_data[Stairs4N] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_north_up_000], 0, 72);

    texture_atlas_data[EscalatorDown1W] = texture_atlas_data[EscalatorUp1W] = texture_atlas_data[Stairs1W] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_west_up_000], 0, 0);
    texture_atlas_data[EscalatorDown2W] = texture_atlas_data[EscalatorUp2W] = texture_atlas_data[Stairs2W] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_west_up_000], 0, 24);
    texture_atlas_data[EscalatorDown3W] = texture_atlas_data[EscalatorUp3W] = texture_atlas_data[Stairs3W] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_west_up_000], 0, 48);
    texture_atlas_data[EscalatorDown4W] = texture_atlas_data[EscalatorUp4W] = texture_atlas_data[Stairs4W] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_west_up_000], 0, 72);

    texture_atlas_data[EscalatorDown1E] = texture_atlas_data[EscalatorUp1E] = texture_atlas_data[Stairs1E] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_east_up_000], 0, 0  );
    texture_atlas_data[EscalatorDown2E] = texture_atlas_data[EscalatorUp2E] = texture_atlas_data[Stairs2E] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_east_up_000], 0, 24 );
    texture_atlas_data[EscalatorDown3E] = texture_atlas_data[EscalatorUp3E] = texture_atlas_data[Stairs3E] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_east_up_000], 0, 48 );
    texture_atlas_data[EscalatorDown4E] = texture_atlas_data[EscalatorUp4E] = texture_atlas_data[Stairs4E] = convertSimpleFrameToBlockTexturePos(generated_frames[BL_escalator_east_up_000], 0, 72 );

    int used_static_block_count = 0;
    int used_dynamic_block_count = 0;
    int used_transparent_block_count = 0;

    for (u32 z = 0; z < permanent->dims.z_level ; z++){
        for (u32 y = 0; y< permanent->dims.y; y++){
            for (u32 x = 0; x< permanent->dims.x; x++){
                WorldBlock *b = &permanent->level.blocks[FLATTEN_3D_INDEX(x,y,z,permanent->dims.x, permanent->dims.y)];


                u32 x_ = getRotatedXInt(x, y, facing_side, permanent->dims);
                u32 y_ = getRotatedYInt(x, y, facing_side, permanent->dims);
                Block block = getRotatedBlock(b->object, facing_side);


                permanent->static_blocks[used_static_block_count].is_floor = 0;
                switch (block){
                case WindowBlock:
                    add_transparent_block(x_, y_, z, permanent, &used_transparent_block_count, texture_atlas_data[block]);
                    used_transparent_block_count++;
                    break;

                case WallBlock:
                case LadderUpDown:
                case LadderUp:
                case LadderDown:
                    add_static_block(x_, y_, z, permanent, &used_static_block_count, texture_atlas_data[block]);
                    used_static_block_count++;
                    break;

                case Floor:
                case Stairs1N: case Stairs2N: case Stairs3N: case Stairs4N:
                case Stairs1E: case Stairs2E: case Stairs3E: case Stairs4E:
                case Stairs1S: case Stairs2S: case Stairs3S: case Stairs4S:
                case Stairs1W: case Stairs2W: case Stairs3W: case Stairs4W:
                    add_static_block(x_, y_, z, permanent, &used_static_block_count, texture_atlas_data[block]);
                    permanent->static_blocks[used_static_block_count].is_floor = 1;
                    used_static_block_count++;
                    break;

                case EscalatorUp1N: case EscalatorUp2N: case EscalatorUp3N: case EscalatorUp4N:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_north_up_000, BL_escalator_north_up_011, 0.5f/12, 1);
                    used_dynamic_block_count++;
                    break;
                case EscalatorDown1N: case EscalatorDown2N: case EscalatorDown3N: case EscalatorDown4N:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_north_up_000, BL_escalator_north_up_011, 0.5f/12, 0);
                    used_dynamic_block_count++;
                    break;
                case EscalatorUp1E: case EscalatorUp2E: case EscalatorUp3E: case EscalatorUp4E:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_east_up_000, BL_escalator_east_up_007, 0.5f/8, 1);
                    used_dynamic_block_count++;
                    break;
                case EscalatorDown1E: case EscalatorDown2E: case EscalatorDown3E: case EscalatorDown4E:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block],  BL_escalator_east_up_000,  BL_escalator_east_up_007, 0.5f/8, 0);
                    used_dynamic_block_count++;
                    break;
                case EscalatorUp1W: case EscalatorUp2W: case EscalatorUp3W: case EscalatorUp4W:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_west_up_000, BL_escalator_west_up_007, 0.5f/8, 1);
                    used_dynamic_block_count++;
                    break;
                case EscalatorDown1W: case EscalatorDown2W: case EscalatorDown3W: case EscalatorDown4W:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_west_up_000, BL_escalator_west_up_007, 0.5f/8, 0);
                    used_dynamic_block_count++;
                    break;
                case EscalatorUp1S: case EscalatorUp2S: case EscalatorUp3S: case EscalatorUp4S:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_south_up_000, BL_escalator_south_up_007, 0.5f/8, 1);
                    used_dynamic_block_count++;
                    break;
                case EscalatorDown1S: case EscalatorDown2S: case EscalatorDown3S: case EscalatorDown4S:
                    permanent->dynamic_blocks[used_dynamic_block_count].is_floor = 1;
                    add_dynamic_block(x_, y_, z, permanent, &used_dynamic_block_count, texture_atlas_data[block], BL_escalator_south_up_000, BL_escalator_south_up_007, 0.5f/8, 0);
                    used_dynamic_block_count++;
                    break;
                case Grass:
                case Wood:
                case Concrete:
                case Nothing:
                case Tiles:
                case Carpet:
                case EscalatorUpMeta:
                case EscalatorDownMeta:
                case StairsMeta:
                case StairsFollowUpMeta:
                case Shaded:
                case BlockTotal:

                default:
                    break;
                }
            }
        }
    }

    permanent->static_block_count      = used_static_block_count;
    permanent->dynamic_block_count     = used_dynamic_block_count;
    permanent->transparent_block_count = used_transparent_block_count;

    set_static_block_batch_sizes(permanent, renderer);
    set_dynamic_block_batch_sizes(permanent, renderer);
    set_transparent_block_batch_sizes(permanent, renderer);

    qsort(permanent->static_blocks, used_static_block_count, sizeof(StaticBlock), sort_static_blocks_front_back);
    qsort(permanent->transparent_blocks, used_transparent_block_count, sizeof(StaticBlock), sort_static_blocks_back_front);

    renderer->needs_prepare = 1;

    set_actor_batch_sizes(permanent, renderer);

    permanent->grid = PUSH_STRUCT(&permanent->arena, Grid);
    init_grid(permanent->grid, &permanent->arena, &permanent->level);
    preprocess_grid(permanent->grid);
    set_colored_line_batch_sizes(permanent, renderer);
    memory->is_initialized = true;

}