void ClientSetup::SanityCheck() { if (myPlayerName.empty()) myPlayerName = UnnamedPlayerName; StringReplaceInPlace(myPlayerName, ' ', '_'); if (hostIP == "none") { hostIP = ""; } }
bool COBJParser::ParseModelData(S3DModel* model, const std::string& modelData, const LuaTable& metaData) { static const boost::regex commentPattern("^[ ]*(#|//).*"); static const boost::regex objectPattern("^[ ]*o [ ]*[a-zA-Z0-9_]+[ ]*"); static const boost::regex vertexPattern( "^[ ]*v " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)? " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)? " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)?" "[ ]*" ); static const boost::regex normalPattern( "^[ ]*vn " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)? " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)? " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)?" "[ ]*" ); static const boost::regex txcoorPattern( "^[ ]*vt " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)? " "[ ]*-?[0-9]*\\.?[0-9]*(e-?[0-9]*)?" "[ ]*" ); static const boost::regex polygonPattern( "^[ ]*f " "[ ]*-?[0-9]+/-?[0-9]+/-?[0-9]+" "[ ]*-?[0-9]+/-?[0-9]+/-?[0-9]+" "[ ]*-?[0-9]+/-?[0-9]+/-?[0-9]+" "[ ]*" // do not allow spaces around the '/' separators or the // stringstream >> operator will tokenize the wrong way // (according to the OBJ spec they are illegal anyway: // "there is no space between numbers and the slashes") // "[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+" // 1st vertex/texcoor/normal idx // "[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+" // 2nd vertex/texcoor/normal idx // "[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+[ ]*/[ ]*-?[0-9]+" // 3rd vertex/texcoor/normal idx ); PieceMap pieceMap; SOBJPiece* piece = NULL; std::vector<float3> vertices; vertices.reserve(2048); std::vector<float2> texcoors; texcoors.reserve(2048); std::vector<float3> vnormals; vnormals.reserve(2048); std::string line, lineHeader; std::stringstream lineStream; size_t prevReadIdx = 0; size_t currReadIdx = 0; bool regexMatch = false; while ((currReadIdx = modelData.find_first_of('\n', prevReadIdx)) != std::string::npos) { line = modelData.substr(prevReadIdx, (currReadIdx - prevReadIdx)); line = StringReplaceInPlace(line, '\r', ' '); if (!line.empty()) { regexMatch = (boost::regex_match(line, commentPattern)); if (!regexMatch) { regexMatch = (boost::regex_match(line, objectPattern )); } if (!regexMatch) { regexMatch = (boost::regex_match(line, vertexPattern )); } if (!regexMatch) { regexMatch = (boost::regex_match(line, normalPattern )); } if (!regexMatch) { regexMatch = (boost::regex_match(line, txcoorPattern )); } if (!regexMatch) { regexMatch = (boost::regex_match(line, polygonPattern)); } if (!regexMatch) { // ignore groups ('g'), smoothing groups ('s'), // and materials ("mtllib", "usemtl") for now // (s-groups are obsolete with vertex normals) logOutput.Print("[OBJParser] failed to parse line \"%s\" for model \"%s\"", line.c_str(), model->name.c_str()); prevReadIdx = currReadIdx + 1; continue; } lineStream.str(line); lineStream >> lineHeader; switch (lineHeader[0]) { case '#': { // comment, no-op } break; case 'o': { // named object (piece) std::string pieceName; lineStream >> pieceName; assert(pieceMap.find(pieceName) == pieceMap.end()); piece = new SOBJPiece(); piece->name = pieceName; pieceMap[pieceName] = piece; model->numPieces += 1; } break; case 'v': { // position, normal, or texture-coordinates assert(piece != NULL); float3 f3; lineStream >> f3.x; lineStream >> f3.y; lineStream >> f3.z; float2 f2(f3.x, f3.y); if (lineHeader == "v" ) { vertices.push_back(f3); } else if (lineHeader == "vt") { texcoors.push_back(f2); } else if (lineHeader == "vn") { vnormals.push_back(f3); } } break; case 'f': { // face definition assert(piece != NULL); int vIdx = 0, tIdx = 0, nIdx = 0; size_t i = 0, j = 0, n = 0; SOBJTriangle triangle = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; while (lineStream.good() && n < 3) { std::string vtnIndices; lineStream >> vtnIndices; // vIdx/tcIdx/nIdx triplet of indices into the global lists i = vtnIndices.find('/', 0); assert(i != std::string::npos); j = vtnIndices.find('/', i + 1); assert(j != std::string::npos); vIdx = std::atoi(vtnIndices.substr( 0, i).c_str()); tIdx = std::atoi(vtnIndices.substr(i + 1, j - i).c_str()); nIdx = std::atoi(vtnIndices.substr(j + 1 ).c_str()); if (vIdx < 0) { triangle.vIndices[n] = vertices.size() + vIdx; } else { triangle.vIndices[n] = vIdx - 1; } if (tIdx < 0) { triangle.tIndices[n] = texcoors.size() + tIdx; } else { triangle.tIndices[n] = tIdx - 1; } if (nIdx < 0) { triangle.nIndices[n] = vnormals.size() + nIdx; } else { triangle.nIndices[n] = nIdx - 1; } n += 1; } const bool b0 = (triangle.vIndices[0] >= 0 && triangle.vIndices[1] >= 0 && triangle.vIndices[2] >= 0) && (triangle.tIndices[0] >= 0 && triangle.tIndices[1] >= 0 && triangle.tIndices[2] >= 0) && (triangle.nIndices[0] >= 0 && triangle.nIndices[1] >= 0 && triangle.nIndices[2] >= 0); const bool b1 = (triangle.vIndices[0] < vertices.size() && triangle.vIndices[1] < vertices.size() && triangle.vIndices[2] < vertices.size()) && (triangle.tIndices[0] < texcoors.size() && triangle.tIndices[1] < texcoors.size() && triangle.tIndices[2] < texcoors.size()) && (triangle.nIndices[0] < vnormals.size() && triangle.nIndices[1] < vnormals.size() && triangle.nIndices[2] < vnormals.size()); assert(n == 3); assert(b0 && b1); if (b0 && b1) { // note: this assumes face elements may not reference indices // ahead of the current {vertices, texcoors, vnormals}.size() // if this *is* allowed, the entire file must be parsed first float3 &v0 = vertices[triangle.vIndices[0]], &v1 = vertices[triangle.vIndices[1]], &v2 = vertices[triangle.vIndices[2]]; float2 &t0 = texcoors[triangle.tIndices[0]], &t1 = texcoors[triangle.tIndices[1]], &t2 = texcoors[triangle.tIndices[2]]; float3 &n0 = vnormals[triangle.nIndices[0]], &n1 = vnormals[triangle.nIndices[1]], &n2 = vnormals[triangle.nIndices[2]]; const int idx0 = (piece->GetTriangleCount() * 3) + 0, idx1 = (piece->GetTriangleCount() * 3) + 1, idx2 = (piece->GetTriangleCount() * 3) + 2; // convert to piece-local vtn indices triangle.vIndices[0] = idx0; piece->AddVertex(v0 ); triangle.nIndices[0] = idx0; piece->AddNormal(n0.ANormalize()); triangle.tIndices[0] = idx0; piece->AddTxCoor(t0 ); triangle.vIndices[1] = idx1; piece->AddVertex(v1 ); triangle.nIndices[1] = idx1; piece->AddNormal(n1.ANormalize()); triangle.tIndices[1] = idx1; piece->AddTxCoor(t1 ); triangle.vIndices[2] = idx2; piece->AddVertex(v2 ); triangle.nIndices[2] = idx2; piece->AddNormal(n2.ANormalize()); triangle.tIndices[2] = idx2; piece->AddTxCoor(t2 ); piece->AddTriangle(triangle); } else { logOutput.Print("[OBJParser] illegal face-element indices on line \"%s\" for model \"%s\"", line.c_str(), model->name.c_str()); } } break; default: { } break; } lineStream.clear(); lineStream.str(""); } prevReadIdx = currReadIdx + 1; }
/** * Initializes instance of GameSetup */ void SpringApp::Startup() { std::string inputFile = cmdline->GetInputFile(); if (inputFile.empty()) { #ifdef HEADLESS LOG_L(L_FATAL, "The headless version of the engine can not be run in interactive mode.\n" "Please supply a start-script, save- or demo-file."); exit(1); #endif bool server = !cmdline->IsSet("client") || cmdline->IsSet("server"); #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->Initialize(server, 64); #endif activeController = new SelectMenu(server); } else if (inputFile.rfind("sdf") == inputFile.size() - 3) { std::string demoFileName = inputFile; std::string demoPlayerName = configHandler->GetString("name"); if (demoPlayerName.empty()) { demoPlayerName = "UnnamedPlayer"; } else { demoPlayerName = StringReplaceInPlace(demoPlayerName, ' ', '_'); } demoPlayerName += " (spec)"; startsetup = new ClientSetup(); startsetup->isHost = true; // local demo play startsetup->myPlayerName = demoPlayerName; #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->Initialize(true, 64); //FIXME: add actual number of player #endif pregame = new CPreGame(startsetup); pregame->LoadDemo(demoFileName); } else if (inputFile.rfind("ssf") == inputFile.size() - 3) { std::string savefile = inputFile; startsetup = new ClientSetup(); startsetup->isHost = true; startsetup->myPlayerName = configHandler->GetString("name"); #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->Initialize(true, 64); //FIXME: add actual number of player #endif pregame = new CPreGame(startsetup); pregame->LoadSavefile(savefile); } else { LOG("Loading startscript from: %s", inputFile.c_str()); std::string startscript = inputFile; CFileHandler fh(startscript); if (!fh.FileExists()) throw content_error("Setup-script does not exist in given location: "+startscript); std::string buf; if (!fh.LoadStringData(buf)) throw content_error("Setup-script cannot be read: " + startscript); startsetup = new ClientSetup(); startsetup->Init(buf); // commandline parameters overwrite setup if (cmdline->IsSet("client")) startsetup->isHost = false; else if (cmdline->IsSet("server")) startsetup->isHost = true; #ifdef SYNCDEBUG CSyncDebugger::GetInstance()->Initialize(startsetup->isHost, 64); //FIXME: add actual number of player #endif pregame = new CPreGame(startsetup); if (startsetup->isHost) pregame->LoadSetupscript(buf); } }