GraphicStore::GraphicStore(CL_GraphicContext &gc) : shader_bumpmap(gc) { #ifdef _DEBUG //struct aiLogStream stream; //stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); //aiAttachLogStream(&stream); //stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); //aiAttachLogStream(&stream); #endif store = aiCreatePropertyStore(); aiSetImportPropertyFloat(store, AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,89.53f); }
GraphicStore::GraphicStore(GraphicContext &gc) : shader_color(gc) { #ifdef _DEBUG //struct aiLogStream stream; //stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); //aiAttachLogStream(&stream); //stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); //aiAttachLogStream(&stream); #endif #if defined(I_LOVE_ASSIMP_AND_PRECOMPILED_IT) store = aiCreatePropertyStore(); aiSetImportPropertyFloat(store, AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,89.53f); #endif }
// The start of the Application int App::start(const std::vector<CL_String> &args) { quit = false; CL_GL1WindowDescription desc; desc.set_title("ClanLib Object 3D Example"); desc.set_size(CL_Size(640, 480), true); desc.set_multisampling(4); desc.set_depth_size(16); CL_DisplayWindow window(desc); #ifdef _DEBUG //struct aiLogStream stream; //stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); //aiAttachLogStream(&stream); //stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); //aiAttachLogStream(&stream); #endif // Connect the Window close event CL_Slot slot_quit = window.sig_window_close().connect(this, &App::on_window_close); // Connect a keyboard handler to on_key_up() CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &App::on_input_up); // Get the graphic context CL_GraphicContext gc = window.get_gc(); #ifdef USE_OPENGL_1 CL_GraphicContext_GL1 gc_gl1 = gc; #endif // Prepare the display gc.set_map_mode(cl_user_projection); CL_PolygonRasterizer polygon_rasterizer; polygon_rasterizer.set_culled(true); polygon_rasterizer.set_face_cull_mode(cl_cull_back); polygon_rasterizer.set_front_face(cl_face_side_clockwise); gc.set_polygon_rasterizer(polygon_rasterizer); CL_BufferControl buffer_control; buffer_control.enable_depth_test(true); buffer_control.set_depth_compare_function(cl_comparefunc_lequal); buffer_control.enable_depth_write(true); gc.set_buffer_control(buffer_control); #ifdef USE_OPENGL_1 // Set the lights CL_LightModel_GL1 light_model; light_model.enable_lighting(true); light_model.set_flat_shading(false); light_model.set_scene_ambient_light(CL_Colorf(0.2f, 0.2f, 0.2f, 1.0f)); gc_gl1.set_light_model(light_model); CL_LightSource_GL1 light_distant; light_distant.set_spot_cutoff(180.0f); light_distant.set_diffuse_intensity(CL_Colorf(1.0f, 1.0f, 1.0f, 1.0f)); light_distant.set_position(CL_Vec4f(0.0f, -2.0f, 30.0f, 0.0f).normalize3()); gc_gl1.set_light(0, light_distant); cl1Enable(GL_NORMALIZE); #endif #ifdef USE_OPENGL_2 Shader shader(gc); #endif // Create the objects aiSetImportPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,89.53f); const struct aiScene* scene_teapot = aiImportFile("../Clan3D/Resources/teapot.dae",aiProcessPreset_TargetRealtime_MaxQuality); if (!scene_teapot) throw CL_Exception("Cannot load the teapot model"); const struct aiScene* scene_clanlib = aiImportFile("../Clan3D/Resources/clanlib.dae",aiProcessPreset_TargetRealtime_MaxQuality); if (!scene_clanlib) throw CL_Exception("Cannot load the clanlib model"); const struct aiScene* scene_tuxball = aiImportFile("../Clan3D/Resources/tux_ball.dae",aiProcessPreset_TargetRealtime_MaxQuality | aiProcess_FlipUVs); if (!scene_tuxball) throw CL_Exception("Cannot load the tux ball model"); // Load the texture CL_Texture tux(gc, "../Clan3D/Resources/tux.png"); float angle = 0.0f; // Run until someone presses escape while (!quit) { CL_Mat4f perp = CL_Mat4f::perspective(45.0f, ((float) gc.get_width()) / ((float) gc.get_height()), 0.1f, 1000.0f); gc.set_projection(perp); gc.clear(CL_Colorf::black); gc.clear_depth(1.0f); angle += 1.0f; if (angle >= 360.0f) angle -= 360.0f; #ifdef USE_OPENGL_2 shader.Set(gc); shader.Use(gc); #else gc.set_program_object(cl_program_color_only); #endif CL_PrimitivesArray prim_array(gc); gc.set_modelview(CL_Mat4f::identity()); gc.mult_scale(1.0f,1.0f, -1.0f); // So +'ve Z goes into the screen gc.mult_translate(0.0f, 0.0f, 2.0f); gc.mult_rotate(CL_Angle(angle, cl_degrees), 0.0f, 1.0f, 0.0f, false); gc.push_modelview(); recursive_render(gc, scene_teapot, scene_teapot->mRootNode, false); gc.pop_modelview(); gc.push_modelview(); gc.mult_scale(0.5f, 0.5f, 0.5f); gc.mult_translate(0.0f, -0.5f, 0.0f); recursive_render(gc, scene_clanlib, scene_clanlib->mRootNode, false); gc.pop_modelview(); #ifdef USE_OPENGL_2 shader.Set(gc, 0); shader.Use(gc); #else gc.set_program_object(cl_program_single_texture); #endif gc.set_texture(0, tux); gc.set_modelview(CL_Mat4f::identity()); gc.mult_scale(1.0f,1.0f, -1.0f); // So +'ve Z goes into the screen gc.mult_translate(0.7f, 0.5f, 2.0f); gc.mult_scale(0.05f, 0.05f, 0.05f); gc.mult_rotate(CL_Angle(angle * 4.0f, cl_degrees), 0.0f, 1.0f, 0.0f, false); recursive_render(gc, scene_tuxball, scene_tuxball->mRootNode, true); gc.reset_texture(0); gc.reset_program_object(); // Flip the display, showing on the screen what we have drawed // since last call to flip() window.flip(1); // This call processes user input and other events CL_KeepAlive::process(); } aiReleaseImport(scene_tuxball); aiReleaseImport(scene_clanlib); aiReleaseImport(scene_teapot); aiDetachAllLogStreams(); return 0; }
bool opMeshBaker::LoadAndBake(const char* input_filename, const char* output_filename) { aiSetImportPropertyFloat("AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE", 80.0f); aiSetImportPropertyInteger("AI_CONFIG_PP_RVC_FLAGS", aiComponent_NORMALS); // throw away normals (generate them) /* generate a mesh from the input file: Calculate tangents and bitangents Triangulate Weld vertices together Sort by primitive type Generate smooth normals Fix infacing normals Generate UV coords optimize the mesh */ const aiScene* scene = aiImportFile(input_filename, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_JoinIdenticalVertices | aiProcess_SortByPType | aiProcess_GenSmoothNormals | aiProcess_FixInfacingNormals | aiProcess_GenUVCoords | aiProcess_ConvertToLeftHanded | aiProcess_OptimizeMeshes); if(scene == NULL) { palPrintf("Could not open understand input file: %s\n", input_filename); return false; } palPrintf("Baking %s to %s\n", input_filename, output_filename); // we only support 1:1 mapping between input file meshes and output file meshes palAssert(scene->mNumMeshes == 1); aiMesh* mesh = scene->mMeshes[0]; // we expect faces palAssert(mesh->HasFaces() == true); // we expect vertex positions palAssert(mesh->HasPositions() == true); //printf("Has vertex positions.\n"); // we expect normals palAssert(mesh->HasNormals() == true); //printf("Has vertex normal.\n"); // we only support triangular meshes palAssert(mesh->mPrimitiveTypes == aiPrimitiveType_TRIANGLE); palFile baked; int r; r = baked.OpenForWritingTruncate(output_filename); if (r != 0) { palPrintf("Could not open output file: %s\n", output_filename); return false; } palArray<opBakedMeshArrayHeader> mesh_arrays; mesh_arrays.SetAllocator(g_DefaultHeapAllocator); palArray<void*> mesh_arrays_data; mesh_arrays_data.SetAllocator(g_DefaultHeapAllocator); palArray<opBakedMeshAttributeHeader> mesh_attributes; mesh_attributes.SetAllocator(g_DefaultHeapAllocator); opBakedMeshArrayHeader mesh_array; // index array mesh_array.array_type = OP_BAKED_MESH_INDEX_ARRAY; // pack index data tightly uint32_t num_indices = mesh->mNumFaces * 3; void* index_array_data = NULL; if (num_indices < 0xffff) { mesh_array.index_type = kOpRenderDeviceFormatUintR16; mesh_array.length_in_bytes = num_indices * sizeof(uint16_t); uint16_t* indices = (uint16_t*)g_DefaultHeapAllocator->Allocate(mesh_array.length_in_bytes); palAssert(indices); index_array_data = indices; for (unsigned int i = 0; i < mesh->mNumFaces; i++) { *indices = mesh->mFaces[i].mIndices[0]; indices++; *indices = mesh->mFaces[i].mIndices[1]; indices++; *indices = mesh->mFaces[i].mIndices[2]; indices++; } } else { mesh_array.index_type = kOpRenderDeviceFormatUintR32; mesh_array.length_in_bytes = num_indices * sizeof(uint32_t); uint32_t* indices = (uint32_t*)g_DefaultHeapAllocator->Allocate(mesh_array.length_in_bytes); palAssert(indices); index_array_data = indices; for (unsigned int i = 0; i < mesh->mNumFaces; i++) { *indices = mesh->mFaces[i].mIndices[0]; indices++; *indices = mesh->mFaces[i].mIndices[1]; indices++; *indices = mesh->mFaces[i].mIndices[2]; indices++; } } printf("Indexed triangle mesh: %d triangles (%d bytes in index data)\n", num_indices/3, mesh_array.length_in_bytes); mesh_arrays_data.push_back(index_array_data); mesh_arrays.push_back(mesh_array); // pack into single interleaved array { uint32_t offset = 0; opBakedMeshAttributeHeader mesh_component; // position mesh_component.attribute_type = OP_BAKED_MESH_ATTRIBUTE_VERTICES; mesh_component.element_type = kOpRenderDeviceFormatFloat32x3; mesh_component.offset_in_bytes = 0; mesh_component.array_index = 1; mesh_attributes.push_back(mesh_component); offset += 3 * sizeof(float); // normals mesh_component.attribute_type = OP_BAKED_MESH_ATTRIBUTE_NORMALS; mesh_component.element_type = kOpRenderDeviceFormatFloat32x3; mesh_component.offset_in_bytes = offset; mesh_component.array_index = 1; mesh_attributes.push_back(mesh_component); offset += 3 * sizeof(float); if (mesh->HasTangentsAndBitangents()) { // tangents mesh_component.attribute_type = OP_BAKED_MESH_ATTRIBUTE_TANGENTS; mesh_component.element_type = kOpRenderDeviceFormatFloat32x3; mesh_component.offset_in_bytes = offset; mesh_component.array_index = 1; mesh_attributes.push_back(mesh_component); offset += 3 * sizeof(float); // bitangents mesh_component.attribute_type = OP_BAKED_MESH_ATTRIBUTE_BITANGENTS; mesh_component.element_type = kOpRenderDeviceFormatFloat32x3; mesh_component.offset_in_bytes = offset; mesh_component.array_index = 1; mesh_attributes.push_back(mesh_component); offset += 3 * sizeof(float); printf("Has vertex tangents and bitangents.\n"); } // texture coordinates 0..3 for (unsigned int i = 0; i < mesh->GetNumUVChannels(); i++) { mesh_component.attribute_type = (opBakedMeshAttributeType)(OP_BAKED_MESH_ATTRIBUTE_TEXCOORDS0 + i); mesh_component.element_type = TextureElementType(mesh->mNumUVComponents[i]); mesh_component.offset_in_bytes = offset; mesh_component.array_index = 1; printf("Has UV channel %d (%d)\n", i, mesh->mNumUVComponents[i]); mesh_attributes.push_back(mesh_component); offset += mesh->mNumUVComponents[i] * sizeof(float); } // fill in the stride between vertices for (int i = 0; i < mesh_attributes.GetSize(); i++) { mesh_attributes[i].stride_in_bytes = offset; } mesh_array.array_type = OP_BAKED_MESH_VERTEX_ARRAY; mesh_array.length_in_bytes = mesh->mNumVertices * offset; printf("%d vertices (%d bytes in vertex data)\n", mesh->mNumVertices, mesh_array.length_in_bytes); void* vertex_array_data = g_DefaultHeapAllocator->Allocate(mesh_array.length_in_bytes); float* vertex_array_data_f = (float*)vertex_array_data; for (unsigned int i = 0; i < mesh->mNumVertices; i++) { // positions *vertex_array_data_f = mesh->mVertices[i].x; vertex_array_data_f++; *vertex_array_data_f = mesh->mVertices[i].y; vertex_array_data_f++; *vertex_array_data_f = mesh->mVertices[i].z; vertex_array_data_f++; // normals *vertex_array_data_f = mesh->mNormals[i].x; vertex_array_data_f++; *vertex_array_data_f = mesh->mNormals[i].y; vertex_array_data_f++; *vertex_array_data_f = mesh->mNormals[i].z; vertex_array_data_f++; if (mesh->HasTangentsAndBitangents()) { // tangents *vertex_array_data_f = mesh->mTangents[i].x; vertex_array_data_f++; *vertex_array_data_f = mesh->mTangents[i].y; vertex_array_data_f++; *vertex_array_data_f = mesh->mTangents[i].z; vertex_array_data_f++; // bitangents *vertex_array_data_f = mesh->mBitangents[i].x; vertex_array_data_f++; *vertex_array_data_f = mesh->mBitangents[i].y; vertex_array_data_f++; *vertex_array_data_f = mesh->mBitangents[i].z; vertex_array_data_f++; } // texture channels for (unsigned int tc = 0; tc < mesh->GetNumUVChannels(); tc++) { // texture coordinates for (unsigned int st = 0; st < mesh->mNumUVComponents[tc]; st++) { //printf("tex[%d] = %f\n", st, mesh->mTextureCoords[tc][i][st]); *vertex_array_data_f = mesh->mTextureCoords[tc][i][st]; vertex_array_data_f++; } } } // push data back into arrays mesh_arrays_data.push_back(vertex_array_data); mesh_arrays.push_back(mesh_array); } // write data to disk opBakedMeshHeader header; header.magic = OP_BAKED_MESH_FILE_MAGIC; header.attribute_count = mesh_attributes.GetSize(); header.attribute_offset = sizeof(header); header.array_count = mesh_arrays.GetSize(); header.array_offset = sizeof(header) + sizeof(opBakedMeshAttributeHeader) * mesh_attributes.GetSize(); baked.Write(&header, sizeof(header)); for (int i = 0; i < mesh_attributes.GetSize();i++) { opBakedMeshAttributeHeader& component_attribute = mesh_attributes[i]; baked.Write(&component_attribute, sizeof(component_attribute)); } uint32_t array_offset = sizeof(header); array_offset += sizeof(opBakedMeshAttributeHeader) * mesh_attributes.GetSize(); array_offset += sizeof(opBakedMeshArrayHeader) * mesh_arrays.GetSize(); for (int i = 0; i < mesh_arrays.GetSize(); i++) { opBakedMeshArrayHeader& array_header = mesh_arrays[i]; array_header.offset_in_bytes = array_offset; baked.Write(&array_header, sizeof(array_header)); array_offset += array_header.length_in_bytes; } for (int i = 0; i < mesh_arrays.GetSize(); i++) { baked.Write(mesh_arrays_data[i], mesh_arrays[i].length_in_bytes); g_DefaultHeapAllocator->Deallocate(mesh_arrays_data[i]); } baked.Close(); aiReleaseImport(scene); return true; }
// The start of the Application int App::start(const std::vector<CL_String> &args) { quit = false; CL_OpenGLWindowDescription desc; desc.set_title("ClanLib Shadow Example"); desc.set_size(CL_Size(640, 640), true); desc.set_multisampling(4); desc.set_depth_size(16); CL_DisplayWindow window(desc); #ifdef _DEBUG //struct aiLogStream stream; //stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL); //aiAttachLogStream(&stream); //stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt"); //aiAttachLogStream(&stream); #endif aiSetImportPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,89.53f); // Connect the Window close event CL_Slot slot_quit = window.sig_window_close().connect(this, &App::on_window_close); // Connect a keyboard handler to on_key_up() CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &App::on_input_up); // Get the graphic context CL_GraphicContext gc = window.get_gc(); GraphicStore graphic_store(gc); scene.gs = &graphic_store; // Prepare the display gc.set_map_mode(cl_user_projection); CL_PolygonRasterizer polygon_rasterizer; polygon_rasterizer.set_culled(true); polygon_rasterizer.set_face_cull_mode(cl_cull_back); polygon_rasterizer.set_front_face(cl_face_side_clockwise); gc.set_polygon_rasterizer(polygon_rasterizer); create_scene(gc); CL_FrameBuffer framebuffer(gc); CL_Texture new_depth_texture(gc, CL_Size(1024, 1024), cl_depth_component); new_depth_texture.set_wrap_mode(cl_wrap_clamp_to_edge, cl_wrap_clamp_to_edge, cl_wrap_clamp_to_edge); framebuffer.attach_depth_buffer(new_depth_texture); scene.gs->texture_shadow = new_depth_texture; camera_angle = 0.0f; CL_Font font(gc, "tahoma", 24); FramerateCounter framerate_counter; unsigned int time_last = CL_System::get_time(); // Run until someone presses escape while (!quit) { framerate_counter.frame_shown(); unsigned int time_now = CL_System::get_time(); time_delta = time_now - time_last; time_last = time_now; rotate_teapot(); control_camera(); update_light(gc); calculate_matricies(gc); render_from_lightsource(gc, framebuffer); render_from_camera(gc, framebuffer); gc.set_modelview(CL_Mat4f::identity()); gc.set_map_mode(cl_map_2d_upper_left); CL_String fps(cl_format("%1 fps", framerate_counter.get_framerate())); font.draw_text(gc, 16-2, gc.get_height()-16-2, fps, CL_Colorf(0.0f, 0.0f, 0.0f, 1.0f)); font.draw_text(gc, 16, gc.get_height()-16-2, fps, CL_Colorf(1.0f, 1.0f, 1.0f, 1.0f)); // Use flip(1) to lock the fps window.flip(0); // This call processes user input and other events CL_KeepAlive::process(); } aiDetachAllLogStreams(); return 0; }