static ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, int op) { ast_expression *swapped = NULL; /* using this as bool */ ast_value *load; if (!ast_istype(right, ast_value) || !fold_can_1((load = (ast_value*)right))) { swapped = left; left = right; right = swapped; } if (!ast_istype(right, ast_value) || !fold_can_1((load = (ast_value*)right))) return NULL; switch (op) { case INSTR_DIV_F: if (swapped) return NULL; case INSTR_MUL_F: if (fold_immvalue_float(load) == 1.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; } break; case INSTR_SUB_F: if (swapped) return NULL; case INSTR_ADD_F: if (fold_immvalue_float(load) == 0.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; } break; case INSTR_MUL_V: if (vec3_cmp(fold_immvalue_vector(load), vec3_create(1, 1, 1))) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; } break; case INSTR_SUB_V: if (swapped) return NULL; case INSTR_ADD_V: if (vec3_cmp(fold_immvalue_vector(load), vec3_create(0, 0, 0))) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; } break; } return NULL; }
vec3 vec3_cross(vec3 a, vec3 b) { return vec3_create ( a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x ); }
fold_t *fold_init(parser_t *parser) { fold_t *fold = (fold_t*)mem_a(sizeof(fold_t)); fold->parser = parser; fold->imm_float = NULL; fold->imm_vector = NULL; fold->imm_string = NULL; fold->imm_string_untranslate = util_htnew(FOLD_STRING_UNTRANSLATE_HTSIZE); fold->imm_string_dotranslate = util_htnew(FOLD_STRING_DOTRANSLATE_HTSIZE); /* * prime the tables with common constant values at constant * locations. */ (void)fold_constgen_float (fold, 0.0f); (void)fold_constgen_float (fold, 1.0f); (void)fold_constgen_float (fold, -1.0f); (void)fold_constgen_float (fold, 2.0f); (void)fold_constgen_vector(fold, vec3_create(0.0f, 0.0f, 0.0f)); (void)fold_constgen_vector(fold, vec3_create(-1.0f, -1.0f, -1.0f)); return fold; }
vec3 *vec3_get_surface_normal(const vec3 *v1, const vec3 *v2, const vec3 *v3) { vec3 u, v; u.x = v2->x - v1->x; u.y = v2->y - v1->y; u.z = v2->z - v1->z; v.x = v3->x - v1->x; v.y = v3->y - v1->y; v.z = v3->z - v1->z; vec3 *normal = vec3_create(0, 0, 0); normal->x = u.x * v.x - u.z * v.z; normal->y = u.z * v.x - u.x * v.z; normal->z = u.x * v.y - u.y * v.x; vec3_norm(normal); return normal; }
vec3 vec3_scale(vec3 A, double s){ return vec3_create(A.x * s, A.y * s, A.z * s); }
vec3 vec3_diff(vec3 A, vec3 B){ return vec3_create(A.x - B.x, A.y - B.y, A.z - B.z); }
vec3 vec3_add(vec3 A, vec3 B) { return vec3_create ( A.x+B.x, A.y + B.y, A.z + B.z ); }
void update_game(Game* G) { float delta_time = (float)get_delta_time(G->timer); int ii; _control_camera(G, delta_time); set_view_matrix(G->graphics, mat4_inverse(transform_get_matrix(G->camera))); /* Dynamic Lights */ if(G->dynamic_lights) { G->sun_light.position = mat3_mul_vector(vec3_create(5,5,0), mat3_rotation_y((float)get_running_time(G->timer)*0.5f)); G->light_transform += delta_time; for(ii=0;ii<NUM_LIGHTS;++ii) { if(ii % 2) G->lights[ii].position.z = sinf((G->light_transform + ii * 1.0f)/2.0f) * 10.0f; else G->lights[ii].position.x = sinf((G->light_transform + ii * 1.0f)/2.0f) * 10.0f; } } add_light(G->graphics, G->sun_light); for(ii=0;ii<NUM_LIGHTS;++ii) { add_light(G->graphics, G->lights[ii]); } render_scene(G->scene, G->graphics); G->tap_timer += delta_time; /* Calculate FPS */ G->fps_time += delta_time; G->fps_count++; if(G->fps_time >= 1.0f) { G->fps = G->fps_count/G->fps_time; system_log("FPS: %f\n", G->fps); G->fps_time -= 1.0f; G->fps_count = 0; } { int width, height; float scale = 50.0f; float x = -G->width/2.0f; float y = G->height/2.0f-scale; char buffer[256] = {0}; // FPS sprintf(buffer, "FPS: %.2f", G->fps); add_string(G->ui, x, y, scale, buffer); y -= scale; // Renderer switch(renderer_type(G->graphics)) { case kForward: add_string(G->ui, x, y, scale, "Forward renderer"); break; case kLightPrePass: add_string(G->ui, x, y, scale, "Deferred Lighting"); break; case kDeferred: add_string(G->ui, x, y, scale, "Deferred Shading"); break; default: assert(!"Invalid renderer"); break; } y -= scale; // Resolution graphics_size(G->graphics, &width, &height); sprintf(buffer, "%dx%d", width, height); add_string(G->ui, x, y, scale, buffer); } }
/* External functions */ Game* create_game(void) { int ii; Game* G = (Game*)calloc(1, sizeof(Game)); G->timer = create_timer(); G->graphics = create_graphics(); G->ui = create_ui(G->graphics); /* Set up camera */ G->camera = transform_zero; G->camera.orientation = quat_from_euler(0, -0.75f * kPi, 0); G->camera.position.x = 4.0f; G->camera.position.y = 2; G->camera.position.z = 7.5f; /* Load scene */ reset_timer(G->timer); G->scene = create_scene("lightHouse.obj"); G->sun_light.position = vec3_create(-4.0f, 5.0f, 2.0f); G->sun_light.color = vec3_create(1, 1, 1); G->sun_light.size = 35.0f; G->lights[0].color = vec3_create(1, 0, 0); G->lights[1].color = vec3_create(1, 1, 0); G->lights[2].color = vec3_create(0, 1, 0); G->lights[3].color = vec3_create(1, 0, 1); G->lights[4].color = vec3_create(0, 0, 1); G->lights[5].color = vec3_create(0, 1, 1); for(ii=0;ii<NUM_LIGHTS;++ii) { float x = (20.0f/NUM_LIGHTS) * ii - 8.0f; G->lights[ii].color = vec3_create(_rand_float(), _rand_float(), _rand_float()); G->lights[ii].color = vec3_normalize(G->lights[ii].color); if(ii % 2) G->lights[ii].position = vec3_create(x, _rand_float()*3 + 2.0f, 0.0f); else G->lights[ii].position = vec3_create(0.0f, _rand_float()*3 + 2.0f, x); G->lights[ii].size = 5; } get_model(G->scene, 3)->material->specular_color = vec3_create(0.5f, 0.5f, 0.5f); get_model(G->scene, 3)->material->specular_coefficient = 1.0f; G->dynamic_lights = 1; reset_timer(G->timer); return G; }
vec3 *vec3_clone(vec3 *vec) { return vec3_create(vec->x, vec->y, vec->z); }
int main(void) { _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); int width = 800, height = 600; GLFWwindow* window; glfwSetErrorCallback(error_callback); if (!glfwInit()) exit(EXIT_FAILURE); window = glfwCreateWindow(width, height, "cpu-voxels", NULL, NULL); if (!window) { glfwTerminate(); return 1; } glfwMakeContextCurrent(window); glfwSwapInterval(0); glfwSetKeyCallback(window, key_callback); glfwSetMouseButtonCallback(window, mouse_button_callback); glfwSetCursorPosCallback(window, mouse_move_callback); glfwSetKeyCallback(window, key_callback); vec3 eye = vec3_create(0.0f, 0.0f, VOXEL_BRICK_SIZE * 4); vec3 center = vec3f(0.0f); vec3 up = vec3_create(0.0, 1.0, 0.0 ); orbit_camera_init(eye, center, up); // TODO: handle resize int dw, dh; glfwGetFramebufferSize(window, &dw, &dh); int stride = 3; int total = dw*dh*stride; uint8_t *data = malloc(total); vec3 ro; //, rd; mat4 m4inverted, view; mat4 projection; mat4_perspective( projection, M_PI/4.0, (float)width/(float)height, 0.1, 1000.0 ); GLuint texture[1]; #ifdef ENABLE_THREADS screen_area areas[TOTAL_THREADS]; threadpool thpool = thpool_init(TOTAL_THREADS); #else screen_area areas[1]; #endif glGenTextures(1, texture); float start = glfwGetTime(); int fps = 0; voxel_brick my_first_brick = voxel_brick_create(); // TODO: make this work when the brick lb corner is not oriented at 0,0,0 voxel_brick_position(my_first_brick, vec3f(0.0f)); voxel_brick_fill(my_first_brick, &brick_fill); while (!glfwWindowShouldClose(window)) { if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { orbit_camera_rotate(0, 0, -.1, 0); } if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { orbit_camera_rotate(0, 0, .1, 0); } if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { orbit_camera_rotate(0, 0, 0, .1); } if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { orbit_camera_rotate(0, 0, 0, -.1); } glfwGetFramebufferSize(window, &width, &height); float now = glfwGetTime(); if (now - start > 1) { unsigned long long total_rays = (fps * width * height); printf("fps: %i (%f Mrays/s)@%ix%i - %i threads\n", fps, total_rays/1000000.0, width, height, TOTAL_THREADS); start = now; fps = 0; } fps++; orbit_camera_view(view); ro = mat4_get_eye(view); mat4_mul(m4inverted, projection, view); mat4_invert(m4inverted, m4inverted); // compute 3 points so that we can interpolate instead of unprojecting // on every point vec3 rda, rdb, planeYPosition, dcol, drow; vec3 t0 = vec3_create(0, 0, 0), tx = vec3_create(1, 0, 0), ty = vec3_create(0, 1, 0); vec4 viewport = { 0, 0, width, height }; rda = orbit_camera_unproject(t0, viewport, m4inverted); rdb = orbit_camera_unproject(tx, viewport, m4inverted); planeYPosition = orbit_camera_unproject(ty, viewport, m4inverted); dcol = planeYPosition - rda; drow = rdb - rda; int i=0, bh = height; #ifdef ENABLE_THREADS bh = (height/TOTAL_THREADS); for (i; i<TOTAL_THREADS; i++) { #endif areas[i].dcol = dcol; areas[i].drow = drow; areas[i].pos = planeYPosition; areas[i].ro = ro; areas[i].x = 0; areas[i].y = i*bh; areas[i].width = width; areas[i].height = areas[i].y + (int)(bh); areas[i].screen_height = (int)(height); areas[i].stride = stride; areas[i].data = data; areas[i].render_id = i; areas[i].brick = my_first_brick; #ifdef ENABLE_THREADS thpool_add_work(thpool, (void *)render_screen_area, (void *)(&areas[i])); } thpool_wait(thpool); #else render_screen_area((void *)(&areas[i])); #endif #ifdef RENDER glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_CULL_FACE); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glScalef(1.0f, -1.0f, 1.0f); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f( -1, -1); glTexCoord2f(1.0f, 0.0f); glVertex2f( 1, -1); glTexCoord2f(1.0f, 1.0f); glVertex2f( 1, 1); glTexCoord2f(0.0f, 1.0f); glVertex2f( -1, 1); glEnd(); glfwSwapBuffers(window); glDeleteTextures(1, &texture[0]); #endif glfwPollEvents(); } glfwDestroyWindow(window); glfwTerminate(); exit(EXIT_SUCCESS); }