Scene *readHeights(char* fn) { int width, height; unsigned char *height_map; height_map = readBMP(fn, width, height); if (!height_map) { fl_alert("Error loading height map\n"); return false; } Scene * ret = new Scene(); //TODO: customize mat Material * mat = new Material(); mat->kd = vec3f(1.0, 1.0, 1.0); //extract the points Trimesh * trimesh = new Trimesh(ret, mat, &ret->transformRoot); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { int pos = y * width + x; unsigned char pixel[3]; memcpy(pixel, height_map + pos * 3, 3); double height = double(pixel[0] + pixel[1] + pixel[2]) / 3 / 128; vec3f point(x, y, height); trimesh->addVertex(point); if (x > 0 && y > 0) { //link the points trimesh->addFace(pos, pos - 1, pos - 1 - width); trimesh->addFace(pos, pos - 1 - width, pos - width); } } } char *error; if (error = trimesh->doubleCheck()) throw ParseError(error); //add a trimesh ret->add(trimesh); //add a pointlight PointLight* point_light = new PointLight(ret, vec3f(width, height, 10), vec3f(1.0, 1.0, 1.0)); ret->add(point_light); //set the camerea //TODO: calculate the correct viewing distance; vec3f map_center((double)width / 2 - 0.5, (double)height / 2 - 0.5, 0.5); double camera_distance = (double)width + 3.0; vec3f camera_pos(0, -camera_distance, 2 * camera_distance); camera_pos += map_center; ret->getCamera()->setEye(camera_pos); ret->getCamera()->setLook((map_center - camera_pos).normalize(), vec3f(0, 0, 1).normalize()); return ret; }
Shape *PhysicsEntityComponentTemplate::TrimeshInfo::create(Entity *entity) { Engine *engine = entity->getWorld()->getEngine(); // Load trimesh data TrimeshData tridata; if (!tridata.init(engine->getDirectory() + "/Data/Graphics/" + file)) { return 0; } // Create shape Trimesh *trimesh = new Trimesh; if (!trimesh->init(tridata, 0.0f, false)) { delete trimesh; return 0; } return trimesh; }
void SceneLoader::ImportMesh(Scene& scene, const aiMesh* const mesh) { Trimesh* trimesh = new Trimesh(); for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { aiVector3D v = mesh->mVertices[i]; trimesh->AddVertex(glm::vec3(v[0], v[1], v[2])); } std::cout << "mNumVertices = " << mesh->mNumVertices << std::endl; if (NULL != mesh->mNormals) { for (uint32_t i = 0; i < mesh->mNumVertices; ++i) { aiVector3D n = mesh->mNormals[i]; trimesh->AddNormal(glm::vec3(n[0], n[1], n[2])); } } std::cout << "mNumFaces = " << mesh->mNumFaces << std::endl; for (uint32_t i = 0; i < mesh->mNumFaces; ++i) { aiFace f = mesh->mFaces[i]; if (3 == f.mNumIndices) { trimesh->AddFace(f.mIndices[0], f.mIndices[1], f.mIndices[2]); } } std::cout << "materials.size() = " << scene.material_list().materials.size() << std::endl; Material* mat = &scene.material_list().materials[mesh->mMaterialIndex]; trimesh->set_material(mat); if (NULL == mesh->mNormals) { trimesh->GenNormals(); } scene.AddSceneShape(static_cast<SceneShape*>(trimesh)); }
TEST(RayTracerTest, TurbineMeshTest) { SceneLoader& loader = SceneLoader::GetInstance(); std::string path = "../assets/blade.ply"; std::string status = ""; Scene scene; std::cout << "loading" << std::endl; bool success = loader.LoadScene(path, scene, status); EXPECT_TRUE(success); EXPECT_EQ("OK", status); std::cout << "done loading" << std::endl; int image_width = 1024; int image_height = 1024; glm::vec3 eye_pos = glm::vec3(-274.564f, -282.243f, 950.0f); glm::vec3 at_pos = glm::vec3(-274.564f, -282.243f, 254.327f); glm::vec3 up_dir = glm::vec3(0.0f, 1.0f, 0.0f); std::cout << "set camera" << std::endl; glm::mat4x4 look_at = LookAt(eye_pos, at_pos, up_dir); Camera camera(image_width, image_height, Orthographic(0.0f, 1.0f), look_at); std::cout << "camera set" << std::endl; Light point_light; glm::vec3 point_light_color = glm::vec3(0.4f, 0.4f, 0.4f); point_light.ka = point_light_color; point_light.kd = point_light_color; point_light.ks = point_light_color; point_light.ray = Ray(glm::vec3(0.0, -400.0, 400.0f), glm::vec3(0.0f)); point_light.type = Light::kPoint; point_light.attenuation_coefficients = glm::vec3(0.25f, 0.003372407f, 0.000045492f); Light directional_light; glm::vec3 directional_light_color = glm::vec3(0.4f, 0.4f, 0.4f); directional_light.ka = directional_light_color; directional_light.kd = directional_light_color; directional_light.ks = directional_light_color; directional_light.ray = Ray(glm::vec3(0.0f), glm::vec3(0.0f, -1.0f, -1.0f)); directional_light.type = Light::kDirectional; scene.AddLight(point_light); scene.AddLight(directional_light); Trimesh* trimesh = static_cast<Trimesh*>(scene.scene_objects()[0]); OctreeType octree; std::cout << "Building octree" << std::endl; octree.Build(trimesh->faces()); //octree.set_trace(true); //octree.Print(std::cout); std::cout << "Octree built.\n"; std::cout << "bounds = " << octree.GetBounds() << " center = " << octree.GetBounds().GetCenter() << std::endl; trimesh->set_accelerator(&octree); Image image; image.Resize(image_width, image_height); RayTracer ray_tracer(&scene, &camera); ray_tracer.set_display_progress(!use_timing); ray_tracer.set_display_stats(!use_timing); ray_tracer.set_background_color(glm::vec3(0.05f, 0.05f, 0.05f)); timeval t_start, t_finish; if (use_timing) gettimeofday(&t_start, NULL); std::cout << "Rendering..." << std::endl; ray_tracer.Render(image); if (use_timing) { gettimeofday(&t_finish, NULL); float sec = t_finish.tv_sec - t_start.tv_sec + t_finish.tv_usec / 1000000.0f - t_start.tv_usec / 1000000.0f; std::cout << "Render time:" << sec << std::endl; } else std::cout << "Done." << std::endl; ImageStorage& storage = ImageStorage::GetInstance(); success = storage.WriteImage("blade_octree.jpg", image, status); EXPECT_TRUE(success); EXPECT_EQ("OK", status); }
static void processTrimesh( string name, Obj *child, Scene *scene, const mmap& materials, TransformNode *transform ) { Material *mat; if( hasField( child, "material" ) ) mat = getMaterial( getField( child, "material" ), materials ); else mat = new Material(); Trimesh *tmesh = new Trimesh( scene, mat, transform); const mytuple &points = getField( child, "points" )->getTuple(); for( mytuple::const_iterator pi = points.begin(); pi != points.end(); ++pi ) tmesh->addVertex( tupleToVec( *pi ) ); const mytuple &faces = getField( child, "faces" )->getTuple(); for( mytuple::const_iterator fi = faces.begin(); fi != faces.end(); ++fi ) { const mytuple &pointids = (*fi)->getTuple(); // triangulate here and now. assume the poly is // concave and we can triangulate using an arbitrary fan if( pointids.size() < 3 ) throw ParseError( "Faces must have at least 3 vertices." ); mytuple::const_iterator i = pointids.begin(); int a = (int) (*i++)->getScalar(); int b = (int) (*i++)->getScalar(); while( i != pointids.end() ) { int c = (int) (*i++)->getScalar(); if( !tmesh->addFace(a,b,c) ) throw ParseError( "Bad face in trimesh." ); b = c; } } bool generateNormals = false; maybeExtractField( child, "gennormals", generateNormals ); if( generateNormals ) tmesh->generateNormals(); if( hasField( child, "materials" ) ) { const mytuple &mats = getField( child, "materials" )->getTuple(); for( mytuple::const_iterator mi = mats.begin(); mi != mats.end(); ++mi ) tmesh->addMaterial( getMaterial( *mi, materials ) ); } if( hasField( child, "normals" ) ) { const mytuple &norms = getField( child, "normals" )->getTuple(); for( mytuple::const_iterator ni = norms.begin(); ni != norms.end(); ++ni ) tmesh->addNormal( tupleToVec( *ni ) ); } char *error; if( error = tmesh->doubleCheck() ) throw ParseError( error ); scene->add(tmesh); }
void parseInput(char cmd[LINE_SIZE], bool isCommand) { std::vector<char*> v; char* chars_array = strtok(cmd, " "); while(chars_array) { v.push_back(chars_array); chars_array = strtok(NULL, " "); } float span; if(meshes.size() > 0) { float diam = meshes.back()->get_diam(); float z = 1.0f + diam * 4.0f + perm_zoom + zoom; float theta = 30.0f/2.0f; float tang = tan(theta); float opposite = tang * z; span = -opposite; } int i; Trimesh* mesh; if(v.size() == 0) return; if(meshes.size() > 0) mesh = meshes.back(); if(!strcmp(v[0], "L") & v.size() >= 2) { cout << "Loading file: " << v[1] << endl; Trimesh* mesh = new Trimesh(); if(loader->loadOBJ(v[1], mesh)) { meshes.push_back(mesh); flushTransformations(); } } else if(!strcmp(v[0], "D")) { if(v.size() >= 2) { meshes.erase(meshes.begin() + atoi(v[1])); printFiles(); } else meshes.pop_back(); } else if(!strcmp(v[0], "I")) { mesh->addTransformation(4.0f, 0.f, 0.f, 0.f, 0.f); flushTransformations(); } else if(!strcmp(v[0], "T") && v.size() >= 4) { if(local_coords && false) mesh->addTransformation(1.0f, 0.f, span * atof(v[1]), -span * atof(v[2]), span * atof(v[3])); else mesh->addTransformation(1.0f, 0.f, atof(v[1]), -atof(v[2]), atof(v[3])); } else if(!strcmp(v[0], "S") && v.size() >= 4) { if(local_coords && false) { mesh->addTransformation(2.0f, 0.f, atof(v[1]) == 1.0f ? 1.0f : span * atof(v[1]), atof(v[2]) == 1.0f ? 1.0f : span * atof(v[2]), atof(v[3]) == 1.0f ? 1.0f : span * atof(v[3])); } else mesh->addTransformation(2.0f, 0.f, atof(v[1]), atof(v[2]), atof(v[3])); } else if(!strcmp(v[0], "R") && v.size() >= 5) { mesh->addTransformation(3.0f, atof(v[1]), atof(v[2]), atof(v[3]), atof(v[4])); } else if(!strcmp(v[0], "V")) { local_coords = true; } else if(!strcmp(v[0], "W")) { local_coords = false; } else if(!strcmp(v[0], "POINT")) { mode = POINTS; } else if(!strcmp(v[0], "WIRE")) { mode = LINES; } else if(!strcmp(v[0], "SOLID")) { mode = FACES; lighting_off = true; } else if(!strcmp(v[0], "SHADED")) { mode = FACES; lighting_off = false; } else if(!strcmp(v[0], "FNORMALS")) { fnormals = !fnormals; } else if(!strcmp(v[0], "VNORMALS")) { vnormals = !vnormals; } else if(!strcmp(v[0], "QUIT")) { exit(0); } else if(!strcmp(v[0], "ROTATOPOTATO")) { auto_rotate_enabled = !auto_rotate_enabled; } else if(!strcmp(v[0], "OBJECTS")) { printFiles(); } else if(!strcmp(v[0], "SWITCH")) { if(v.size() >= 2) { int ind = atoi(v[1]); meshes.push_back(meshes[ind]); meshes.erase(meshes.begin() + ind); printFiles(); } } else if(!strcmp(v[0], "DRAW")) { if(v.size() >= 2) { int ind = atoi(v[1]); if(meshes.size()-1 >= ind) meshes[ind]->draw = true; printFiles(); } } if(isCommand) newCommand = false; }
void Parser::parseTrimesh(Scene* scene, TransformNode* transform, const Material& mat) { Trimesh* tmesh = new Trimesh( scene, new Material(mat), transform); _tokenizer.Read( TRIMESH ); _tokenizer.Read( LBRACE ); bool generateNormals( true ); list<Vec3d> faces; char* error; for( ;; ) { const Token* t = _tokenizer.Peek(); switch( t->kind() ) { case GENNORMALS: _tokenizer.Read( GENNORMALS ); _tokenizer.Read( SEMICOLON ); generateNormals = true; break; case MATERIAL: tmesh->setMaterial( parseMaterialExpression( scene, mat ) ); break; case NAME: parseIdentExpression(); break; case MATERIALS: _tokenizer.Read( MATERIALS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addMaterial( parseMaterial( scene, tmesh->getMaterial() ) ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addMaterial( parseMaterial( scene, tmesh->getMaterial() ) ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case NORMALS: _tokenizer.Read( NORMALS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addNormal( parseVec3d() ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addNormal( parseVec3d() ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case FACES: _tokenizer.Read( FACES ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { parseFaces( faces ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); parseFaces( faces ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case POLYPOINTS: _tokenizer.Read( POLYPOINTS ); _tokenizer.Read( EQUALS ); _tokenizer.Read( LPAREN ); if( RPAREN != _tokenizer.Peek()->kind() ) { tmesh->addVertex( parseVec3d() ); for( ;; ) { const Token* nextToken = _tokenizer.Peek(); if( RPAREN == nextToken->kind() ) break; _tokenizer.Read( COMMA ); tmesh->addVertex( parseVec3d() ); } } _tokenizer.Read( RPAREN ); _tokenizer.Read( SEMICOLON ); break; case RBRACE: { _tokenizer.Read( RBRACE ); // Now add all the faces into the trimesh, since hopefully // the vertices have been parsed out for( list<Vec3d>::const_iterator vitr = faces.begin(); vitr != faces.end(); vitr++ ) { if( !tmesh->addFace( (*vitr)[0], (*vitr)[1], (*vitr)[2] ) ) { ostringstream oss; oss << "Bad face in trimesh: (" << (*vitr)[0] << ", " << (*vitr)[1] << ", " << (*vitr)[2] << ")"; throw ParserException( oss.str() ); } } if( generateNormals ) tmesh->generateNormals(); if( error = tmesh->doubleCheck() ) throw ParserException( error ); scene->add( tmesh ); return; } default: throw SyntaxErrorException( "Expected: trimesh attributes", _tokenizer ); } } }
int main(int argc, char **argv) { bool wants_tree = false; bool wants_tokens = false; bool wants_timeout = false; bool wants_render = false; bool wants_quiet = false; bool is_flat = true; int timeout = 45; std::string out_path = ""; GeometryMode::geometry_mode_t geometry_mode = GeometryMode::SURFACE; int optind = 1; for (; optind < argc && argv[optind][0] == '-'; ++optind) { std::string formal = argv[optind]; if (formal == "--timeout") { wants_timeout = true; if (optind < argc - 1) { for (size_t i = 0; i < strlen(argv[optind + 1]); ++i) { if (!isdigit(argv[optind + 1][i])) { usage("Timeout must be positive integer."); } } timeout = atoi(argv[optind + 1]); ++optind; } else { usage("Timeout must be given."); } } else if (formal == "--tree") { wants_tree = true; } else if (formal == "--tokens") { wants_tokens = true; } else if (formal == "-r") { wants_render = true; } else if (formal == "-q") { wants_quiet = true; } else if (formal == "-o") { if (optind < argc - 1) { out_path = argv[optind + 1]; ++optind; } else { usage("-o given, but no path specified."); } } else if (formal == "--shading") { if (optind < argc - 1) { std::string mode_label = argv[optind + 1]; if (mode_label == "FLAT") { is_flat = true; } else if (mode_label == "SMOOTH") { is_flat = false; } else { std::stringstream ss; ss << "unknown shading mode \"" << mode_label << "\""; usage(ss.str()); } ++optind; } else { usage("--shading given, but invalid mode."); } } else if (formal == "--geometry") { if (optind < argc - 1) { std::string mode_label = argv[optind + 1]; if (mode_label == "SURFACE") { geometry_mode = GeometryMode::SURFACE; } else if (mode_label == "PATH") { geometry_mode = GeometryMode::PATH; } else if (mode_label == "NONE") { geometry_mode = GeometryMode::NONE; } else { std::stringstream ss; ss << "unknown geometry mode \"" << mode_label << "\""; usage(ss.str()); } ++optind; } else { usage("--geometry given, but no path specified."); } } else { usage("unknown option: " + formal); } } if (optind >= argc) { usage("No input path specified."); } std::string in_path = argv[optind]; ++optind; if (optind < argc) { usage("Stray parameters."); } std::string source = Utilities::Slurp(in_path); std::ifstream in(in_path); Lexer lexer(in); try { const std::vector<Token> &tokens = lexer.lex(); if (wants_tokens) { for (std::vector<Token>::const_iterator i = tokens.begin(); i != tokens.end(); ++i) { std::cout << *i << std::endl; } } Parser parser(tokens, source); Co<ExpressionBlock> program = parser.program(); if (wants_tree) { std::cout << program << std::endl; } if (!wants_quiet) { Environment env; env.prime(); env.setGeometryMode(geometry_mode); srand(time(NULL)); rand(); if (wants_timeout) { env.setTimeout(timeout); } /* std::future<void> future = std::async(std::launch::async, [&program, &env] { */ /* program->evaluate(env); */ /* }); */ /* future.get(); */ program->evaluate(env); Trimesh *trimesh = env.getMesh(); if (out_path.length() > 0) { if (geometry_mode == GeometryMode::PATH) { std::ofstream out(out_path.c_str()); out << env.getPathsJSON(); out.close(); } else if (geometry_mode == GeometryMode::SURFACE) { if (is_flat) { trimesh->DisconnectFaces(); trimesh->ComputeMeta(true); } else { td::Trimesh *sharped = madeup::MeshBoolean::compute_normals(*trimesh, 20); delete trimesh; trimesh = sharped; trimesh->ComputeMeta(false); } if (out_path.find_first_of('.') == std::string::npos || out_path.find(".json") == out_path.length() - 5) { trimesh->WriteJSON(out_path); } else if (out_path.find(".stl") == out_path.length() - 4) { trimesh->WriteSTL(out_path); } else { trimesh->WriteObj(out_path); } if (trimesh->GetVertexCount() == 0) { std::cerr << "Uh oh. You either didn't visit any locations or didn't invoke a solidifier. I can't make any models without more information from you." << std::endl; } } if (wants_render) { std::string command = "runx /Users/johnch/checkouts/cj_graphics/build/projects/mesher/mesher.app -m " + out_path; system(command.c_str()); } } } } catch (std::bad_alloc e) { std::cerr << "Whoa! I don't have enough memory for that." << std::endl; in.close(); exit(1); } catch (td::MessagedException e) { std::cerr << e.GetMessage() << std::endl; in.close(); exit(1); } in.close(); return 0; }
void Parser::parseObj(string inputfile, Scene* scene, const Material& parent, TransformNode* transform){ // Trimesh* tmesh = new Trimesh( scene, new Material(mat), transform); std::cout << inputfile << std::endl; std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::material_t> materials; std::string err; bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str()); if (!err.empty()) { // `err` may contain warning message. std::cerr << err << std::endl; } if (!ret) { exit(1); } //Else successful now add the objects to the scene for(int i = 0; i < shapes.size(); i++){ //Will only support one material per object // Get Materials Trimesh* tmesh; if(!shapes[i].mesh.material_ids.empty()){ auto mtr = materials[shapes[i].mesh.material_ids[0]]; // float ambient[3]; // float diffuse[3]; // float specular[3]; // float transmittance[3]; // float emission[3]; // float shininess; // float ior; Vec3d ke(mtr.emission[0], mtr.emission[1], mtr.emission[2] ); Vec3d ka(mtr.ambient[0], mtr.ambient[1], mtr.ambient[2] ); Vec3d ks(mtr.specular[0], mtr.specular[1], mtr.specular[2] ); Vec3d kd(mtr.diffuse[0], mtr.diffuse[1], mtr.diffuse[2] ); // Vec3d kt(mtr.transmittance[0], mtr.transmittance[1], mtr.transmittance[2]); Vec3d kt(1.0 - mtr.dissolve, 1.0 - mtr.dissolve,1.0 - mtr.dissolve); std::cout << "Tr " << mtr.transmittance[0]<< " " << mtr.transmittance[1] << " " << mtr.transmittance[2] << " :d->: "<< mtr.dissolve << std::endl; Vec3d kr = Vec3d(0.0,0.0,0.0); // if(mtr.dissolve < 1.0) kr = ks; if(mtr.dissolve < 1.0) kr = Vec3d(0.2,0.2,0.2); tmesh = new Trimesh( scene, new Material(ke, ka, ks, kd, kr,kt, mtr.shininess, mtr.ior), transform); }else{ std::cerr << "Note: OBJ file missing material" << std::endl; tmesh = new Trimesh( scene, new Material(parent), transform); } for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) { //First Add Vertices Vec3d vert(shapes[i].mesh.positions[3*v+0], shapes[i].mesh.positions[3*v+1], shapes[i].mesh.positions[3*v+2]); tmesh->addVertex(vert); } for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) { //Then Add Faces tmesh->addFace(shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2]); } tmesh->generateNormals(); // tmesh->buildKdTree(); scene->addBB( tmesh ); } }