void init_positions(void) { int i; X = GRID_RANGE / 2.; Y = GRID_RANGE / 2.; Z = 1.5; /* * randomly position the planes near center of world * take MAX of height above terrain and 0, so planes * don't fall into canyon. Canyon has negative elevation */ for (i = 0; i < NUM_PLANES; i++) { flock[i].PX = (float) IRND(20) + GRID_RANGE / 2 - 10; flock[i].PY = (float) IRND(20) + GRID_RANGE / 2 - 10; flock[i].PZ = MAX(terrain_height(flock[i].PX, flock[i].PY),0.) + 2.*(float)i/NUM_PLANES+.3; flock[i].Pazimuth = ((float)IRND(256) / 128.) * M_PI; } Speed = 0.1f; Azimuth = M_PI / 2.; #if 0 // if (Init_pos) { // X = Init_x; // Y = Init_y; // Z = Init_z; // Azimuth = Init_azimuth; // Keyboard_mode = 1; // } #endif }
static void toggle_freecam(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, vec2_new(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; freecam = !freecam; camera* cam = entity_get("camera"); landscape* world = entity_get("world"); vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; cam->target = vec3_add(cam->position, cam_dir); } } }
void scotland_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); static_object* skydome = entity_get("skydome"); landscape* world = entity_get("world"); sun_orbit += frame_time() * 0.01; sun->position.x = 512 + sin(sun_orbit) * 512; sun->position.y = cos(sun_orbit) * 512; sun->position.z = 512; sun->target = vec3_new(512, 0, 512); if (w_held || s_held) { vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float speed = 0.5; if (!freecam) speed = 0.05; if (w_held) { cam->position = vec3_add(cam->position, vec3_mul(cam_dir, speed)); } if (s_held) { cam->position = vec3_sub(cam->position, vec3_mul(cam_dir, speed)); } if (!freecam) { float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; } cam->target = vec3_add(cam->position, cam_dir); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * 0.005; float a2 = (float)mouse_y * 0.005; vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); cam_dir.y += -a2; vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0))); cam_dir = vec3_add(cam_dir, vec3_mul(side_dir, -a1)); cam_dir = vec3_normalize(cam_dir); cam->target = vec3_add(cam->position, cam_dir); } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
mat3 terrain_axis(terrain* ter, vec2 position) { float offset = terrain_height(ter, position); float offset_x = terrain_height(ter, vec2_add(position, vec2_new(1,0))); float offset_y = terrain_height(ter, vec2_add(position, vec2_new(0,1))); vec3 pos = vec3_new(position.x+0, offset, position.y+0); vec3 pos_xv = vec3_new(position.x+1, offset_x, position.y+0); vec3 pos_yv = vec3_new(position.x+0, offset_y, position.y+1); vec3 tangent = vec3_normalize(vec3_sub(pos_xv, pos)); vec3 binorm = vec3_normalize(vec3_sub(pos_yv, pos)); vec3 normal = vec3_cross(binorm, tangent); return mat3_new( tangent.x, tangent.y, tangent.z, normal.x, normal.y, normal.z, binorm.x, binorm.y, binorm.z); }
void fly(perfobj_t *viewer_pos) { float terrain_z, xpos, ypos, xcntr, ycntr; float delta_speed = .003; /* if (++_frame == 1000) { _frame = 0; init_positions(); }*/ xcntr = Wxsize / 2; ycntr = Wysize / 2; if (Xgetbutton(RKEY)) init_positions(); if (Xgetbutton(SPACEKEY)) { Keyboard_mode = !Keyboard_mode; } if (Keyboard_mode) { /* * step-at-a-time debugging mode */ if (Keyboard_mode && Xgetbutton(LEFTARROWKEY)) { Azimuth -= 0.025; } if (Keyboard_mode && Xgetbutton(RIGHTARROWKEY)) { Azimuth += 0.025; } if (Keyboard_mode && Xgetbutton(UPARROWKEY)) { X += cosf(-Azimuth + M_PI / 2.) * 0.025; Y += sinf(-Azimuth + M_PI / 2.) * 0.025; } if (Keyboard_mode && Xgetbutton(DOWNARROWKEY)) { X -= cosf(-Azimuth + M_PI / 2.) * 0.025; Y -= sinf(-Azimuth + M_PI / 2.) * 0.025; } if (Keyboard_mode && Xgetbutton(PAGEUPKEY)) { Z += 0.025; } if (Keyboard_mode && Xgetbutton(PAGEDOWNKEY)) { Z -= 0.025; } } else { /* * simple, mouse-driven flight model */ if (Xgetbutton(LEFTMOUSE) && Speed < .3) Speed += delta_speed; if (Xgetbutton(RIGHTMOUSE) && Speed > -.3) Speed -= delta_speed; if (Xgetbutton(MIDDLEMOUSE)) Speed = Speed*.8; xpos = (Xgetvaluator(MOUSEX)-xcntr) / ((float)Wxsize*14.); ypos = (Xgetvaluator(MOUSEY)-ycntr) / ((float)Wysize*.5); /* * move in direction of view */ Azimuth += xpos; X += cosf(-Azimuth + M_PI / 2.) * Speed; Y += sinf(-Azimuth + M_PI / 2.) * Speed; Z -= ypos * Speed; } /* * keep from getting too close to terrain */ terrain_z = terrain_height(X, Y); if (Z < terrain_z +.4) Z = terrain_z +.4; X = MAX(X, 1.); X = MIN(X, GRID_RANGE); Y = MAX(Y, 1.); Y = MIN(Y, GRID_RANGE); Z = MIN(Z, 20.); *((float *) viewer_pos->vdata + 0) = X; *((float *) viewer_pos->vdata + 1) = Y; *((float *) viewer_pos->vdata + 2) = Z; *((float *) viewer_pos->vdata + 3) = Azimuth; }
void fly_paper_planes(perfobj_t *paper_plane_pos) { int i; float speed = .08; float terrain_z; /* * slow planes down in cyclops mode since * frame rate is doubled */ for (i = 0; i < NUM_PLANES; i++) { /* * If plane is not turning, one chance in 50 of * starting a turn */ if (flock[i].Pcount == 0 && IRND(50) == 1) { /* initiate a roll */ /* roll for a random period */ flock[i].Pcount = IRND(100); /* random turn rate */ flock[i].Pturn_rate = IRND(100) / 10000.; flock[i].Pdirection = IRND(3) - 1; } if (flock[i].Pcount > 0) { /* continue rolling */ flock[i].Proll += flock[i].Pdirection * flock[i].Pturn_rate; flock[i].Pcount--; } else /* damp amount of roll when turn complete */ flock[i].Proll *=.95; /* turn as a function of roll */ flock[i].Pazimuth -= flock[i].Proll *.05; /* follow terrain elevation */ terrain_z=terrain_height(flock[i].PX,flock[i].PY); /* use a "spring-mass-damp" system of terrain follow */ flock[i].PZv = flock[i].PZv - .01 * (flock[i].PZ - (MAX(terrain_z,0.) + 2.*(float)i/NUM_PLANES+.3)) - flock[i].PZv *.04; /* U-turn if fly off world!! */ if (flock[i].PX < 1 || flock[i].PX > GRID_RANGE - 2 || flock[i].PY < 1 || flock[i].PY > GRID_RANGE - 2) flock[i].Pazimuth += M_PI; /* move planes */ flock[i].PX += cosf(flock[i].Pazimuth) * speed; flock[i].PY += sinf(flock[i].Pazimuth) * speed; flock[i].PZ += flock[i].PZv; } for (i = 0; i < NUM_PLANES; i++) { *((float *) paper_plane_pos[i].vdata + 0) = flock[i].PX; *((float *) paper_plane_pos[i].vdata + 1) = flock[i].PY; *((float *) paper_plane_pos[i].vdata + 2) = flock[i].PZ; *((float *) paper_plane_pos[i].vdata + 3) = flock[i].Pazimuth * RAD_TO_DEG; *((float *) paper_plane_pos[i].vdata + 4) = flock[i].PZv * (-500.); *((float *) paper_plane_pos[i].vdata + 5) = flock[i].Proll *RAD_TO_DEG; } }
static void terrain_new_chunk(terrain* ter, int i) { const int SUBDIVISIONS = NUM_TERRAIN_SUBDIVISIONS+1; terrain_chunk* tc = malloc(sizeof(terrain_chunk)); tc->id = i; tc->x = i % ter->num_cols; tc->y = i / ter->num_cols; tc->width = ter->chunk_width; tc->height = ter->chunk_height; int x_max = tc->width * SUBDIVISIONS + 1; int y_max = tc->height * SUBDIVISIONS + 1; tc->num_verts = x_max * y_max + x_max * 2 + y_max * 2; vec3* vertex_buffer = malloc(sizeof(vec3) * 4 * tc->num_verts); int index = 0; for(int x = 0; x < x_max; x++) for(int y = 0; y < y_max; y++) { float gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; float gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)); mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } /* Adding fins. Don't look, horrible code */ const float FIN_DEPTH = 5.0; for(int y = 0; y < y_max; y++) { int gx = tc->x * ter->chunk_width + 0; int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int y = 0; y < y_max; y++) { int gx = tc->x * ter->chunk_width + ter->chunk_width; int gy = tc->y * ter->chunk_height + (float)y/SUBDIVISIONS; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int x = 0; x < x_max; x++) { int gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; int gy = tc->y * ter->chunk_height + 0; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } for(int x = 0; x < x_max; x++) { int gx = tc->x * ter->chunk_width + (float)x/SUBDIVISIONS; int gy = tc->y * ter->chunk_height + ter->chunk_height; float height = terrain_height(ter, vec2_new(gx, gy)) - FIN_DEPTH; mat3 axis = terrain_tbn(ter, vec2_new(gx, gy)); vec3 pos = vec3_new(gx, height, gy); vec3 tangent = mat3_mul_vec3(axis, vec3_new(1,0,0)); vec3 normal = mat3_mul_vec3(axis, vec3_new(0,1,0)); vec3 binorm = mat3_mul_vec3(axis, vec3_new(0,0,1)); vertex_buffer[index] = pos; index++; vertex_buffer[index] = normal; index++; vertex_buffer[index] = tangent; index++; vertex_buffer[index] = binorm; index++; } tc->bound.center = vec3_zero(); for (int i = 0; i < index; i+=4) { tc->bound.center = vec3_add(tc->bound.center, vertex_buffer[i]); } tc->bound.center = vec3_div(tc->bound.center, tc->num_verts); tc->bound.radius = 0; for (int i = 0; i < index; i+=4) { tc->bound.radius = max(tc->bound.radius, vec3_dist(tc->bound.center, vertex_buffer[i])); } if (net_is_client()) { glGenBuffers(1, &tc->vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, tc->vertex_buffer); glBufferData(GL_ARRAY_BUFFER, sizeof(vec3) * 4 * tc->num_verts, vertex_buffer, GL_STATIC_DRAW); } free(vertex_buffer); if (net_is_client()) { glGenBuffers(NUM_TERRAIN_BUFFERS, tc->index_buffers); } for(int j = 0; j < NUM_TERRAIN_BUFFERS; j++) { int off = pow(2, j); int x_max = tc->width * SUBDIVISIONS; int y_max = tc->height * SUBDIVISIONS; tc->num_indicies[j] = (x_max / off) * (y_max / off) * 6 + (x_max / off) * 12 + (y_max / off) * 12; uint32_t* index_buffer = malloc(sizeof(uint32_t) * tc->num_indicies[j]); index = 0; for(int x = 0; x < x_max; x+=off) for(int y = 0; y < y_max; y+=off) { index_buffer[index] = x + y * (x_max+1); index++; index_buffer[index] = (x+off) + y * (x_max+1); index++; index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++; index_buffer[index] = x + y * (x_max+1); index++; index_buffer[index] = (x+off) + (y+off) * (x_max+1); index++; index_buffer[index] = x + (y+off) * (x_max+1); index++; } /* Again, adding fins. Don't look horrible code */ int x_base = (x_max + 1) * (y_max + 1); int y_base = (x_max + 1) * (y_max + 1) + (x_max + 1) * 2; for(int x = 0; x < x_max; x+=off) { index_buffer[index] = x + 0 * (x_max+1); index++; index_buffer[index] = x_base + x; index++; index_buffer[index] = (x+off) + 0 * (x_max+1); index++; index_buffer[index] = (x+off) + 0 * (x_max+1); index++; index_buffer[index] = x_base + x; index++; index_buffer[index] = x_base + x+off; index++; } for(int x = 0; x < x_max; x+=off) { index_buffer[index] = x + y_max * (x_max+1); index++; index_buffer[index] = (x+off) + y_max * (x_max+1); index++; index_buffer[index] = x_base + y_max+1 + x; index++; index_buffer[index] = (x+off) + y_max * (x_max+1); index++; index_buffer[index] = x_base + x_max+1 + x+off; index++; index_buffer[index] = x_base + x_max+1 + x; index++; } for(int y = 0; y < y_max; y+=off) { index_buffer[index] = 0 + y * (x_max+1); index++; index_buffer[index] = 0 + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y; index++; index_buffer[index] = 0 + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y+off; index++; index_buffer[index] = y_base + y; index++; } for(int y = 0; y < y_max; y+=off) { index_buffer[index] = x_max + y * (x_max+1); index++; index_buffer[index] = y_base + y_max+1 + y; index++; index_buffer[index] = x_max + (y+off) * (x_max+1); index++; index_buffer[index] = x_max + (y+off) * (x_max+1); index++; index_buffer[index] = y_base + y_max+1 + y; index++; index_buffer[index] = y_base + y_max+1 + y+off; index++; } if (net_is_client()) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tc->index_buffers[j]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint32_t) * tc->num_indicies[j], index_buffer, GL_DYNAMIC_DRAW); } free(index_buffer); } tc->colmesh = malloc(sizeof(cmesh)); tc->colmesh->is_leaf = true; tc->colmesh->triangles_num = (tc->width/4) * (tc->height/4) * 2; tc->colmesh->triangles = malloc(sizeof(ctri) * tc->colmesh->triangles_num); int tri_i = 0; for (int x = 0; x < tc->width; x += 4) for (int y = 0; y < tc->height; y += 4) { float gx = tc->x * ter->chunk_width + (float)x; float gy = tc->y * ter->chunk_height + (float)y; vec3 a = vec3_new(gx , terrain_height(ter, vec2_new(gx , gy )) , gy ); vec3 b = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy )) , gy ); vec3 c = vec3_new(gx+4, terrain_height(ter, vec2_new(gx+4, gy+4)) , gy+4); vec3 d = vec3_new(gx , terrain_height(ter, vec2_new(gx , gy+4)) , gy+4); vec3 tang = vec3_normalize(vec3_sub(b, a)); vec3 binorm = vec3_normalize(vec3_sub(d, a)); vec3 norm = vec3_cross( binorm, tang ); tc->colmesh->triangles[tri_i] = ctri_new(a, c, b, norm); tri_i++; tc->colmesh->triangles[tri_i] = ctri_new(a, d, c, norm); tri_i++; } tc->colmesh->bound = cmesh_bound(tc->colmesh); /* For some reason this is not working correctly */ cmesh_subdivide(tc->colmesh, 5); ter->chunks[i] = tc; }