/* virtual */ void perspective::do_changed(field::base& f) { TRACE("hugh::scene::object::camera::perspective::do_changed"); if ((&f == &viewport) || (&f == &fovy)) { viewport_type const& vp(viewport.get()); frustum_ = compute_frustum(vp, glm::vec2(frustum_.near, frustum_.far)); if (std::numeric_limits<glm::vec2>::infinity() == frustum_.far) { projection_ = glm::infinitePerspective(fovy.get(), vp.width / vp.height, frustum_.near); } else { projection_ = glm::perspectiveFov(fovy.get(), vp.width, vp.height, frustum_.near, frustum_.far); } } else { base::do_changed(f); } }
/* explicit */ base::base(matrix_type const& a, viewport_type const& b, glm::vec2 const& c) : object::base(), projection (*this, "projection", std::bind(&base::cb_get_projection, this), std::bind(&base::cb_set_projection, this, std::placeholders::_1)), frustum (*this, "frustum", std::bind(&base::cb_get_frustum, this), std::bind(&base::cb_set_frustum, this, std::placeholders::_1)), viewport (*this, "viewport", b), projection_ (a), frustum_ (compute_frustum(b, c)) { TRACE("hugh::scene::object::camera::base::base"); }
void render_voxel_world(float campos[3]) { int num_build_remaining; int distance; float x = campos[0], y = campos[1]; int qchunk_x, qchunk_y; int cam_x, cam_y; int i,j, rad; #ifdef SINGLE_THREADED_MESHBUILD num_build_remaining = 1; #else num_build_remaining = 0; #endif cam_x = (int) floor(x); cam_y = (int) floor(y); qchunk_x = C_MESH_CHUNK_X_FOR_WORLD_X(cam_x); qchunk_y = C_MESH_CHUNK_Y_FOR_WORLD_Y(cam_y); request_mesh_generation(qchunk_x, qchunk_y, cam_x, cam_y); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.5); stbglUseProgram(main_prog); setup_uniforms(campos); // set uniforms to default values inefficiently glActiveTextureARB(GL_TEXTURE2_ARB); stbglEnableVertexAttribArray(0); rad = view_distance >> MESH_CHUNK_SIZE_X_LOG2; view_dist_for_display = view_distance; { float lighting[2][3] = { { 0,0,0 }, { 0.75,0.75,0.65f } }; float bright = 32; lighting[0][0] = light_pos[0]; lighting[0][1] = light_pos[1]; lighting[0][2] = light_pos[2]; lighting[1][0] *= bright; lighting[1][1] *= bright; lighting[1][2] *= bright; stbglUniform3fv(stbgl_find_uniform(main_prog, "light_source"), 2, lighting[0]); } quads_rendered = 0; quads_considered = 0; chunk_storage_rendered = 0; chunk_storage_considered = 0; chunk_locations = 0; chunks_considered = 0; chunks_in_frustum = 0; compute_frustum(); for (distance = 0; distance <= rad; ++distance) { for (j=-distance; j <= distance; ++j) { for (i=-distance; i <= distance; ++i) { int cx = qchunk_x + i; int cy = qchunk_y + j; int slot_x = cx & (C_MESH_CHUNK_CACHE_X-1); int slot_y = cy & (C_MESH_CHUNK_CACHE_Y-1); mesh_chunk *mc = c_mesh_cache[slot_y][slot_x]; if (stb_max(abs(i),abs(j)) != distance) continue; if (i*i + j*j > rad*rad) continue; if (mc == NULL || mc->chunk_x != cx || mc->chunk_y != cy || mc->vbuf == 0) { float estimated_bounds[2][3]; if (num_build_remaining == 0) continue; estimated_bounds[0][0] = (float) ( cx << MESH_CHUNK_SIZE_X_LOG2); estimated_bounds[0][1] = (float) ( cy << MESH_CHUNK_SIZE_Y_LOG2); estimated_bounds[0][2] = (float) (0); estimated_bounds[1][0] = (float) ((cx+1) << MESH_CHUNK_SIZE_X_LOG2); estimated_bounds[1][1] = (float) ((cy+1) << MESH_CHUNK_SIZE_Y_LOG2); estimated_bounds[1][2] = (float) (255); if (!is_box_in_frustum(estimated_bounds[0], estimated_bounds[1])) continue; mc = build_mesh_chunk_for_coord(cx * C_MESH_CHUNK_CACHE_X, cy * C_MESH_CHUNK_CACHE_Y); --num_build_remaining; } ++chunk_locations; ++chunks_considered; quads_considered += mc->num_quads; chunk_storage_considered += mc->num_quads * 20; if (mc->num_quads) { if (is_box_in_frustum(mc->bounds[0], mc->bounds[1])) { // @TODO if in range, frustum cull stbglUniform3fv(stbgl_find_uniform(main_prog, "transform"), 3, mc->transform[0]); glBindBufferARB(GL_ARRAY_BUFFER_ARB, mc->vbuf); glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, 4, (void*) 0); glBindTexture(GL_TEXTURE_BUFFER_ARB, mc->fbuf_tex); glDrawArrays(GL_QUADS, 0, mc->num_quads*4); quads_rendered += mc->num_quads; ++chunks_in_frustum; chunk_storage_rendered += mc->num_quads * 20; } } } } } if (num_build_remaining) { for (j=-rad; j <= rad; ++j) { for (i=-rad; i <= rad; ++i) { int cx = qchunk_x + i; int cy = qchunk_y + j; int slot_x = cx & (C_MESH_CHUNK_CACHE_X-1); int slot_y = cy & (C_MESH_CHUNK_CACHE_Y-1); mesh_chunk *mc = c_mesh_cache[slot_y][slot_x]; if (mc->chunk_x != cx || mc->chunk_y != cy || mc->vbuf == 0) { mc = build_mesh_chunk_for_coord(cx * C_MESH_CHUNK_CACHE_X, cy * C_MESH_CHUNK_CACHE_Y); --num_build_remaining; if (num_build_remaining == 0) goto done; } } } done: ; } { built_mesh bm; while (get_next_built_mesh(&bm)) { if (!bm.mc->has_triangles) { // server: physics_process_mesh_chunk(bm.mc); // don't free the physics data below, because the above call copies them bm.mc->allocs = NULL; free_mesh_chunk(bm.mc); } else { //s_process_mesh_chunk(bm.mc); // client: upload_mesh(bm.mc, bm.vertex_build_buffer, bm.face_buffer); set_mesh_chunk_for_coord(bm.mc->chunk_x * MESH_CHUNK_SIZE_X, bm.mc->chunk_y * MESH_CHUNK_SIZE_Y, bm.mc); free(bm.face_buffer); free(bm.vertex_build_buffer); bm.mc = NULL; } } } chunk_storage_total = 0; for (j=0; j < C_MESH_CHUNK_CACHE_Y; ++j) for (i=0; i < C_MESH_CHUNK_CACHE_X; ++i) if (c_mesh_cache[j][i] != NULL && c_mesh_cache[j][i]->vbuf) chunk_storage_total += c_mesh_cache[j][i]->num_quads * 20; stbglDisableVertexAttribArray(0); glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); glActiveTextureARB(GL_TEXTURE0_ARB); stbglUseProgram(0); }