⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.cpp

📁 国外游戏开发者杂志2003年第七期配套代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        child_opacity = 1;
    }

    tree->opacity = my_opacity;
    tree->lod_instance_state = I_AM_TRANSITIONING;

    set_child_properties(tree, child_opacity, frame_index, I_AM_TRANSITIONING);

    mesh_triangles += tree->mesh->num_faces;
    mesh_triangles += count_child_triangles(tree);
}

// Rotate the camera based on mouse input.
void update_camera_orientation() {
    int mouse_x = app_shell->mouse_pointer_delta_x;
    int mouse_y = app_shell->mouse_pointer_delta_y;

    // Don't allow motion for the first several frames,
    // because we have Windows mouse weirdness problems.
    if (global_current_lod_frame_index > NUM_FRAMES_WITHOUT_INPUT) {
        const float RADIANS_PER_MOUSE_TICK = .01;
        camera_theta -= mouse_x * RADIANS_PER_MOUSE_TICK;
        camera_phi -= mouse_y * RADIANS_PER_MOUSE_TICK;
    }

    Clamp(camera_phi, -M_PI * 0.5f, M_PI * 0.5f);

    float theta = camera_theta;
    float phi = camera_phi;

    Quaternion rotation_theta;
    Quaternion rotation_phi;

    rotation_theta.set_from_axis_and_angle(0, 0, 1, theta);

    Vector3 new_y(0, 1, 0);
    new_y.rotate(rotation_theta);
    rotation_phi.set_from_axis_and_angle(new_y.x, new_y.y, new_y.z, phi);
    Quaternion rotation = rotation_phi * rotation_theta;

    client_globals.camera_orientation = rotation;
}


// Move the camera through the world based on our current
// velocity and direction.
void simulate_viewpoint_motion() {
    if (!moving) return;

    // Okay, let's simulate the view position along...
    Vector3 view_vector(1, 0, 0);
    view_vector.rotate(client_globals.camera_orientation);

    float dt = app_shell->get_dt();
    Vector3 delta = view_vector * viewpoint_speed * dt;
    client_globals.camera_position = client_globals.camera_position + delta;
}


void draw_world_demo() {
    if (the_world_tree == NULL) return;

    global_current_lod_frame_index++;
    
    mesh_triangles = 0;  // This gets incremented by select_world_lods

    // Figure out the LOD for each part of the world.
    select_world_lods(the_world_tree);

    // Find visible world blocks...
    Segregated_World_Pieces pieces;
    collect_visible_world(the_world_tree, &pieces);


    // Push the camera transform onto the transform stack
    // (this computes the product of the transform matrix with
    // whatever was already on the stack).
    push_viewpoint_transform(client_globals.transformer, client_globals.camera_position, client_globals.camera_orientation);


    // Send this transform to the graphics library so that the lighting
    // gets set up properly.
    rendering_3d(client_globals.transformer->current_transform, client_globals.view_projector);

    void draw_ground();
    if (should_draw_ground) draw_ground();


    // Draw the world blocks...


    // SOLID blocks

    setup_mesh_render_state(RS_SOLID, false);

    World_Block *node;
    if (draw_solid_blocks) {
        Array_Foreach(&pieces.solid, node) {
            draw_single_block(node);
        } Endeach;
    }

    if (wireframe) {
        setup_mesh_render_state(RS_SOLID, true);

        World_Block *node;
        if (draw_solid_blocks) {
            Array_Foreach(&pieces.solid, node) {
                draw_single_block(node);
            } Endeach;
        }
    }

    
    // Now we draw the seams... fun fun!
    
    Auto_Array <Mesh_Seam *> seams;

    // First mark the solid blocks.
    Array_Foreach(&pieces.solid, node) {
        node->block_search_marker = 1;
    } Endeach;

    // Now search...
    seam_database->collect_fully_marked_seams(&seams);

    // Now unmark the solid blocks!
    Array_Foreach(&pieces.solid, node) {
        node->block_search_marker = 0;
    } Endeach;


    // Re-ensure render state
    setup_mesh_render_state(RS_SOLID, false);

    // Set up the transform...
    rendering_3d(client_globals.transformer->current_transform, client_globals.view_projector);
    // And kick 'em out, homey!
    Mesh_Seam *seam;
    Array_Foreach(&seams, seam) {
        draw_world_view_seam(seam);
    } Endeach;

    if (wireframe) {
        setup_mesh_render_state(RS_SOLID, true);
        Array_Foreach(&seams, seam) {
            draw_world_view_seam(seam);
        } Endeach;
    }

    if (wireframe) {
        // Icky hack!
        mesh_triangles_rendered /= 2;
        seam_triangles_rendered /= 2;
    }

    // All done with the seams!
    // Now time to do fading blocks.


    setup_mesh_render_state(RS_FADING, wireframe);

    // FADING blocks, and right now we toggle the z-state appropriately...
    sort_world(&pieces.fading);
    Array_Foreach(&pieces.fading, node) {
        setup_mesh_render_opacity(node->opacity, node->use_zfunc_lessequal);
        draw_single_block(node);
    } Endeach;


    // Done!

    pop_viewpoint_transform(client_globals.transformer);
}


