📄 main.cpp
字号:
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 + -