void client_view_physics(objid oid, player_controls *con, float dt) { object *o = &obj[oid]; if (con->flying) { view_x_vel *= (float) pow(0.75, dt); view_z_vel *= (float) pow(0.75, dt); view_x_vel += (pending_view_x - view_x_vel)*dt*60; view_z_vel += (pending_view_z - view_z_vel)*dt*60; pending_view_x -= view_x_vel * dt; pending_view_z -= view_z_vel * dt; o->ang.x += view_x_vel * dt; o->ang.z += view_z_vel * dt; o->ang.x = stb_clamp(o->ang.x, -90, 90); o->ang.z = (float) fmod(o->ang.z, 360); } else { o->ang.x += pending_view_x * 0.25f; o->ang.z += pending_view_z * 0.50f; pending_view_x = 0; pending_view_z = 0; o->ang.x = stb_clamp(o->ang.x, -90, 90); o->ang.z = (float) fmod(o->ang.z, 360); } }
void write_floats(FILE *g, int len, float *left, float *right) { const float scale = 32768; int j; for (j=0; j < len; ++j) { int16 x,y; x = (int) stb_clamp((int) (scale * left[j]), -32768, 32767); y = (int) stb_clamp((int) (scale * right[j]), -32768, 32767); fwrite(&x, 2, 1, g); fwrite(&y, 2, 1, g); } }
float compute_height_field(int x, int y) { float ht = AVG_GROUND; #if 1 float weight=0; int o; weight = (float) stb_linear_remap(stb_perlin_noise3(x/256.0f,y/256.0f,100,256,256,256), -1.5, 1.5, -4.0f, 5.0f); weight = stb_clamp(weight,0,1); for (o=0; o < 8; ++o) { float scale = (float) (1 << o); float ns = stb_perlin_noise3(x/scale, y/scale, o*2.0f, 256,256,256), heavier; float sign = (ns < 0 ? -1.0f : 1.0f); ns = (float) fabs(ns); heavier = ns*ns*ns*ns*4; ht += scale/2 * stb_lerp(weight, ns, heavier); } #else if (x >= 10 && x <= 50 && y >= 30 && y <= 70) { ht += x; } if (x >= 110 && x <= 150 && y >= 30 && y <= 70) { ht += y; } #endif return ht; }
gen_chunk *generate_chunk(int x, int y) { int z_seg; int i,j,z; int ground_top = 0; gen_chunk *gc = malloc(sizeof(*gc)); float height_field[GEN_CHUNK_SIZE_Y+2][GEN_CHUNK_SIZE_X+2]; int height_field_int[GEN_CHUNK_SIZE_Y+2][GEN_CHUNK_SIZE_X+2]; int corner_tex[2][2], corner_weight[2][2]; int block_type[GEN_CHUNK_SIZE_Y][GEN_CHUNK_SIZE_X]; for (j=-1; j <= GEN_CHUNK_SIZE_Y; ++j) for (i=-1; i <= GEN_CHUNK_SIZE_X; ++i) { float ht = compute_height_field(x+i,y+j); height_field[j+1][i+1] = ht; height_field_int[j+1][i+1] = (int) height_field[j+1][i+1]; ground_top = stb_max(ground_top, height_field_int[j+1][i+1]); } memset(gc->non_empty, 0, sizeof(gc->non_empty)); memset(gc->non_empty, 1, (ground_top+Z_SEGMENT_SIZE-1)>>Z_SEGMENT_SIZE_LOG2); for (j=0; j < 2; ++j) { for (i=0; i < 2; ++i) { unsigned int val = fast_noise(x+i*GEN_CHUNK_SIZE_X,y+j*GEN_CHUNK_SIZE_Y,3,777); val = (val*16)/65536; corner_tex[j][i] = val; corner_weight[j][i] = 32+(fast_noise(x+i*GEN_CHUNK_SIZE_X,y+j*GEN_CHUNK_SIZE_Y,3,666)&255); } } for (j=0; j < GEN_CHUNK_SIZE_Y; ++j) { for (i=0; i < GEN_CHUNK_SIZE_X; ++i) { int best=0, best_w=0, w; w = corner_weight[0][0]*(GEN_CHUNK_SIZE_X+i)*(GEN_CHUNK_SIZE_Y-j); if (w >= best_w) { best_w = w; best = corner_tex[0][0]; } w = corner_weight[0][1]*(i)*(GEN_CHUNK_SIZE_Y-j); if (w >= best_w) { best_w = w; best = corner_tex[0][1]; } w = corner_weight[1][0]*(GEN_CHUNK_SIZE_X-i)*(j); if (w >= best_w) { best_w = w; best = corner_tex[1][0]; } w = corner_weight[1][1]*(i)*(j); if (w >= best_w) { best_w = w; best = corner_tex[1][1]; } block_type[j][i] = (BT_solid + best); } } for (z_seg=0; z_seg < NUM_Z_SEGMENTS; ++z_seg) { int z0 = z_seg * Z_SEGMENT_SIZE; gen_chunk_partial *gcp = &gc->partial[z_seg]; for (j=0; j < GEN_CHUNK_SIZE_Y; ++j) { for (i=0; i < GEN_CHUNK_SIZE_X; ++i) { int ht = height_field_int[j+1][i+1]; int z_limit = stb_clamp(ht-z0, 0, Z_SEGMENT_SIZE); assert(z_limit >= 0 && Z_SEGMENT_SIZE - z_limit >= 0); memset(&gcp->block[j][i][ 0 ], block_type[j][i], z_limit); memset(&gcp->block[j][i][z_limit], BT_empty , Z_SEGMENT_SIZE - z_limit); } } } // compute lighting for every block by weighted average of neighbors // loop through every partial chunk separately for (z_seg=0; (z_seg < NUM_Z_SEGMENTS); ++z_seg) { gen_chunk_partial *gcp = &gc->partial[z_seg]; int z0 = z_seg * Z_SEGMENT_SIZE; int z_limit; z_limit = Z_SEGMENT_SIZE; if (z_limit + z0 > ground_top+1) z_limit = ground_top+1 - z0; if (z_limit < 0) break; for (j=0; j < GEN_CHUNK_SIZE_Y; ++j) { for (i=0; i < GEN_CHUNK_SIZE_X; ++i) { unsigned char *lt = &gcp->lighting[j][i][0]; for (z=0; z < z_limit; ++z) { int light; if (z0+z < height_field_int[j+1][i+1]) { light = 0; } else { int m,n; light = 0; for (m=-1; m <= 1; ++m) { for (n=-1; n <= 1; ++n) { int ht = height_field_int[j+1+m][i+1+n]; int val = z0+z-ht+2; if (val < 0) val=0; if (val > 3) val = 3; light += val; } } // 27 ? light += 4; light = light << 3; } *lt++ = light; } for (; z < Z_SEGMENT_SIZE; ++z) *lt++ = 255; } } } for (; z_seg < NUM_Z_SEGMENTS; ++z_seg) { gen_chunk_partial *gcp = &gc->partial[z_seg]; for (j=0; j < GEN_CHUNK_SIZE_Y; ++j) for (i=0; i < GEN_CHUNK_SIZE_X; ++i) { unsigned char *lt = &gcp->lighting[j][i][0]; for (z=0; z < Z_SEGMENT_SIZE; ++z) *lt++ = 255; } } gc->ref_count = 0; return gc; }