void draw_ground() {
    static Loaded_Texture_Info ground_texture;
    static bool first = true;
    if (first) {
        first = false;
        app_shell->load_texture(&ground_texture, "data\\ground.jpg");
    }

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    glColor3f(1, 1, 1);
    glEnable(GL_TEXTURE_2D);

    const float GROUND_SIZE = 500;
    glBindTexture(GL_TEXTURE_2D, ground_texture.texture_handle);
    float s = GROUND_SIZE;
    float u = 12.0f;
    float z = -5.0f;

    glBegin(GL_TRIANGLES);
    glTexCoord2f(0, 0);
    glVertex3f(-s, -s, z);
    glTexCoord2f(u, 0);
    glVertex3f(+s, -s, z);
    glTexCoord2f(u, u);
    glVertex3f(+s, +s, z);

    glTexCoord2f(0, 0);
    glVertex3f(-s, -s, z);
    glTexCoord2f(u, u);
    glVertex3f(+s, +s, z);
    glTexCoord2f(0, u);
    glVertex3f(-s, +s, z);
    glEnd();
}

// Draw the scene!
void draw_scene() {
    Transformer *tr = client_globals.transformer;
    Projector *pr = client_globals.view_projector;

    // Reset some stat counters...
    mesh_triangles_rendered = 0;
    mesh_triangles = 0;
    seam_triangles_rendered = 0;

    // Set up the view projection
    pr->set_viewport(app_shell->screen_width, app_shell->screen_height);
    pr->set_fov(M_PI * 0.4);


    update_camera_orientation();
    simulate_viewpoint_motion();

    draw_world_demo();

    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    draw_world_view_hud();

    // Sleep here so that the OS doesn't spaz out and get starved
    // (this is especially a problem with Windows XP; XP really sucks).
    // We're not really going for speed right now so this is okay.
    app_shell->sleep(0.01f);
}


// Handle keyboard input...
void adjust_view_speed(int factor) {
    const float BASE_UNITS_PER_SECOND = 0.8f;
    float scalar = factor * BASE_UNITS_PER_SECOND;
    viewpoint_speed = scalar;
}


void seam_explode_recurse(World_Block *block, float factor) {
    block->position *= factor;
    int i;
    for (i = 0; i < block->num_children; i++) {
        seam_explode_recurse(block->children[i], factor);
    }
}

void toggle_seam_explode() {
    explode_seams = !explode_seams;
    float factor = explode_seams ? 1.2f : (float)(1.0 / 1.2);
    seam_explode_recurse(the_world_tree, factor);
}

void handle_keydown(int key) {
    switch (key) {
    case 'W':
        wireframe = !wireframe;
        break;
    case 'O':
        obvious_seams = !obvious_seams;
        break;
    case 'G':
        should_draw_ground = !should_draw_ground;
        break;
    case 'E':
        toggle_seam_explode();
        break;
    case 'H':
        draw_hud = !draw_hud;
        break;
    case 'S':
        draw_solid_blocks = !draw_solid_blocks;
        break;
    case 'C':
        color_code_by_lod = !color_code_by_lod;
        break;
    case 'T':
        textures_disabled = !textures_disabled;
        break;
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8': {
        int factor = key - '0';
        adjust_view_speed(factor*factor);
        break;
    }
    case '9':
        adjust_view_speed(-9);
        break;
    case '-':
        adjust_view_speed(-1);
        break;
    case ' ':
        moving = !moving;
        break;
    }
}

void handle_keyup(int key) {
}

