void uhfsolve::setupF(){ //set up the Fock matrix double Di = 0; double Ex = 0; double DiMinusEx = 0; for(int p=0;p<nStates;p++){ for(int q=0;q<nStates;q++){ //F(p,q) = Bs.h(p,q); Fu(p,q) = Bs.h(p,q); Fd(p,q) = Bs.h(p,q); for(int r=0;r<nStates;r++){ for(int s=0;s<nStates;s++){ //Di = Bs.v(p,r)(q,s); //Ex = Bs.v(p,r)(s,q); Di = Bs.v(p,q)(r,s); Ex = Bs.v(p,s)(r,q); DiMinusEx = Di-Ex; //F(p,q) += 0.5*coupledMatrixTilde(p,q,r,s)*P(r,s); //Alt. 2 27/5 2014 Fu(p,q) += Pu(s,r)*(Di-Ex) + Pd(s,r)*Di; Fd(p,q) += Pd(s,r)*(Di-Ex) + Pu(s,r)*Di; } } } } }
void Controller::moveY(double speed) { speed *= MoveSpeed; speed *= FRATE; Point<double> posrollback = Point<double>(player->origin); Point<double> tarrollback = Point<double>(target); Vector<double> vec = (-player->rotation * Vector<double>(0,1,0)); vec.z = 0; vec = ~vec; double yaw = atan2(vec.x, vec.y); player->origin = player->origin + vec*speed; target = player->origin + Pd(.75 * sin(yaw - .25*Pi), .75 * cos(yaw-.25*Pi), 2); if(!walkAble(posrollback, player->origin)){ player->origin = posrollback; target = tarrollback; blocked = true; return; } vec = ~(camAngle * Vector<double>(0,1,0)); if (firstPerson) { camera.origin = player->origin + Pd(0,0,2.5) + vec; camera.lookAt(camera.origin + (vec * 5.0)); } else { camera.origin = target - (vec * zoom); camera.lookAt(target); } blocked = false; }
float Ship::Wm(){ float c1, c2; c1 = c2 = 0.; float PdV = Pd(v.Vk)/Vol(); float c3 = pow(v.Year, 0.4) - 19; if (PdV > 40) c1 = 0.14 * c3; else if (PdV > 26) c1 = 0.13 * c3; else if (PdV > 21) c1 = 0.21 * c3; else if (PdV > 10) c1 = 0.22 * c3; else c1 = 1.; if (Vol() > 5000) c1 = 1.; if (v.Year < 1915) c2 = 1.9; else if(v.Year < 1933) c2 = 1.6; else c2 = 0.92; return find(et, e.Eng).K1 * pow(Pd(v.Vk), find(et, e.Eng).K2)* (pow((pow(v.Year, 0.45) - 29.3), 2.) + 0.45) * c1 * c2 * find(st, e.Gear).Wgear; }
Droppable::Droppable(Pd _origin, Resource _worth, long _dropped, long _ttl) : BoundedObject(_origin, Qd(), BoundingBox(Pd(-0.105, -0.5, 0.0), Pd(0.105, 0.5, 1.0))) { model.coin = ModelObjectContainer(); model.coin->children.insert(Assets::Model::CoinObj); children.insert(model.coin); model.coin->material = Assets::Model::CoinTex; worth = _worth; dropped = _dropped; ttl = _ttl; done = false; long pid = (Game::game.player ? Game::game.player->id : 0); id = topId++ | (pid << 16); }
void Controller::lookZ(double speed) { speed *= LookSpeed; speed *= FRATE; Qd buffer = camAngle;//Used to rollback if out of bounds Vector<double> mystery = ~(camAngle * Vector<double>(0,1,0)); double mysteryYaw = atan2(mystery.x, mystery.y); camAngle = Qd(Rd(speed, Vd(cos(mysteryYaw),-sin(mysteryYaw),0))) * camAngle; if((camAngle*Vector<double>(0,1,0)).z > 0.99 || (camAngle*Vector<double>(0,1,0)).z < -0.99){ camAngle = buffer; return; } Vector<double> vec = ~(camAngle * Vector<double>(0,1,0)); if (firstPerson == true) { camera.origin = player->origin + Pd(0,0,2.5) + vec; camera.lookAt(camera.origin + (vec * 5.0)); } else { camera.origin = target - (vec * zoom); camera.lookAt(target); } }
void P_nested(vector<double> &P, const vector<double> &par, const NumericMatrix &Theta, const int &N, const int &nfact, const int &ncat, const int &correct) { NumericVector dummy(1); const int par_size = par.size(); vector<double> dpar(nfact+3), npar(par_size - nfact - 3, 1.0); for(int i = 0; i < nfact+3; ++i) dpar[i] = par[i]; for(int i = nfact+3; i < par_size; ++i) npar[i - (nfact+3) + nfact] = par[i]; vector<double> Pd(N*2), Pn(N*(ncat-1)); P_dich(Pd, dpar, Theta, dummy, N, nfact); P_nominal(Pn, npar, Theta, dummy, N, nfact, ncat-1, 0, 0); NumericMatrix PD = vec2mat(Pd, N, 2); NumericMatrix PN = vec2mat(Pn, N, ncat-1); int k = 0, which = 0; for(int i = 0; i < ncat; ++i){ if((i+1) == correct){ for(int j = 0; j < N; ++j){ P[which] = PD(j,1); ++which; } --k; } else { for(int j = 0; j < N; ++j){ P[which] = PD(j,0) * PN(j,k); ++which; } } ++k; } }
Point<double> getSpawn(const char team){ switch(team){ case 'b':{ //Pd spawn1 = game.world->terrain->ToPointD(GridPoint(5, 24)); Pd spawn2 = game.world->terrain->ToPointD(GridPoint(5, 25)); int randval = rand() % 2; if(randval == 0){ return spawn2; }else{ return spawn2; } } break; case 'a':{ //Pd spawn1 = game.world->terrain->ToPointD(GridPoint(45,25)); Pd spawn2 = game.world->terrain->ToPointD(GridPoint(45,26)); int randval = rand() % 2; if(randval == 0){ return spawn2; }else{ return spawn2; } } break; default:{ return Pd(); } } }
void Sky::frame(){ if(stars.size() < 300){ int res = rand()%100; if(res == 0){ int x = rand()%width - (int)width/2; int y = rand()%height - (int)height/2; int min = HIGH - (int)(HIGH/10); int z = rand()%(HIGH-min) + min; stars.push_back(Star(Pd(x, y, z))); } } if(stars.size() > 150){ int res = rand()%200; if(res == 0){ stars.erase(stars.begin() + (rand()%stars.size())); } } if(stars.size() > 100){ int res = rand()%60; if(res == 0){ vector<Star>::iterator it; it = stars.begin() + (rand()%stars.size()); it->big = !it->big; } } }
void Controller::lookY(double speed) { speed *= ZoomSpeed; speed *= FRATE; Vector<double> vec = ~(camAngle * Vector<double>(0,1,0)); zoom -= speed; if (zoom > 25.0) { zoom = 25.0; } else if (zoom <= 5.0) { firstPerson = true; zoom = 5.0; } else { firstPerson = false; } if (firstPerson == true) { camera.origin = player->origin + Pd(0,0,2.5) + vec; camera.lookAt(camera.origin + (vec * 5.0)); } else { camera.origin = target - (vec * zoom); camera.lookAt(target); } }
float Ship::Bunker(){ float b1 = v.Range / (1. + 0.4 * v.Coalpct); float b2 = 0.; float b3 = 1.8/Pd(v.Vc) * v.Range * v.Vc * 0.1; if (v.Year < 1898 || e.Eng == QuadExp || e.Eng == TripExp) b2 = 1. - (1910 - v.Year)/70.; else if (v.Year < 1920) b2 = 1. + (v.Year - 1910)/20.; else if( v.Year < 1950) b2 = 1.5 + (v.Year - 1920)/60.; else b2 = 2 + (v.Year - 1950)/60.; float c1 = (Pd(v.Vk)/Vol() > 15 && Pd(v.Vk)/Vol() < 18) ? 0.3 : 1; return (b1 / (b2 * b3) + 0.005 * Vol()) * c1 * find(et, e.Eng).FcE * find(st, e.Gear).FcT; }
void Test(string str) { if(str == "a"){ game.world->children.insert(Droppable(Pd(0.0, 0.0, 0.0), 30)); }else if(str == "b"){ game.world->temporary.push_back(Droppable(Pd(0.0, 0.0, 0.0), 30)); }else{ Player::Id pid2 = game.topId++; ObjectHandle player2 = Player(pid2, 'a', "Carl"); game.root->children.insert(player2); game.players[pid2] = player2; if(game.teams.count('a')) game.teams['a'].resources = 1000; game.world->terrain->placeStructure(GridPoint(22,24), DefenseTower(pid2)); } }
World::World(double _width, double _height) : BoundedObject(Pd(), Qd(), BoundingBox(Pd(-_width/2, -_height/2, 0), Pd(_width,0,0), Pd(0,_height,0), Pd(_width,_height,0), Pd(), Pd(), Pd(), Pd(_width/2, _height/2, HIGH)), Assets::WorldMaterial) { ObjectHandle tHandle; tHandle = Terrain(_width, _height); terrain = TO(Terrain, tHandle); children.insert(tHandle); ObjectHandle hudHandle; hudHandle = HUD(640, 480); hud = TO(HUD, hudHandle); children.insert(hudHandle); children.insert(Sky((int) _width, (int) _height)); width = _width; height = _height; }
void Controller::frame() { if (move[dirY] != 0.0) moveY(move[dirY]); if (move[dirZ] != 0.0) moveZ(move[dirZ]); if (look[dirX] != 0.0) lookX(look[dirX]); if (look[dirY] != 0.0) lookY(look[dirY]); if (look[dirZ] != 0.0) lookZ(look[dirZ]); if (move[dirY] != 0.0) { if ((move[dirX] < 0.0 && move[dirY] > 0.0) || (move[dirX] > 0.0 && move[dirY] < 0.0)) player->rotation = player->rotation * Rd(-0.05,Vd(0,0,1)); else if ((move[dirX] > 0.0 && move[dirY] > 0.0) || (move[dirX] < 0.0 && move[dirY] < 0.0)) player->rotation = player->rotation * Rd(0.05,Vd(0,0,1)); else { Vd camv = camAngle*Vd(0,1,0); Vd plav = player->rotation*Vd(0,1,0); camv.z = 0; camv = ~camv; plav.z = 0; plav = ~plav; double angle = atan2(camv.y - plav.y, camv.x - plav.x); double angle2 = (angle < 0? -angle : angle); double axis = angle2 > 0.5*Pi ^ angle > 0? 1 : -1; angle2 = angle2 > 0.5*Pi ? Pi - angle2 : angle2; angle2 = angle2 < 0.05? angle2 : 0.05; if (axis != 0) player->rotation = player->rotation * Rd(-angle2,Vd(0,0,axis)); } } Vector<double> vec = (-player->rotation * Vector<double>(0,1,0)); vec.z = 0; vec = ~vec; double yaw = atan2(vec.x, vec.y); target = player->origin + Pd(.75 * sin(yaw - .25*Pi), .75 * cos(yaw-.25*Pi), 2); vec = ~(camAngle * Vector<double>(0,1,0)); if (firstPerson) { camera.lookAt(camera.origin + (vec * 5.0)); } else { camera.lookAt(target); } Objects::Player * p = TO(Objects::Player,player); p->velocity = Vd(0,MoveSpeed,0); }
Controller::Controller(Camera &C, ObjectHandle P) : camera(C), player(P) { firstPerson = false; lastView = false; target = player->origin + Pd(-.5,-.5,2); Vector<double> vec = camAngle * Vector<double>(0,1,0); zoom = 10.0; camera.origin = target - (~vec * zoom); camera.lookAt(target); camAngle = Qd(); blocked = false; }
void Controller::lookX(double speed) { speed *= -LookSpeed; speed *= FRATE; camAngle = Qd(Rd(speed, Vd(0,0,1))) * camAngle; Vector<double> vec = ~(camAngle * Vector<double>(0,1,0)); if (firstPerson == true) { camera.origin = player->origin + Pd(0,0,2.5) + vec; camera.lookAt(camera.origin + (vec * 5.0)); } else { camera.origin = target - (vec * zoom); camera.lookAt(target); } }
float Ship::Lcmi(){ return (0.002 * Pd(v.Vk) + 5.5) / M2FT; }
void Initialize(int argc, char *argv[]) { // Process command line arguments for (int i = 0; i < argc - 1; ++i) { if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--map-width")) gameWidth = atof(argv[++i]); else if (!strcmp(argv[i], "-y") || !strcmp(argv[i], "--map-height")) gameHeight = atof(argv[++i]); else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--path")) path = argv[++i]; else if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--screen-width")) windowWidth = atoi(argv[++i]); else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--screen-height")) windowHeight = atoi(argv[++i]); } // Process config file if (!file_exists(CONFIG_FILE)) { ConfigFile newconfig; newconfig.add("playername", "Unnamed"); newconfig.add("team", 'a'); newconfig.save(CONFIG_FILE); } try { config = new ConfigFile(CONFIG_FILE); } catch (ConfigFile::file_not_found e) { delete config; config = NULL; puts("Unable to create config file: " CONFIG_FILE "!"); exit(EXIT_FAILURE); } fullscreen = (config->read("fullscreen", '0')) == '1'? true : false; /* deprecated: for (int i = 0; i < argc; ++i) { if (!strcmp(argv[i], "--fullscreen")) fullscreen = true; }*/ // Global subsystem initializations srand(time(NULL)); // Create window and set up viewports game.window = new Video::Window(windowWidth, windowHeight, GAME_NAME, fullscreen); Video::Viewport *view = new Video::Viewport(1,1); game.window->viewports.push_back(view); // Show loading screen // Problem: we can't use the hud prior to asset loading // Load game assets Assets::Initialize(argc, argv); config->readInto(NetCode::MessageOfTheDay, "motd", string("No message of the day ;(")); // Set up game world game.root = World(gameWidth, gameHeight); game.world = TO(World,game.root); game.topId = 1; game.teams.insert(make_pair('a', Team('a'))); game.teams.insert(make_pair('b', Team('b'))); string name; unsigned char team; config->readInto(name, "playername", string("Unnamed")); team = config->read("team", 'a'); Player::Id pid = game.topId++; ObjectHandle player = Player(pid, team, name); game.player = TO(Player,player); game.player->weapon = weapLaser; game.player->origin = getSpawn(team); game.root->children.insert(player); game.players[pid] = player; game.world->terrain->placeStructure(GridPoint(2,2), Mine()); game.world->terrain->placeStructure(GridPoint(2,48), Mine()); game.world->terrain->placeStructure(GridPoint(48,2), Mine()); game.world->terrain->placeStructure(GridPoint(48,48), Mine()); game.world->terrain->placeStructure(GridPoint(25,25), RichMine()); game.world->terrain->placeStructure(GridPoint(15,25), Mine()); game.world->terrain->placeStructure(GridPoint(35,25), Mine()); game.world->terrain->placeStructure(GridPoint(25,5), RichMine()); game.world->terrain->placeStructure(GridPoint(25,45), RichMine()); game.world->terrain->placeStructure(GridPoint(6,9), Mine()); game.world->terrain->placeStructure(GridPoint(6,41), Mine()); game.world->terrain->placeStructure(GridPoint(44,9), Mine()); game.world->terrain->placeStructure(GridPoint(44,41), Mine()); game.world->terrain->placeStructure(GridPoint(10,17), Mine()); game.world->terrain->placeStructure(GridPoint(10,33), Mine()); game.world->terrain->placeStructure(GridPoint(40,17), Mine()); game.world->terrain->placeStructure(GridPoint(40,33), Mine()); ObjectHandle RedBot = player; ObjectHandle BlueBot = player; if (team == 'b') { RedBot = Player(INT_MAX - 'a', 'a', "RedBot", Pd(-1000,-1000,-1000)); //game.world->children.insert(RedBot); game.players[TO(Player, RedBot)->id] = RedBot; } else if (team == 'a') { BlueBot = Player(INT_MAX - 'b', 'b', "BlueBot", Pd(-1000,-1000,-1000)); //game.world->children.insert(BlueBot); game.players[TO(Player, BlueBot)->id] = BlueBot; } game.world->terrain->placeStructure(GridPoint(3,25), HeadQuarters(TO(Player, BlueBot)->id)); game.world->terrain->placeStructure(GridPoint(48,26), HeadQuarters(TO(Player, RedBot)->id)); game.world->terrain->placeStructure(GridPoint(4,26), DefenseTower(TO(Player, BlueBot)->id)); game.world->terrain->placeStructure(GridPoint(4,23), DefenseTower(TO(Player, BlueBot)->id)); game.world->terrain->placeStructure(GridPoint(46,27), DefenseTower(TO(Player, RedBot)->id)); game.world->terrain->placeStructure(GridPoint(46,24), DefenseTower(TO(Player, RedBot)->id)); for(int i = 0; i <= 50; i++) { game.world->terrain->placeStructure(GridPoint(0,i), Wall()); game.world->terrain->placeStructure(GridPoint(50,i), Wall()); game.world->terrain->placeStructure(GridPoint(i,0), Wall()); game.world->terrain->placeStructure(GridPoint(i,50), Wall()); } for(int i = 8; i <= 42; i++) { if (i < 23 || i > 27) { game.world->terrain->placeStructure(GridPoint(25,i), Wall()); game.world->terrain->placeStructure(GridPoint(i,5), Wall()); game.world->terrain->placeStructure(GridPoint(i,45), Wall()); } if (i < 22 || i > 28) { game.world->terrain->placeStructure(GridPoint(i,15), Wall()); game.world->terrain->placeStructure(GridPoint(i,35), Wall()); } if (i < 13 || i > 37) { game.world->terrain->placeStructure(GridPoint(i,25), Wall()); } } for (int i = 5; i <=11; i++) { game.world->terrain->placeStructure(GridPoint(4,i), Wall()); game.world->terrain->placeStructure(GridPoint(46,i), Wall()); game.world->terrain->placeStructure(GridPoint(i,11), Wall()); game.world->terrain->placeStructure(GridPoint(i,39), Wall()); } for (int i = 39; i <=45; i++) { game.world->terrain->placeStructure(GridPoint(4,i), Wall()); game.world->terrain->placeStructure(GridPoint(46,i), Wall()); game.world->terrain->placeStructure(GridPoint(i,11), Wall()); game.world->terrain->placeStructure(GridPoint(i,39), Wall()); } for (int i = 15; i <= 35; i++) { game.world->terrain->placeStructure(GridPoint(8,i), Wall()); game.world->terrain->placeStructure(GridPoint(42,i), Wall()); } for (int i = 3; i <= 47; i++) { if (i < 12 || i > 38 || (i > 19 && i < 31)) { game.world->terrain->placeStructure(GridPoint(18,i), Wall()); game.world->terrain->placeStructure(GridPoint(32,i), Wall()); } } for (int i = 13; i <= 37; i++) { if (i < 18 || i > 32) { game.world->terrain->placeStructure(GridPoint(i,20), Wall()); game.world->terrain->placeStructure(GridPoint(i,30), Wall()); } } game.world->terrain->placeStructure(GridPoint(11,1), Wall()); game.world->terrain->placeStructure(GridPoint(11,2), Wall()); game.world->terrain->placeStructure(GridPoint(11,49), Wall()); game.world->terrain->placeStructure(GridPoint(11,48), Wall()); game.world->terrain->placeStructure(GridPoint(39,1), Wall()); game.world->terrain->placeStructure(GridPoint(39,2), Wall()); game.world->terrain->placeStructure(GridPoint(39,49), Wall()); game.world->terrain->placeStructure(GridPoint(39,48), Wall()); // Set up user interface view->world = game.root; game.controller = new Controller(view->camera, player); game.input = new Input(*game.window); game.input->onKeyUp = KeyUp; game.input->onKeyDown = KeyDown; //input->onMouseMove = MouseMove; Echo("Everything loaded!"); Echo("Welcome to the game"); Echo(NetCode::MessageOfTheDay); }
CC_FILE_ERROR ObjFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters) { ccLog::Print(QString("[OBJ] ") + filename); //open file QFile file(filename); if (!file.open(QFile::ReadOnly)) return CC_FERR_READING; QTextStream stream(&file); //current vertex shift CCVector3d Pshift(0,0,0); //vertices ccPointCloud* vertices = new ccPointCloud("vertices"); int pointsRead = 0; //facets unsigned int facesRead = 0; unsigned int totalFacesRead = 0; int maxVertexIndex = -1; //base mesh ccMesh* baseMesh = new ccMesh(vertices); baseMesh->setName(QFileInfo(filename).baseName()); //we need some space already reserved! if (!baseMesh->reserve(128)) { ccLog::Error("Not engouh memory!"); return CC_FERR_NOT_ENOUGH_MEMORY; } //groups (starting index + name) std::vector<std::pair<unsigned,QString> > groups; //materials ccMaterialSet* materials = 0; bool hasMaterial = false; int currentMaterial = -1; bool currentMaterialDefined = false; bool materialsLoadFailed = true; //texture coordinates TextureCoordsContainer* texCoords = 0; bool hasTexCoords = false; int texCoordsRead = 0; int maxTexCoordIndex = -1; //normals NormsIndexesTableType* normals = 0; int normsRead = 0; bool normalsPerFacet = false; int maxTriNormIndex = -1; //progress dialog ccProgressDialog pDlg(true); pDlg.setMethodTitle("OBJ file"); pDlg.setInfo("Loading in progress..."); pDlg.setRange(0,static_cast<int>(file.size())); pDlg.show(); QApplication::processEvents(); //common warnings that can appear multiple time (we avoid to send too many messages to the console!) enum OBJ_WARNINGS { INVALID_NORMALS = 0, INVALID_INDEX = 1, NOT_ENOUGH_MEMORY = 2, INVALID_LINE = 3, CANCELLED_BY_USER = 4, }; bool objWarnings[5] = { false, false, false, false, false }; bool error = false; try { unsigned lineCount = 0; unsigned polyCount = 0; QString currentLine = stream.readLine(); while (!currentLine.isNull()) { if ((++lineCount % 2048) == 0) { if (pDlg.wasCanceled()) { error = true; objWarnings[CANCELLED_BY_USER] = true; break; } pDlg.setValue(static_cast<int>(file.pos())); QApplication::processEvents(); } QStringList tokens = QString(currentLine).split(QRegExp("\\s+"),QString::SkipEmptyParts); //skip comments & empty lines if( tokens.empty() || tokens.front().startsWith('/',Qt::CaseInsensitive) || tokens.front().startsWith('#',Qt::CaseInsensitive) ) { currentLine = stream.readLine(); continue; } /*** new vertex ***/ if (tokens.front() == "v") { //reserve more memory if necessary if (vertices->size() == vertices->capacity()) { if (!vertices->reserve(vertices->capacity()+MAX_NUMBER_OF_ELEMENTS_PER_CHUNK)) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } } //malformed line? if (tokens.size() < 4) { objWarnings[INVALID_LINE] = true; error = true; break; } CCVector3d Pd( tokens[1].toDouble(), tokens[2].toDouble(), tokens[3].toDouble() ); //first point: check for 'big' coordinates if (pointsRead == 0) { if (HandleGlobalShift(Pd,Pshift,parameters)) { vertices->setGlobalShift(Pshift); ccLog::Warning("[OBJ] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z); } } //shifted point CCVector3 P = CCVector3::fromArray((Pd + Pshift).u); vertices->addPoint(P); ++pointsRead; } /*** new vertex texture coordinates ***/ else if (tokens.front() == "vt") { //create and reserve memory for tex. coords container if necessary if (!texCoords) { texCoords = new TextureCoordsContainer(); texCoords->link(); } if (texCoords->currentSize() == texCoords->capacity()) { if (!texCoords->reserve(texCoords->capacity() + MAX_NUMBER_OF_ELEMENTS_PER_CHUNK)) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } } //malformed line? if (tokens.size() < 2) { objWarnings[INVALID_LINE] = true; error = true; break; } float T[2] = { T[0] = tokens[1].toFloat(), 0 }; if (tokens.size() > 2) //OBJ specification allows for only one value!!! { T[1] = tokens[2].toFloat(); } texCoords->addElement(T); ++texCoordsRead; } /*** new vertex normal ***/ else if (tokens.front() == "vn") //--> in fact it can also be a facet normal!!! { //create and reserve memory for normals container if necessary if (!normals) { normals = new NormsIndexesTableType; normals->link(); } if (normals->currentSize() == normals->capacity()) { if (!normals->reserve(normals->capacity() + MAX_NUMBER_OF_ELEMENTS_PER_CHUNK)) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } } //malformed line? if (tokens.size() < 4) { objWarnings[INVALID_LINE] = true; error = true; break; } CCVector3 N(static_cast<PointCoordinateType>(tokens[1].toDouble()), static_cast<PointCoordinateType>(tokens[2].toDouble()), static_cast<PointCoordinateType>(tokens[3].toDouble())); if (fabs(N.norm2() - 1.0) > 0.005) { objWarnings[INVALID_NORMALS] = true; N.normalize(); } CompressedNormType nIndex = ccNormalVectors::GetNormIndex(N.u); normals->addElement(nIndex); //we don't know yet if it's per-vertex or per-triangle normal... ++normsRead; } /*** new group ***/ else if (tokens.front() == "g" || tokens.front() == "o") { //update new group index facesRead = 0; //get the group name QString groupName = (tokens.size() > 1 && !tokens[1].isEmpty() ? tokens[1] : "default"); for (int i=2; i<tokens.size(); ++i) //multiple parts? groupName.append(QString(" ")+tokens[i]); //push previous group descriptor (if none was pushed) if (groups.empty() && totalFacesRead > 0) groups.push_back(std::pair<unsigned,QString>(0,"default")); //push new group descriptor if (!groups.empty() && groups.back().first == totalFacesRead) groups.back().second = groupName; //simply replace the group name if the previous group was empty! else groups.push_back(std::pair<unsigned,QString>(totalFacesRead,groupName)); polyCount = 0; //restart polyline count at 0! } /*** new face ***/ else if (tokens.front().startsWith('f')) { //malformed line? if (tokens.size() < 4) { objWarnings[INVALID_LINE] = true; currentLine = stream.readLine(); continue; //error = true; //break; } //read the face elements (singleton, pair or triplet) std::vector<facetElement> currentFace; { for (int i=1; i<tokens.size(); ++i) { QStringList vertexTokens = tokens[i].split('/'); if (vertexTokens.size() == 0 || vertexTokens[0].isEmpty()) { objWarnings[INVALID_LINE] = true; error = true; break; } else { //new vertex facetElement fe; //(0,0,0) by default fe.vIndex = vertexTokens[0].toInt(); if (vertexTokens.size() > 1 && !vertexTokens[1].isEmpty()) fe.tcIndex = vertexTokens[1].toInt(); if (vertexTokens.size() > 2 && !vertexTokens[2].isEmpty()) fe.nIndex = vertexTokens[2].toInt(); currentFace.push_back(fe); } } } if (error) break; if (currentFace.size() < 3) { ccLog::Warning("[OBJ] Malformed file: polygon on line %1 has less than 3 vertices!",lineCount); error = true; break; } //first vertex std::vector<facetElement>::iterator A = currentFace.begin(); //the very first vertex of the group tells us about the whole sequence if (facesRead == 0) { //we have a tex. coord index as second vertex element! if (!hasTexCoords && A->tcIndex != 0 && !materialsLoadFailed) { if (!baseMesh->reservePerTriangleTexCoordIndexes()) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } for (unsigned int i=0; i<totalFacesRead; ++i) baseMesh->addTriangleTexCoordIndexes(-1, -1, -1); hasTexCoords = true; } //we have a normal index as third vertex element! if (!normalsPerFacet && A->nIndex != 0) { //so the normals are 'per-facet' if (!baseMesh->reservePerTriangleNormalIndexes()) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } for (unsigned int i=0; i<totalFacesRead; ++i) baseMesh->addTriangleNormalIndexes(-1, -1, -1); normalsPerFacet = true; } } //we process all vertices accordingly for (std::vector<facetElement>::iterator it = currentFace.begin() ; it!=currentFace.end(); ++it) { facetElement& vertex = *it; //vertex index { if (!vertex.updatePointIndex(pointsRead)) { objWarnings[INVALID_INDEX] = true; error = true; break; } if (vertex.vIndex > maxVertexIndex) maxVertexIndex = vertex.vIndex; } //should we have a tex. coord index as second vertex element? if (hasTexCoords && currentMaterialDefined) { if (!vertex.updateTexCoordIndex(texCoordsRead)) { objWarnings[INVALID_INDEX] = true; error = true; break; } if (vertex.tcIndex > maxTexCoordIndex) maxTexCoordIndex = vertex.tcIndex; } //should we have a normal index as third vertex element? if (normalsPerFacet) { if (!vertex.updateNormalIndex(normsRead)) { objWarnings[INVALID_INDEX] = true; error = true; break; } if (vertex.nIndex > maxTriNormIndex) maxTriNormIndex = vertex.nIndex; } } //don't forget material (common for all vertices) if (currentMaterialDefined && !materialsLoadFailed) { if (!hasMaterial) { if (!baseMesh->reservePerTriangleMtlIndexes()) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } for (unsigned int i=0; i<totalFacesRead; ++i) baseMesh->addTriangleMtlIndex(-1); hasMaterial = true; } } if (error) break; //Now, let's tesselate the whole polygon //FIXME: yeah, we do very ulgy tesselation here! std::vector<facetElement>::const_iterator B = A+1; std::vector<facetElement>::const_iterator C = B+1; for ( ; C != currentFace.end(); ++B,++C) { //need more space? if (baseMesh->size() == baseMesh->capacity()) { if (!baseMesh->reserve(baseMesh->size()+128)) { objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; break; } } //push new triangle baseMesh->addTriangle(A->vIndex, B->vIndex, C->vIndex); ++facesRead; ++totalFacesRead; if (hasMaterial) baseMesh->addTriangleMtlIndex(currentMaterial); if (hasTexCoords) baseMesh->addTriangleTexCoordIndexes(A->tcIndex, B->tcIndex, C->tcIndex); if (normalsPerFacet) baseMesh->addTriangleNormalIndexes(A->nIndex, B->nIndex, C->nIndex); } } /*** polyline ***/ else if (tokens.front().startsWith('l')) { //malformed line? if (tokens.size() < 3) { objWarnings[INVALID_LINE] = true; currentLine = stream.readLine(); continue; } //read the face elements (singleton, pair or triplet) ccPolyline* polyline = new ccPolyline(vertices); if (!polyline->reserve(static_cast<unsigned>(tokens.size()-1))) { //not enough memory objWarnings[NOT_ENOUGH_MEMORY] = true; delete polyline; polyline = 0; currentLine = stream.readLine(); continue; } for (int i=1; i<tokens.size(); ++i) { //get next polyline's vertex index QStringList vertexTokens = tokens[i].split('/'); if (vertexTokens.size() == 0 || vertexTokens[0].isEmpty()) { objWarnings[INVALID_LINE] = true; error = true; break; } else { int index = vertexTokens[0].toInt(); //we ignore normal index (if any!) if (!UpdatePointIndex(index,pointsRead)) { objWarnings[INVALID_INDEX] = true; error = true; break; } polyline->addPointIndex(index); } } if (error) { delete polyline; polyline = 0; break; } polyline->setVisible(true); QString name = groups.empty() ? QString("Line") : groups.back().second+QString(".line"); polyline->setName(QString("%1 %2").arg(name).arg(++polyCount)); vertices->addChild(polyline); } /*** material ***/ else if (tokens.front() == "usemtl") //see 'MTL file' below { if (materials) //otherwise we have failed to load MTL file!!! { QString mtlName = currentLine.mid(7).trimmed(); //DGM: in case there's space characters in the material name, we must read it again from the original line buffer //QString mtlName = (tokens.size() > 1 && !tokens[1].isEmpty() ? tokens[1] : ""); currentMaterial = (!mtlName.isEmpty() ? materials->findMaterialByName(mtlName) : -1); currentMaterialDefined = true; } } /*** material file (MTL) ***/ else if (tokens.front() == "mtllib") { //malformed line? if (tokens.size() < 2 || tokens[1].isEmpty()) { objWarnings[INVALID_LINE] = true; } else { //we build the whole MTL filename + path //DGM: in case there's space characters in the filename, we must read it again from the original line buffer //QString mtlFilename = tokens[1]; QString mtlFilename = currentLine.mid(7).trimmed(); ccLog::Print(QString("[OBJ] Material file: ")+mtlFilename); QString mtlPath = QFileInfo(filename).canonicalPath(); //we try to load it if (!materials) { materials = new ccMaterialSet("materials"); materials->link(); } size_t oldSize = materials->size(); QStringList errors; if (ccMaterialSet::ParseMTL(mtlPath,mtlFilename,*materials,errors)) { ccLog::Print("[OBJ] %i materials loaded",materials->size()-oldSize); materialsLoadFailed = false; } else { ccLog::Error(QString("[OBJ] Failed to load material file! (should be in '%1')").arg(mtlPath+'/'+QString(mtlFilename))); materialsLoadFailed = true; } if (!errors.empty()) { for (int i=0; i<errors.size(); ++i) ccLog::Warning(QString("[OBJ::Load::MTL parser] ")+errors[i]); } if (materials->empty()) { materials->release(); materials=0; materialsLoadFailed = true; } } } ///*** shading group ***/ //else if (tokens.front() == "s") //{ // //ignored! //} if (error) break; currentLine = stream.readLine(); } } catch (const std::bad_alloc&) { //not enough memory objWarnings[NOT_ENOUGH_MEMORY] = true; error = true; } file.close(); //1st check if (!error && pointsRead == 0) { //of course if there's no vertex, that's the end of the story ... ccLog::Warning("[OBJ] Malformed file: no vertex in file!"); error = true; } if (!error) { ccLog::Print("[OBJ] %i points, %u faces",pointsRead,totalFacesRead); if (texCoordsRead > 0 || normsRead > 0) ccLog::Print("[OBJ] %i tex. coords, %i normals",texCoordsRead,normsRead); //do some cleaning vertices->shrinkToFit(); if (normals) normals->shrinkToFit(); if (texCoords) texCoords->shrinkToFit(); if (baseMesh->size() == 0) { delete baseMesh; baseMesh = 0; } else { baseMesh->shrinkToFit(); } if ( maxVertexIndex >= pointsRead || maxTexCoordIndex >= texCoordsRead || maxTriNormIndex >= normsRead) { //hum, we've got a problem here ccLog::Warning("[OBJ] Malformed file: indexes go higher than the number of elements! (v=%i/tc=%i/n=%i)",maxVertexIndex,maxTexCoordIndex,maxTriNormIndex); if (maxVertexIndex >= pointsRead) { error = true; } else { objWarnings[INVALID_INDEX] = true; if (maxTexCoordIndex >= texCoordsRead) { texCoords->release(); texCoords = 0; materials->release(); materials = 0; } if (maxTriNormIndex >= normsRead) { normals->release(); normals = 0; } } } if (!error && baseMesh) { if (normals && normalsPerFacet) { baseMesh->setTriNormsTable(normals); baseMesh->showTriNorms(true); } if (materials) { baseMesh->setMaterialSet(materials); baseMesh->showMaterials(true); } if (texCoords) { if (materials) { baseMesh->setTexCoordinatesTable(texCoords); } else { ccLog::Warning("[OBJ] Texture coordinates were defined but no material could be loaded!"); } } //normals: if the obj file doesn't provide any, should we compute them? if (!normals) { //DGM: normals can be per-vertex or per-triangle so it's better to let the user do it himself later //Moreover it's not always good idea if the user doesn't want normals (especially in ccViewer!) //if (!materials && !baseMesh->hasColors()) //yes if no material is available! //{ // ccLog::Print("[OBJ] Mesh has no normal! We will compute them automatically"); // baseMesh->computeNormals(); // baseMesh->showNormals(true); //} //else { ccLog::Warning("[OBJ] Mesh has no normal! You can manually compute them (select it then call \"Edit > Normals > Compute\")"); } } //create sub-meshes if necessary ccLog::Print("[OBJ] 1 mesh loaded - %i group(s)", groups.size()); if (groups.size() > 1) { for (size_t i=0; i<groups.size(); ++i) { const QString& groupName = groups[i].second; unsigned startIndex = groups[i].first; unsigned endIndex = (i+1 == groups.size() ? baseMesh->size() : groups[i+1].first); if (startIndex == endIndex) { continue; } ccSubMesh* subTri = new ccSubMesh(baseMesh); if (subTri->reserve(endIndex-startIndex)) { subTri->addTriangleIndex(startIndex,endIndex); subTri->setName(groupName); subTri->showMaterials(baseMesh->materialsShown()); subTri->showNormals(baseMesh->normalsShown()); subTri->showTriNorms(baseMesh->triNormsShown()); //subTri->showColors(baseMesh->colorsShown()); //subTri->showWired(baseMesh->isShownAsWire()); baseMesh->addChild(subTri); } else { delete subTri; subTri = 0; objWarnings[NOT_ENOUGH_MEMORY] = true; } } baseMesh->setVisible(false); vertices->setLocked(true); } baseMesh->addChild(vertices); //DGM: we can't deactive the vertices if it has children! (such as polyline) if (vertices->getChildrenNumber() != 0) vertices->setVisible(false); else vertices->setEnabled(false); container.addChild(baseMesh); } if (!baseMesh && vertices->size() != 0) { //no (valid) mesh! container.addChild(vertices); //we hide the vertices if the entity has children (probably polylines!) if (vertices->getChildrenNumber() != 0) { vertices->setVisible(false); } } //special case: normals held by cloud! if (normals && !normalsPerFacet) { if (normsRead == pointsRead) //must be 'per-vertex' normals { vertices->setNormsTable(normals); if (baseMesh) baseMesh->showNormals(true); } else { ccLog::Warning("File contains normals which seem to be neither per-vertex nor per-face!!! We had to ignore them..."); } } } if (error) { if (baseMesh) delete baseMesh; if (vertices) delete vertices; } //release shared structures if (normals) { normals->release(); normals = 0; } if (texCoords) { texCoords->release(); texCoords = 0; } if (materials) { materials->release(); materials = 0; } pDlg.close(); //potential warnings if (objWarnings[INVALID_NORMALS]) ccLog::Warning("[OBJ] Some normals in file were invalid. You should re-compute them (select entity, then \"Edit > Normals > Compute\")"); if (objWarnings[INVALID_INDEX]) ccLog::Warning("[OBJ] File is malformed! Check indexes..."); if (objWarnings[NOT_ENOUGH_MEMORY]) ccLog::Warning("[OBJ] Not enough memory!"); if (objWarnings[INVALID_LINE]) ccLog::Warning("[OBJ] File is malformed! Missing data."); if (error) { if (objWarnings[NOT_ENOUGH_MEMORY]) return CC_FERR_NOT_ENOUGH_MEMORY; else if (objWarnings[CANCELLED_BY_USER]) return CC_FERR_CANCELED_BY_USER; else return CC_FERR_MALFORMED_FILE; } else { return CC_FERR_NO_ERROR; } }
CC_FILE_ERROR VTKFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters) { //open ASCII file for reading QFile file(filename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return CC_FERR_READING; QTextStream inFile(&file); //read header QString nextline = inFile.readLine(); if (!nextline.startsWith("# vtk")) return CC_FERR_MALFORMED_FILE; //comment nextline = inFile.readLine(); ccLog::Print(QString("[VTK] ")+nextline); ccMesh* mesh = 0; ccPointCloud* vertices = 0; std::vector<int> indexes; //global so as to avoid unnecessary mem. allocations QString lastSfName; bool acceptLookupTables = true; unsigned lastDataSize = 0; QString fileType = inFile.readLine().toUpper(); if (fileType.startsWith("BINARY")) { //binary not supported yet! ccLog::Error("VTK binary format not supported yet!"); return CC_FERR_WRONG_FILE_TYPE; } else if (fileType.startsWith("ASCII")) { //allow blank lines QString dataType; if (!GetNextNonEmptyLine(inFile,dataType)) return CC_FERR_MALFORMED_FILE; if (!dataType.startsWith("DATASET")) return CC_FERR_MALFORMED_FILE; dataType.remove(0,8); if (dataType.startsWith("POLYDATA")) { vertices = new ccPointCloud("vertices"); mesh = new ccMesh(vertices); } else if (dataType.startsWith("UNSTRUCTURED_GRID")) { vertices = new ccPointCloud("unnamed - VTK unstructured grid"); } else { ccLog::Error(QString("VTK entity '%1' is not supported!").arg(dataType)); return CC_FERR_WRONG_FILE_TYPE; } } //loop on keywords/data CC_FILE_ERROR error = CC_FERR_NO_ERROR; CCVector3d Pshift(0,0,0); bool skipReadLine = false; while (error == CC_FERR_NO_ERROR) { if (!skipReadLine && !GetNextNonEmptyLine(inFile,nextline)) break; //end of file skipReadLine = false; assert(!nextline.isEmpty()); if (nextline.startsWith("POINTS")) { QStringList parts = nextline.split(" ",QString::SkipEmptyParts); if (parts.size() != 3) { error=CC_FERR_MALFORMED_FILE; break; } bool ok = false; unsigned ptsCount = parts[1].toInt(&ok); if (!ok) { error = CC_FERR_MALFORMED_FILE; break; } //QString dataFormat = parts[3].toUpper(); //char buffer[8]; //unsigned char datSize = 4; //if (dataFormat == "DOUBLE") //{ // datSize = 8; //} //else if (dataFormat != "FLOAT") //{ // ccLog::Error(QString("Non floating point data (%1) is not supported!").arg(dataFormat)); // error = CC_FERR_WRONG_FILE_TYPE; // break; //} if (!vertices->reserve(ptsCount)) { error = CC_FERR_NOT_ENOUGH_MEMORY; break; } //warning: multiple points can be stored on a single line! unsigned iPt = 0; CCVector3d Pd(0,0,0); unsigned coordIndex = 0; while (iPt < ptsCount) { nextline = inFile.readLine(); parts = nextline.split(" ",QString::SkipEmptyParts); for (int i=0; i<parts.size(); ++i) { Pd.u[coordIndex] = parts[i].toDouble(&ok); if (!ok) { ccLog::Warning("[VTK] Element #%1 of POINTS data is corrupted!",iPt); error = CC_FERR_MALFORMED_FILE; iPt = ptsCount; break; } if (coordIndex == 2) { //first point: check for 'big' coordinates if (iPt == 0) { if (HandleGlobalShift(Pd,Pshift,parameters)) { vertices->setGlobalShift(Pshift); ccLog::Warning("[VTKFilter::loadFile] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z); } } CCVector3 P = CCVector3::fromArray((Pd + Pshift).u); vertices->addPoint(P); coordIndex = 0; ++iPt; } else { ++coordIndex; } } } //end POINTS } else if (nextline.startsWith("POLYGONS") || nextline.startsWith("TRIANGLE_STRIPS")) { QStringList parts = nextline.split(" ",QString::SkipEmptyParts); if (parts.size() != 3) { error = CC_FERR_MALFORMED_FILE; break; } //current type name (i.e. POLYGONS or TRIANGLE_STRIPS) QString typeName = parts[0]; bool isPolygon = (typeName == "POLYGONS"); bool ok = false; unsigned elemCount = parts[1].toUInt(&ok); if (!ok) { error = CC_FERR_MALFORMED_FILE; break; } // unsigned totalElements = parts[2].toUInt(&ok); if (!ok) { error = CC_FERR_MALFORMED_FILE; break; } assert(mesh); if (!mesh) { ccLog::Warning(QString("[VTK] We found %1 data while file is not composed of POLYDATA!").arg(typeName)); mesh = new ccMesh(vertices); //however, we can still try to load it? } for (unsigned i=0; i<elemCount; ++i) { nextline = inFile.readLine(); parts = nextline.split(" ",QString::SkipEmptyParts); if (parts.empty()) { error = CC_FERR_MALFORMED_FILE; break; } unsigned vertCount = parts[0].toUInt(&ok); if (!ok || static_cast<int>(vertCount) >= parts.size()) { error = CC_FERR_MALFORMED_FILE; break; } else if (vertCount < 3) { ccLog::Warning(QString("[VTK] Element #%1 of %2 data is corrupted! (not enough indexes)").arg(i).arg(typeName)); } if (isPolygon && (vertCount != 3 && vertCount != 4)) //quads are easy to handle as well! { ccLog::Warning(QString("[VTK] POLYGON element #%1 has an unhandled size (> 4 vertices)").arg(i)); continue; } //reserve mem to. store indexes if (indexes.size() < vertCount) { try { indexes.resize(vertCount); } catch (const std::bad_alloc&) { error = CC_FERR_NOT_ENOUGH_MEMORY; break; } } //decode indexes for (unsigned j=0; j<vertCount; ++j) { indexes[j] = parts[j+1].toUInt(&ok); if (!ok) { ccLog::Warning(QString("[VTK] Element #%1 of %2 data is corrupted! (invalid index value)").arg(i).arg(typeName)); error = CC_FERR_MALFORMED_FILE; break; } } //add the triangles { assert(vertCount > 2); unsigned triCount = vertCount-2; if (mesh->size() + triCount > mesh->maxSize()) { if (!mesh->reserve(mesh->size()+triCount+256)) //take some advance to avoid too many allocations { error = CC_FERR_NOT_ENOUGH_MEMORY; break; } } if (isPolygon) { //triangle or quad mesh->addTriangle(indexes[0],indexes[1],indexes[2]); if (vertCount == 4) mesh->addTriangle(indexes[0],indexes[2],indexes[3]); } else { //triangle strip for (unsigned j=0; j<triCount; ++j) mesh->addTriangle(indexes[j],indexes[j+1],indexes[j+2]); } } } if (mesh->size() != 0 && mesh->size() < mesh->maxSize()) { mesh->resize(mesh->size()); } //end POLYGONS or TRIANGLE_STRIPS } else if (nextline.startsWith("NORMALS")) { if (lastDataSize == 0) lastDataSize = vertices->size(); if (lastDataSize == 0) { error = CC_FERR_MALFORMED_FILE; break; } bool loadNormals = false; if (lastDataSize == vertices->size()) { if (!vertices->reserveTheNormsTable()) ccLog::Warning("[VTK] Not enough memory to load normals!"); else loadNormals = true; } //warning: multiple normals can be stored on a single line! unsigned iNorm = 0; CCVector3 N; unsigned coordIndex = 0; while (iNorm < lastDataSize) { nextline = inFile.readLine(); QStringList parts = nextline.split(" ",QString::SkipEmptyParts); for (int i=0; i<parts.size(); ++i) { bool ok; N.u[coordIndex] = static_cast<PointCoordinateType>(parts[i].toDouble(&ok)); if (!ok) { ccLog::Warning("[VTK] Element #%1 of NORMALS data is corrupted!",iNorm); error = CC_FERR_MALFORMED_FILE; iNorm = lastDataSize; break; } if (coordIndex == 2) { if (loadNormals) vertices->addNorm(N); coordIndex = 0; ++iNorm; } else { ++coordIndex; } } } lastDataSize = 0; //lastDataSize is consumed //end NORMALS } else if (nextline.startsWith("COLOR_SCALARS")) { if (lastDataSize == 0) lastDataSize = vertices->size(); if (lastDataSize == 0) { error = CC_FERR_MALFORMED_FILE; break; } bool loadRGBColors = vertices->reserveTheRGBTable(); if (!loadRGBColors) ccLog::Warning("[VTK] Not enough memory to load RGB colors!"); //warning: multiple colors can be stored on a single line! unsigned iCol = 0; colorType rgb[3]; unsigned coordIndex = 0; while (iCol < lastDataSize) { nextline = inFile.readLine(); QStringList parts = nextline.split(" ",QString::SkipEmptyParts); for (int i=0; i<parts.size(); ++i) { bool ok; rgb[coordIndex] = static_cast<colorType>(parts[i].toDouble(&ok) * ccColor::MAX); if (!ok) { ccLog::Warning("[VTK] Element #%1 of COLOR_SCALARS data is corrupted!",iCol); error = CC_FERR_MALFORMED_FILE; iCol = lastDataSize; break; } if (coordIndex == 2) { if (loadRGBColors) vertices->addRGBColor(rgb); coordIndex = 0; ++iCol; } else { ++coordIndex; } } } lastDataSize = 0; //lastDataSize is consumed //end COLOR_SCALARS } else if (nextline.startsWith("SCALARS")) { QStringList parts = nextline.split(" ",QString::SkipEmptyParts); lastSfName = "ScalarField"; if (parts.size() > 1) lastSfName = parts[1].replace("_"," "); //SF already exists? if (vertices->getScalarFieldIndexByName(qPrintable(lastSfName)) >= 0) lastSfName += QString(" (%1)").arg(vertices->getNumberOfScalarFields()); //end of SCALARS } else if (nextline.startsWith("LOOKUP_TABLE") || nextline.startsWith("VECTORS")) { bool expected = (lastDataSize != 0); assert(!acceptLookupTables || expected); //i.e. lastDataSize shouldn't be 0 for 'accepted' lookup tables QStringList parts = nextline.split(" ",QString::SkipEmptyParts); QString itemName = parts[0]; if (parts.size() > 2) { bool ok = false; int valCount = parts[2].toUInt(&ok); if (ok) lastDataSize = valCount; } else if (!expected) { ccLog::Warning(QString("[VTK] field %1 has no size?!").arg(itemName)); error = CC_FERR_MALFORMED_FILE; break; } bool createSF = (vertices->size() == lastDataSize && vertices->size() != 0); if (acceptLookupTables && !createSF) { ccLog::Warning(QString("[VTK] field %1 has not the right number of points (will be ignored)").arg(itemName)); } createSF &= (acceptLookupTables || expected); if (createSF && lastSfName.isNull()) { ccLog::Warning(QString("[VTK] field %1 has no name (will be ignored)").arg(itemName)); createSF = false; } else if (!expected) { ccLog::Warning(QString("[VTK] field %1 was not expected (will be ignored)").arg(itemName)); } //create scalar field? ccScalarField* sf = 0; if (createSF) { sf = new ccScalarField(qPrintable(lastSfName)); if (!sf->reserve(lastDataSize)) { ccLog::Warning(QString("[VTK] Not enough memory to load scalar field' %1' (will be ignored)").arg(lastSfName)); sf->release(); sf = 0; } } lastSfName.clear(); //name is "consumed" //warning: multiple colors can be stored on a single line! unsigned iScal = 0; while (iScal < lastDataSize) { nextline = inFile.readLine(); QStringList parts = nextline.split(" ",QString::SkipEmptyParts); if (expected) { for (int i=0; i<parts.size(); ++i) { bool ok; ScalarType d = static_cast<ScalarType>(parts[i].toDouble(&ok)); if (!ok) { ccLog::Warning("[VTK] Element #%1 of LOOKUP_TABLE/VECTORS data is corrupted!",iScal); error = CC_FERR_MALFORMED_FILE; if (sf) { sf->release(); sf = 0; } iScal = lastDataSize; break; } if (sf) sf->addElement(d); ++iScal; } } else { //hard to guess the right format, but an unexpected field seem to always be //organized as 'one element per line' ++iScal; } } lastDataSize = 0; //lastDataSize is "consumed" acceptLookupTables = false; if (sf) { sf->computeMinAndMax(); int newSFIndex = vertices->addScalarField(sf); if (newSFIndex == 0) vertices->setCurrentDisplayedScalarField(newSFIndex); vertices->showSF(true); } //end of SCALARS } else if (nextline.startsWith("POINT_DATA")) { //check that the number of 'point_data' match the number of points QStringList parts = nextline.split(" ",QString::SkipEmptyParts); acceptLookupTables = false; if (parts.size() > 1) { bool ok; lastDataSize = parts[1].toUInt(&ok); acceptLookupTables = ok && vertices; } } else if (nextline.startsWith("FIELD")) { QStringList parts = nextline.split(" ",QString::SkipEmptyParts); if (parts.size() < 2) { error = CC_FERR_MALFORMED_FILE; break; } bool ok; unsigned elements = parts[2].toUInt(&ok); if (!ok) { error = CC_FERR_MALFORMED_FILE; break; } elements *= 2; //we don't know how to handle those properly but at least //we know that for FIELD elements, there's 2 lines per element... for (unsigned i=0; i<elements; ++i) { inFile.readLine(); //ignore } } else //unhandled property (CELLS, CELL_TYPES, etc.) { QStringList parts = nextline.split(" ",QString::SkipEmptyParts); if (parts.size() < 2) { ccLog::Warning(QString("[VTK] Unhandled element: %1").arg(parts[0])); error = CC_FERR_MALFORMED_FILE; break; } bool ok; unsigned elements = parts[1].toUInt(&ok); if (!ok) { error = CC_FERR_MALFORMED_FILE; break; } if (nextline.startsWith("CELL_DATA")) { //read next line (in case we actually know how to read it! if (!GetNextNonEmptyLine(inFile,nextline)) { error = CC_FERR_MALFORMED_FILE; break; } skipReadLine = true; if ( nextline.startsWith("SCALARS") || nextline.startsWith("NORMALS") || nextline.startsWith("COLOR_SCALARS")) { lastDataSize = elements; acceptLookupTables = false; //this property is for triangles! continue; } } //we'll try to blindly skip the elements... for (unsigned i=0; i<elements; ++i) { inFile.readLine(); //ignore } //end unhandled property } if (error != CC_FERR_NO_ERROR) break; } file.close(); if (vertices && vertices->size() == 0) { delete vertices; vertices = 0; if (error == CC_FERR_NO_ERROR) error = CC_FERR_NO_LOAD; } if (mesh && (mesh->size() == 0 || vertices == 0)) { delete mesh; mesh = 0; if (error == CC_FERR_NO_ERROR) error = CC_FERR_NO_LOAD; } if (mesh) { container.addChild(mesh); mesh->setVisible(true); mesh->addChild(vertices); vertices->setEnabled(false); vertices->setName("Vertices"); vertices->setLocked(true); //DGM: no need to lock it as it is only used by one mesh! //DGM: normals can be per-vertex or per-triangle so it's better to let the user do it himself later //Moreover it's not always good idea if the user doesn't want normals (especially in ccViewer!) if (!mesh->hasNormals()) { // mesh->computeNormals(); ccLog::Warning("[VTK] Mesh has no normal! You can manually compute them (select it then call \"Edit > Normals > Compute\")"); } mesh->showNormals(mesh->hasNormals()); if (vertices->hasScalarFields()) { vertices->setCurrentDisplayedScalarField(0); mesh->showSF(true); } if (vertices->hasColors()) mesh->showColors(true); } else if (vertices) { container.addChild(vertices); vertices->setVisible(true); if (vertices->hasNormals()) vertices->showNormals(true); if (vertices->hasScalarFields()) { vertices->setCurrentDisplayedScalarField(0); vertices->showSF(true); } if (vertices->hasColors()) vertices->showColors(true); } return error; }
void Ship::output(){ ofstream file; file.open("Report.txt"); file << "[table]" << endl; cout << fixed << setprecision(2) << "Length: \t\t\t\t" << v.Lpp << " m" << endl; file << fixed << setprecision(2) << "[tr][td]Length: \t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t[/td][td]" << v.Lpp << " m[/td][/tr]" << endl; cout << "Beam: \t\t\t\t\t" << v.B << " m" << endl; file << "[tr][td]Beam: [/td][td]" << v.B << " m[/td][/tr]" << endl; cout << "Draft: \t\t\t\t\t" << v.D << " m" << endl; file << "[tr][td]Draft: [/td][td]" << v.D << " m[/td][/tr]" << endl; cout << "Freeboard: \t\t\t\t" << v.fB << " m" << endl; file << "[tr][td]Freeboard: [/td][td]" << v.fB << " m[/td][/tr]" << endl; cout << setprecision(3) << "Block Coefficient: \t\t\t" << Cb() << endl; file << setprecision(3) << "[tr][td]Block Coefficient: [/td][td]" << Cb() << "[/td][/tr]" << endl; cout << setprecision(0) << "Displacement: \t\t\t\t" << Vol() << " t" << endl; file << setprecision(0) << "[tr][td]Displacement: [/td][td]" << Vol() << " t[/td][/tr]" << endl; cout << "Lightship: \t\t\t\t" << Wh() + Wwo() + Wm() + We() + Wspus() + Bunker() << " t" << endl; file << "[tr][td]Lightship: [/td][td]" << Lightship() << " t[/td][/tr]" << endl; cout << setprecision(1) << "\nMax Speed: \t\t\t\t" << v.Vk << " kn" << endl; file << setprecision(1) << "\n[tr][td]Max Speed: [/td][td]" << v.Vk << " kn[/td][/tr]" << endl; cout << "Cruise Speed: \t\t\t\t" << v.Vc << " kn / " << v.Range << " nm" << endl; file << "[tr][td]Cruise Speed: [/td][td]" << v.Vc << " kn / " << v.Range << " nm[/td][/tr]" << endl; cout << "Engine: \t\t\t\t"; file << "[tr][td]Engine: [/td][td]"; switch(e.Gear){ case Direct: cout << "Direct "; file << "Direct "; break; case Geared: cout << "Geared "; file << "Geared "; break; case Turbo_Electric: cout << "Turbo-Electric "; file << "Turbo-Electric "; break; default: cout << "Unknown"; file << "Unknown"; } switch(e.Eng){ case Diesel2stk: cout << "Two Stroke Diesel" << endl; file << "Two Stroke Diesel"; break; case Diesel4stk: cout << "Four Stroke Diesel" << endl; file << "Four Stroke Diesel" << endl; break; case QuadExp: cout << "Quadruple Expansion Reciprocating Engine" << endl; file << "Quadruple Expansion Reciprocating Engine"; break; case TripExp: cout << "Triple Expansion Reciprocating Engine" << endl; file << "Triple Expansion Reciprocating Engine"; break; case SimExp: cout << "Simple Reciprocating Engine" << endl; file << "Simple Reciprocating Engine"; break; case SteamTur: cout << "Steam Turbine" << endl; file << "Steam Turbine"; break; default: cout << endl; } file << "[/td][/tr]" << endl; cout << setprecision(0) << "Power Delivered: \t\t\t" << Pd(v.Vk) << " hp" << endl; file << setprecision(0) << "[tr][td]Power Delivered: [/td][td]" << Pd(v.Vk) << " hp[/td][/tr]" << endl; cout << setprecision(2) << "Total Efficiency: \t\t\t" << NUt()*100 << "%" << endl; file << setprecision(2) << "[tr][td]Total Efficiency: [/td][td]" << NUt()*100 << "%[/td][/tr]" << endl; cout << setprecision(3) << "Froude Number: \t\t\t\t" << Fn() << endl; file << setprecision(3) << "[tr][td]Froude Number: [/td][td]" << Fn() << "[/td][/tr]" << endl; cout << setprecision(0) << "Bunker Size: \t\t\t\t" << Bunker() << " t" << endl; file << setprecision(0) << "[tr][td]Bunker Size: [/td][td]" << Bunker() << " t[/td][/tr]" << endl; cout << "Service Allowance: \t\t\t" << e.SA << "%" << endl; file << "[tr][td]Service Allowance: [/td][td]" << e.SA << "%[/td][/tr]" << endl; cout << setprecision(2); file << setprecision(2); cout << "Length of Superstructure: \t\t" << v.Lspus << " m" << endl; file << "[tr][td]Length of Superstructure: [/td][td]" << v.Lspus << " m[/td][/tr]" << endl; cout << "Aftbody Shape: \t\t\t\t"; file << "[tr][td]Aftbody Shape: [/td][td]"; switch(e.Faa){ case V: cout << "V" << endl; file << "V"; break; case U: cout << "U" << endl; file << "U"; break; case N: cout << "N" << endl; file << "N"; break; default: cout << "N" << endl; file << "N"; } file << "[/td][/tr]"; cout << "\nLongitudinal Center of Buoyancy: \t" << lcb() << "%" << endl; file << "\n[tr][td]Longitudinal Center of Buoyancy: [/td][td]" << lcb() << "% / " << lcb()*v.Lpp << " m from midpoint[/td][/tr]" << endl; cout << "Longitudinal Center of Gravity: \t" << lcg() << "%" << endl; file << "[tr][td]Longitudinal Center of Gravity: [/td][td]" << lcg() << "% / " << lcg()*v.Lpp << " m from midpoint[/td][/tr]" << endl; cout << "Vertical Center of Gravity: \t\t" << KGh() << " m" << endl; file << "[tr][td]Vertical Center of Gravity: [/td][td]" << KGh() << " m[/td][/tr]" << endl; cout << "Metacentric Height: \t\t\t" << GM() << " m" << endl; file << "[tr][td]Metacentric Height: [/td][td]" << GM() << " m[/td][/tr]" << endl; cout << "Roll Period: \t\t\t\t" << TR() << " s" << endl; file << "[tr][td]Roll Period: [/td][td]" << TR() << " s[/td][/tr]" << endl; cout << "\nBow Entrance Angle: \t\t\t" << iE() << " deg" << endl; file << "\n[tr][td]Bow Entrance Angle: [/td][td]" << iE() << " deg[/td][/tr]" << endl; cout << "Length of Engine Room: \t\t\t" << Lcm() << " m" << endl; file << "[tr][td]Length of Engine Room: [/td][td]" << Lcm() << " m[/td][/tr]" << endl; cout << setprecision(0) << "\nMain Belt: \t\t\t\t" << arm.mb_Ttop << " / " << arm.mb_Tbot << " mm at " << arm.b_deg << " degrees, " << arm.b_L << " m long with " << arm.b_H << " m above and " << arm.b_Db << " m below water" << endl; file << setprecision(0) << "\n[tr][td]Main Belt: [/td][td]" << arm.mb_Ttop << " / " << arm.mb_Tbot << " mm, " << arm.b_L << " m long with " << arm.b_H << " m above and " << arm.b_Db << " m below water[/td][/tr]" << endl; cout << "End Belt: \t\t\t\t" << arm.eb_Ttop << " / " << arm.eb_Tbot << " mm" << endl; file << "[tr][td]End Belt: [/td][td]" << arm.eb_Ttop << " / " << arm.eb_Tbot << " mm[/td][/tr]" << endl; cout << "Upper Belt: \t\t\t\t" << arm.ub_Ttop << " / " << arm.ub_Tbot << " mm, " << arm.b_uL << " m long" << endl; file << "[tr][td]Upper Belt: [/td][td]" << arm.ub_Ttop << " / " << arm.ub_Tbot << " mm, " << arm.b_uL << " m long[/td][/tr]" << endl; cout << "Main Deck: \t\t\t\t" << arm.md_T << " mm covering " << arm.md_P << "% / " << arm.md_P * v.Lpp << " m of deck" << endl; file << "[tr][td]Main Deck: [/td][td]" << arm.md_T << " m covering " << arm.md_P << "% / " << arm.md_P * v.Lpp << " m of deck[/td][/tr]" << endl; cout << "Weather Deck: \t\t\t\t" << arm.wd_T << " mm covering " << arm.wd_P << "% / " << arm.wd_P * v.Lpp << " m of deck" << endl; file << "[tr][td]Weather Deck: [/td][td]" << arm.wd_T << " m covering " << arm.wd_P << "% / " << arm.wd_P * v.Lpp << " m of deck[/td][/tr]" << endl; cout << "Splinter Deck: \t\t\t\t" << arm.sd_T << " mm covering " << arm.sd_P << "% / " << arm.sd_P * v.Lpp << " m of deck" << endl; file << "[tr][td]Splinter Deck: [/td][td]" << arm.sd_T << " m covering " << arm.sd_P << "% / " << arm.sd_P * v.Lpp << " m of deck[/td][/tr]" << endl; cout << "Ends Deck: \t\t\t\t" << arm.ed_T << " mm" << endl; file << "[tr][td]Ends Deck: [/td][td]" << arm.ed_T << " mm[/td][/tr]" << endl; cout << "Bulkhead: \t\t\t\t" << arm.blk_T << " mm in " << arm.blk_Lct << "x" << arm.blk_D << " m layers, " << arm.blk_L << " m long, " << arm.blk_H << " m tall" << endl; file << "[tr][td]Bulkhead: [/td][td]" << arm.blk_T << " mm in " << arm.blk_Lct << "x" << arm.blk_D << " m layers, " << arm.blk_L << " m long, " << arm.blk_H << " m tall[/td][/tr]" << endl; file << "[/table]" << endl; file.close(); }
CC_FILE_ERROR OFFFilter::loadFile(QString filename, ccHObject& container, LoadParameters& parameters) { //try to open file QFile fp(filename); if (!fp.open(QIODevice::ReadOnly | QIODevice::Text)) return CC_FERR_READING; QTextStream stream(&fp); QString currentLine = stream.readLine(); if (!currentLine.toUpper().startsWith("OFF")) return CC_FERR_MALFORMED_FILE; //check if the number of vertices/faces/etc. are on the first line (yes it happens :( ) QStringList tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); if (tokens.size() == 4) { tokens.removeAt(0); } else { currentLine = GetNextLine(stream); //end of file already?! if (currentLine.isNull()) return CC_FERR_MALFORMED_FILE; //read the number of vertices/faces tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); if (tokens.size() < 2/*3*/) //should be 3 but we only use the 2 firsts... return CC_FERR_MALFORMED_FILE; } bool ok = false; unsigned vertCount = tokens[0].toUInt(&ok); if (!ok) return CC_FERR_MALFORMED_FILE; unsigned triCount = tokens[1].toUInt(&ok); if (!ok) return CC_FERR_MALFORMED_FILE; //create cloud and reserve some memory ccPointCloud* vertices = new ccPointCloud("vertices"); if (!vertices->reserve(vertCount)) { delete vertices; return CC_FERR_NOT_ENOUGH_MEMORY; } //read vertices { CCVector3d Pshift(0,0,0); for (unsigned i=0; i<vertCount; ++i) { currentLine = GetNextLine(stream); tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); if (tokens.size() < 3) { delete vertices; return CC_FERR_MALFORMED_FILE; } //read vertex CCVector3d Pd(0,0,0); { bool vertexIsOk = false; Pd.x = tokens[0].toDouble(&vertexIsOk); if (vertexIsOk) { Pd.y = tokens[1].toDouble(&vertexIsOk); if (vertexIsOk) Pd.z = tokens[2].toDouble(&vertexIsOk); } if (!vertexIsOk) { delete vertices; return CC_FERR_MALFORMED_FILE; } } //first point: check for 'big' coordinates if (i == 0) { if (HandleGlobalShift(Pd,Pshift,parameters)) { vertices->setGlobalShift(Pshift); ccLog::Warning("[OFF] Cloud has been recentered! Translation: (%.2f,%.2f,%.2f)",Pshift.x,Pshift.y,Pshift.z); } } CCVector3 P = CCVector3::fromArray((Pd + Pshift).u); vertices->addPoint(P); } } ccMesh* mesh = new ccMesh(vertices); mesh->addChild(vertices); if (!mesh->reserve(triCount)) { delete mesh; return CC_FERR_NOT_ENOUGH_MEMORY; } //load triangles { bool ignoredPolygons = false; for (unsigned i=0; i<triCount; ++i) { currentLine = GetNextLine(stream); tokens = currentLine.split(QRegExp("\\s+"),QString::SkipEmptyParts); if (tokens.size() < 3) { delete mesh; return CC_FERR_MALFORMED_FILE; } unsigned polyVertCount = tokens[0].toUInt(&ok); if (!ok || static_cast<int>(polyVertCount) >= tokens.size()) { delete mesh; return CC_FERR_MALFORMED_FILE; } if (polyVertCount == 3 || polyVertCount == 4) { //decode indexes unsigned indexes[4]; for (unsigned j=0; j<polyVertCount; ++j) { indexes[j] = tokens[j+1].toUInt(&ok); if (!ok) { delete mesh; return CC_FERR_MALFORMED_FILE; } } //reserve memory if necessary unsigned polyTriCount = polyVertCount-2; if (mesh->size() + polyTriCount > mesh->capacity()) { if (!mesh->reserve(mesh->size() + polyTriCount + 256)) //use some margin to avoid too many allocations { delete mesh; return CC_FERR_NOT_ENOUGH_MEMORY; } } //triangle or quad only mesh->addTriangle(indexes[0],indexes[1],indexes[2]); if (polyVertCount == 4) mesh->addTriangle(indexes[0],indexes[2],indexes[3]); } else { ignoredPolygons = true; } } if (ignoredPolygons) { ccLog::Warning("[OFF] Some polygons with an unhandled size (i.e. > 4) were ignored!"); } } if (mesh->size() == 0) { ccLog::Warning("[OFF] Failed to load any polygon!"); mesh->detachChild(vertices); delete mesh; mesh = 0; container.addChild(vertices); vertices->setEnabled(true); } else { mesh->shrinkToFit(); //DGM: normals can be per-vertex or per-triangle so it's better to let the user do it himself later //Moreover it's not always good idea if the user doesn't want normals (especially in ccViewer!) //if (mesh->computeNormals()) // mesh->showNormals(true); //else // ccLog::Warning("[OFF] Failed to compute per-vertex normals..."); ccLog::Warning("[OFF] Mesh has no normal! You can manually compute them (select it then call \"Edit > Normals > Compute\")"); vertices->setEnabled(false); //vertices->setLocked(true); //DGM: no need to lock it as it is only used by one mesh! container.addChild(mesh); } return CC_FERR_NO_ERROR; }
void ccGraphicalSegmentationTool::doExportSegmentationPolyline() { MainWindow* mainWindow = MainWindow::TheInstance(); if (mainWindow && m_segmentationPoly) { bool mode2D = false; #ifdef ALLOW_2D_OR_3D_EXPORT QMessageBox messageBox(0); messageBox.setWindowTitle("Choose export type"); messageBox.setText("Export polyline in:\n - 2D (with coordinates relative to the screen)\n - 3D (with coordinates relative to the segmented entities)"); QPushButton* button2D = new QPushButton("2D"); QPushButton* button3D = new QPushButton("3D"); messageBox.addButton(button2D,QMessageBox::AcceptRole); messageBox.addButton(button3D,QMessageBox::AcceptRole); messageBox.addButton(QMessageBox::Cancel); messageBox.setDefaultButton(button3D); messageBox.exec(); if (messageBox.clickedButton() == messageBox.button(QMessageBox::Cancel)) { //process cancelled by user return; } mode2D = (messageBox.clickedButton() == button2D); #endif ccPolyline* poly = new ccPolyline(*m_segmentationPoly); //if the polyline is 2D and we export the polyline in 3D, we must project its vertices if (!mode2D) { //get current display parameters ccGLCameraParameters camera; m_associatedWin->getGLCameraParameters(camera); const double half_w = camera.viewport[2] / 2.0; const double half_h = camera.viewport[3] / 2.0; //project the 2D polyline in 3D CCLib::GenericIndexedCloudPersist* vertices = poly->getAssociatedCloud(); ccPointCloud* verticesPC = dynamic_cast<ccPointCloud*>(vertices); if (verticesPC) { for (unsigned i=0; i<vertices->size(); ++i) { CCVector3* Pscreen = const_cast<CCVector3*>(verticesPC->getPoint(i)); CCVector3d Pd(half_w + Pscreen->x, half_h + Pscreen->y, 0/*Pscreen->z*/); CCVector3d Q3D; camera.unproject(Pd, Q3D); *Pscreen = CCVector3::fromArray(Q3D.u); } verticesPC->invalidateBoundingBox(); } else { assert(false); ccLog::Warning("[Segmentation] Failed to convert 2D polyline to 3D! (internal inconsistency)"); mode2D = false; } } QString polyName = QString("Segmentation polyline #%1").arg(++s_polylineExportCount); poly->setName(polyName); poly->setEnabled(false); //we don't want it to appear while the segmentation mode is enabled! (anyway it's 2D only...) poly->set2DMode(mode2D); poly->setColor(ccColor::yellow); //we use a different color so as to differentiate them from the active polyline! //save associated viewport cc2DViewportObject* viewportObject = new cc2DViewportObject(polyName + QString(" viewport")); viewportObject->setParameters(m_associatedWin->getViewportParameters()); viewportObject->setDisplay(m_associatedWin); poly->addChild(viewportObject); mainWindow->addToDB(poly,false,false,false); ccLog::Print(QString("[Segmentation] Polyline exported (%1 vertices)").arg(poly->size())); } }