/*
  app_init does a bunch of unexciting stuff to load data
  and generally get us ready to run.
*/
void app_init(int argc, char **argv) {
    app_shell->show_mouse_pointer = false;
    app_shell->center_mouse_pointer = true;

    // Check to see if we will be able to use the opengl
    // vertex buffer extensions.
    int extensions = init_gl_extensions();
    if (extensions & EXTENSION_ARB_VERTEX_BUFFER_OBJECT) {
        using_vertex_buffers = true;
    }

    client_globals.transformer = new Transformer();
    client_globals.transformer->push_identity();

    client_globals.view_projector = new Projector();
    client_globals.view_projector->set_viewport(app_shell->screen_width, app_shell->screen_height);
    client_globals.view_projector->set_fov(M_PI * 0.5);


    // Fonts we use to draw HUD text.
    client_globals.big_font = app_shell->load_font("data/Century Big");
    assert(client_globals.big_font != NULL);

    client_globals.small_font = app_shell->load_font("data/Century Small");
    assert(client_globals.small_font != NULL);

    // The 'white_texture' is used when you turn off the world
    // texture from the HUD...
    app_shell->load_texture(&white_texture, "data/bitmaps/white.jpg");
    assert(white_texture.loaded_successfully);

    app_shell->load_texture(&red_texture, "data/bitmaps/red.jpg");
    assert(red_texture.loaded_successfully);


    // Load mesh, init vertex data

    char *name;
    if (argc > 0) {
        name = argv[0];
    } else {
        name = "output.world_lod";
    }

    global_world_file_name = name;
    File_Handle *f = fopen(name, "rb");
    if (f == NULL) {
        name = "output.world_lod";
        f = fopen(name, "rb");
    }

    if (f) {
        the_world_tree = load_world(f, &seam_database);
        fclose(f);
        assert(the_world_tree);
        recursively_init_rendering_data(the_world_tree);
        recursively_compute_lod_distances(the_world_tree, 0.5f, 20.0f);
    } else {
        the_world_tree = NULL;
    }

    client_globals.camera_position = Vector3(540.121f, -7.72513f, 95.7266f);
    camera_theta = -3.15460f;
    camera_phi = 0.2f;
}


void init_rendering_data(World_Block *block) {
    if (block->mesh == NULL) return;

    int i;
    for (i = 0; i < block->mesh->num_materials; i++) {
        int handle = app_shell->find_or_load_texture(block->mesh->material_info[i].name, "data/bitmaps/");
        block->mesh->material_info[i].texture_index = handle;
    }
}


void recursively_init_rendering_data(World_Block *node) {
    if (node == NULL) return;

    int i;
    for (i = 0; i < node->num_children; i++) {
        recursively_init_rendering_data(node->children[i]);
    }

    init_rendering_data(node);
}




void compute_lod_distances(World_Block *node, float parameter, float fade_radius) {
    if (node->num_children) {
        float distance = node->worldspace_error * parameter;
        node->distance_of_lod_demand = distance;

        int i;
        for (i = 0; i < node->num_children; i++) {
            World_Block *child = node->children[i];
            float dist = child->distance_at_which_i_begin_subdividing + fade_radius;
            if (dist > node->distance_of_lod_demand) node->distance_of_lod_demand = dist;
        }

        if (node->distance_of_lod_demand < fade_radius) node->distance_of_lod_demand = fade_radius;

        node->distance_at_which_i_begin_subdividing = node->distance_of_lod_demand + fade_radius;
        node->distance_at_which_i_am_gone = node->distance_of_lod_demand - fade_radius;
    } else {
        node->distance_at_which_i_begin_subdividing = 0;
        node->distance_of_lod_demand = 0;
        node->distance_at_which_i_am_gone = 0;

        if (node->mesh) high_res_triangle_count += node->mesh->num_faces;
    }
}

void recursively_compute_lod_distances(World_Block *node, float parameter, float fade_radius) {
    if (node == NULL) return;

    int i;
    for (i = 0; i < node->num_children; i++) {
        recursively_compute_lod_distances(node->children[i], parameter, fade_radius);
    }

    compute_lod_distances(node, parameter, fade_radius);
}


void push_viewpoint_transform(Transformer *tr, Vector3 pos, Quaternion ori) {
    Matrix4 matrix;
    matrix.identity();
    matrix.translate(-1 * pos);
    matrix.rotate(ori.conjugate());

    tr->push(&matrix);
}

void pop_viewpoint_transform(Transformer *tr) {
    tr->pop();
}


Quaternion get_viewpoint_orientation() {
    return client_globals.camera_orientation;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -