Vector3 Vector3::Cross(Vector3 vect,Vector3 vect2){ return Vector3( vect.y * vect.z - vect.z * vect.y, vect.z * vect.x - vect.x * vect.z, vect.x * vect.y - vect.y * vect.x ); }
Vector3 CrossProduct(const Vector3& other) const { return Vector3((y * other.z) - (z * other.y), -((x * other.z) - (z * other.x)), (x * other.y) - (y * other.x)); }
Vector3 Matrix4::operator[](int basisIdx) const { assert(0 <= basisIdx && basisIdx <= 3); return Vector3(m[0][basisIdx], m[1][basisIdx], m[2][basisIdx]); }
Plane::Plane(FLOAT a, FLOAT b, FLOAT c, FLOAT d) { Normal = Vector3(a,b,c); D = d; };
Plane::Plane(const Vector4 *value) { Normal = Vector3(value->X,value->Y,value->Z); D = value->W; };
Vector3 ILocatable::move(float X,float Y,float Z) {return move(Vector3(X,Y,Z));}
Vector3 ILocatable::scale(float X,float Y,float Z) {return scale(Vector3(X,Y,Z));}
void PathFinder::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) { // *** getting start/end poly logic *** float distToStartPoly, distToEndPoly; float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); // we have a hole in our mesh // make shortcut path and mark it as NOPATH ( with flying exception ) // its up to caller how he will use this info if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } // we may need a better number here bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); if (farFromPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); bool buildShotrcut = false; if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) { Creature* owner = (Creature*)m_sourceUnit; Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; if (m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: underWater case\n"); if (owner->CanSwim()) buildShotrcut = true; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); if (owner->CanFly()) buildShotrcut = true; } } if (buildShotrcut) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return; } else { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); } m_type = PATHFIND_INCOMPLETE; } } // *** poly path generating logic *** // start and end are on same polygon // just need to move in straight line if (startPoly == endPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == endPoly)\n"); BuildShortcut(); m_pathPolyRefs[0] = startPoly; m_polyLength = 1; m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: path type %d\n", m_type); return; } // look for startPoly/endPoly in current path // TODO: we can merge it with getPathPolyByPosition() loop bool startPolyFound = false; bool endPolyFound = false; uint32 pathStartIndex, pathEndIndex; if (m_polyLength) { for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) { // here to carch few bugs MANGOS_ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); if (m_pathPolyRefs[pathStartIndex] == startPoly) { startPolyFound = true; break; } } for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) if (m_pathPolyRefs[pathEndIndex] == endPoly) { endPolyFound = true; break; } } if (startPolyFound && endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); // we moved along the path and the target did not move out of our old poly-path // our path is a simple subpath case, we have all the data we need // just "cut" it out m_polyLength = pathEndIndex - pathStartIndex + 1; memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); } else if (startPolyFound && !endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); // we are moving on the old path but target moved out // so we have atleast part of poly-path ready m_polyLength -= pathStartIndex; // try to adjust the suffix of the path instead of recalculating entire length // at given interval the target cannot get too far from its last location // thus we have less poly to cover // sub-path of optimal path is optimal // take ~80% of the original length // TODO : play with the values here uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); dtPolyRef suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref --prefixPolyLength; suffixStartPoly = m_pathPolyRefs[prefixPolyLength-1]; if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // suffixStartPoly is still invalid, error state BuildShortcut(); m_type = PATHFIND_NOPATH; return; } } // generate suffix uint32 suffixPolyLength = 0; dtStatus dtResult = m_navMeshQuery->findPath( suffixStartPoly, // start polygon endPoly, // end polygon suffixEndPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs + prefixPolyLength - 1, // [out] path (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path if (!suffixPolyLength || dtResult != DT_SUCCESS) { // this is probably an error state, but we'll leave it // and hopefully recover on the next Update // we still need to copy our preffix sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); // new path = prefix + suffix - overlap m_polyLength = prefixPolyLength + suffixPolyLength - 1; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); // either we have no path at all -> first run // or something went really wrong -> we aren't moving along the path to the target // just generate new path // free and invalidate old path data clear(); dtStatus dtResult = m_navMeshQuery->findPath( startPoly, // start polygon endPoly, // end polygon startPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs, // [out] path (int*)&m_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path if (!m_polyLength || dtResult != DT_SUCCESS) { // only happens if we passed bad data to findPath(), or navmesh is messed up sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } } // by now we know what type of path we can get if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) m_type = PATHFIND_NORMAL; else m_type = PATHFIND_INCOMPLETE; // generate the point-path out of our up-to-date poly-path BuildPointPath(startPoint, endPoint); }
void PathFinder::BuildPointPath(const float *startPoint, const float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, m_pointPathLimit); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, m_pointPathLimit); // maximum number of points } if (pointCount < 2 || dtResult != DT_SUCCESS) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } m_pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // first point is always our current location - we need the next one setActualEndPosition(m_pathPoints[pointCount-1]); // force the given destination, if needed if(m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { // we may want to keep partial subpath if(dist3DSqr(getActualEndPosition(), getEndPosition()) < 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) { setActualEndPosition(getEndPosition()); m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); } else { setActualEndPosition(getEndPosition()); BuildShortcut(); } m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
Chunk *ChunkGenerator::generateChunk(City *city, const Vector2 &position) { // First we check if position is valid (if both X and Y are multiple of 1000) if ((int) position.x % 1000 != 0 || (int) position.y % 1000 != 0) { return nullptr; } // And also if this chunk doesn't already exists if (FileIO::fileExists(Chunk::getFileName(position))) { return nullptr; } Profiler::getTimer(3)->startMeasurement(); /* * Generate Intersections and Roads */ //TODO: Put this condition on the different grid layout generators. Each may have different limits int minDistanceIntersections = 50; // Minimum distance between intersections Chunk *chunk = new Chunk(position, city); std::vector<Chunk*> neighbourChunks = city->getNeighbourChunks(chunk, true); ManhattanGridLayout gridLayout = ManhattanGridLayout(Vector2(), Vector2()); int numSubChunks = Chunk::CHUNK_SIZE / Chunk::SUBCHUNK_SIZE; float subChunkSize = (float) Chunk::SUBCHUNK_SIZE; for (int i = 0; i < numSubChunks; i++) { for (int j = 0; j < numSubChunks; j++) { // Calculate the position of the new intersection on this subchunk gridLayout.posMin = Vector2(i * subChunkSize, j * subChunkSize); gridLayout.posMax = Vector2((i + 1) * subChunkSize, (j + 1) * subChunkSize); Vector2 intersectionPos = gridLayout.getIntersectionPosition(); float den = Perlin::getCityBlockDensity(intersectionPos.x + position.x, intersectionPos.y + position.y); if (intersectionPos.x > -99 && intersectionPos.y > -99 && den > 0.0f) { // If there's an intersection in this subchunk, check if it has enough distance from the others intersectionPos += position; // Convert to World Position auto it = chunk->getIntersections()->begin(); auto itEnd = chunk->getIntersections()->end(); bool tooClose = false; Vector3 newIntPos = Vector3(intersectionPos.x, 0, intersectionPos.y); for (; it != itEnd; it++) { Intersection *intersection = (*it); // Chunk position for the new intersection position (0 to 1000) float length = (intersection->getPosition() - newIntPos).getLength(); //std::cout << length << std::endl; if (length < minDistanceIntersections) { tooClose = true; break; } } if (!tooClose) { // If the new intersections is sufficiently distant from all the others, proceed Intersection *newInter = nullptr; Intersection *neighbourSubstitute = nullptr; // Check if the new Intersection is too close to any Intersection on the neighbours for (auto it = neighbourChunks.begin(); it != neighbourChunks.end(); it++) { Intersection *closest = (*it)->getClosestIntersectionTo(newIntPos); if (closest != nullptr) { float distance = (closest->getPosition() - newIntPos).getLength(); if (distance < minDistanceIntersections) { // The new Intersection is too close to an Intersection on an neighbour. Use the // neighbour's Intersection instead neighbourSubstitute = closest; break; } } } if (neighbourSubstitute != nullptr) { newInter = neighbourSubstitute; } else { newInter = new Intersection(newIntPos); } chunk->addIntersection(newInter); gridLayout.generateRoads(chunk, newInter); } } } } //Profiler::getTimer(3)->finishMeasurement(); //Profiler::getTimer(3)->resetCycle(); //std::cout << chunk->getChunkPos() << " generated in " << Profiler::getTimer(3)->getAverageTime() << "ms" << std::endl; //return chunk; /* * Generate City Blocks and Buildings */ auto itEnd = chunk->getIntersections()->end(); for (auto it = chunk->getIntersections()->begin(); it != itEnd; it++) { CityBlock *cityBlock = gridLayout.generateCityBlock(chunk, (*it)); if (cityBlock != nullptr) { // Check if this CityBlock has any Intersections that are in mutiple Chunks. If it does, add the CityBlock to // those Chunks /*Intersection *multiIntersection = nullptr; for (auto it = cityBlock->getVertices()->begin(); it != cityBlock->getVertices()->end(); it++) { if ((*it)->getNumChunksSharing() > 1) { multiIntersection = *it; } } if (multiIntersection != nullptr) { for (auto it = neighbourChunks.begin(); it != neighbourChunks.end(); it++) { if ((*it)->hasIntersection(multiIntersection)) { (*it)->addCityBlock(cityBlock); } } }*/ auto itEndC = chunk->getCityBlocks()->end(); bool duplicate = false; for (auto itC = chunk->getCityBlocks()->begin(); itC != itEndC; itC++) { if ((*itC)->getCentralPosition() == cityBlock->getCentralPosition() && (*itC) != cityBlock) { duplicate = true; } } if (!duplicate) { cityBlock->generateBuildings(); } else { chunk->removeCityBlock(cityBlock); delete cityBlock; } } } Profiler::getTimer(3)->finishMeasurement(); Profiler::getTimer(3)->resetCycle(); std::cout << chunk->getChunkPos() << " generated in " << Profiler::getTimer(3)->getAverageTime() << "ms" << std::endl; //std::cout << ResourcesManager::getResourcesCount() << std::endl; return chunk; /* Chunk Generator Algorithm: */ /* * 1 - We try to load the adjacent chunks to detect invalid intersections near the borders. * * 2 - Iterate over the 10x10 grid of partial chunks, calculate the grid layout for each one and call the generator * algorithm of the correct grid layout to generate intersections and roads for each one of the partial chunks. * NOTE: Consider Voronoi Diagram for the GridLayout selector * * 3 - Connect this chunk's intersections with the adjacent chunk's intersections, if the corresponding adjacent * chunk exists. * * 4 - Generate empty city blocks and add everything generated so far to the scene, so it can render something * while we generate the buildings * * 5 - Use the grid layout and city zone to assign a city block type to each city block * * 6 - Generate the buildings for all city blocks * * 7 - Add the new buildings to the scene so it can render everything * * 8 - Save this chunk to its file * * 9 - Update the adjacent chunks with the new edge city blocks, intersections and roads */ }
Error VariantParser::parse_value(Token& token,Variant &value,Stream *p_stream,int &line,String &r_err_str,ResourceParser *p_res_parser) { /* { Error err = get_token(p_stream,token,line,r_err_str); if (err) return err; }*/ if (token.type==TK_CURLY_BRACKET_OPEN) { Dictionary d; Error err = _parse_dictionary(d,p_stream,line,r_err_str,p_res_parser); if (err) return err; value=d; return OK; } else if (token.type==TK_BRACKET_OPEN) { Array a; Error err = _parse_array(a,p_stream,line,r_err_str,p_res_parser); if (err) return err; value=a; return OK; } else if (token.type==TK_IDENTIFIER) { /* VECTOR2, // 5 RECT2, VECTOR3, MATRIX32, PLANE, QUAT, // 10 _AABB, //sorry naming convention fail :( not like it's used often MATRIX3, TRANSFORM, // misc types COLOR, IMAGE, // 15 NODE_PATH, _RID, OBJECT, INPUT_EVENT, DICTIONARY, // 20 ARRAY, // arrays RAW_ARRAY, INT_ARRAY, REAL_ARRAY, STRING_ARRAY, // 25 VECTOR2_ARRAY, VECTOR3_ARRAY, COLOR_ARRAY, VARIANT_MAX */ String id = token.value; if (id=="true") value=true; else if (id=="false") value=false; else if (id=="null") value=Variant(); else if (id=="Vector2"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=2) { r_err_str="Expected 2 arguments for constructor"; } value=Vector2(args[0],args[1]); return OK; } else if (id=="Rect2"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=4) { r_err_str="Expected 4 arguments for constructor"; } value=Rect2(args[0],args[1],args[2],args[3]); return OK; } else if (id=="Vector3"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=3) { r_err_str="Expected 3 arguments for constructor"; } value=Vector3(args[0],args[1],args[2]); return OK; } else if (id=="Matrix32"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=6) { r_err_str="Expected 6 arguments for constructor"; } Matrix32 m; m[0]=Vector2(args[0],args[1]); m[1]=Vector2(args[2],args[3]); m[2]=Vector2(args[4],args[5]); value=m; return OK; } else if (id=="Plane") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=4) { r_err_str="Expected 4 arguments for constructor"; } value=Plane(args[0],args[1],args[2],args[3]); return OK; } else if (id=="Quat") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=4) { r_err_str="Expected 4 arguments for constructor"; } value=Quat(args[0],args[1],args[2],args[3]); return OK; } else if (id=="AABB"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=6) { r_err_str="Expected 6 arguments for constructor"; } value=AABB(Vector3(args[0],args[1],args[2]),Vector3(args[3],args[4],args[5])); return OK; } else if (id=="Matrix3"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=9) { r_err_str="Expected 9 arguments for constructor"; } value=Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); return OK; } else if (id=="Transform"){ Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=12) { r_err_str="Expected 12 arguments for constructor"; } value=Transform(Matrix3(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]),Vector3(args[9],args[10],args[11])); return OK; } else if (id=="Color") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; if (args.size()!=4) { r_err_str="Expected 4 arguments for constructor"; } value=Color(args[0],args[1],args[2],args[3]); return OK; } else if (id=="Image") { //:| get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type==TK_PARENTHESIS_CLOSE) { value=Image(); // just an Image() return OK; } else if (token.type!=TK_NUMBER) { r_err_str="Expected number (width)"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); int width=token.value; if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected number (height)"; return ERR_PARSE_ERROR; } int height=token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected number (mipmaps)"; return ERR_PARSE_ERROR; } int mipmaps=token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_IDENTIFIER) { r_err_str="Expected identifier (format)"; return ERR_PARSE_ERROR; } String sformat=token.value; Image::Format format; if (sformat=="GRAYSCALE") format=Image::FORMAT_GRAYSCALE; else if (sformat=="INTENSITY") format=Image::FORMAT_INTENSITY; else if (sformat=="GRAYSCALE_ALPHA") format=Image::FORMAT_GRAYSCALE_ALPHA; else if (sformat=="RGB") format=Image::FORMAT_RGB; else if (sformat=="RGBA") format=Image::FORMAT_RGBA; else if (sformat=="INDEXED") format=Image::FORMAT_INDEXED; else if (sformat=="INDEXED_ALPHA") format=Image::FORMAT_INDEXED_ALPHA; else if (sformat=="BC1") format=Image::FORMAT_BC1; else if (sformat=="BC2") format=Image::FORMAT_BC2; else if (sformat=="BC3") format=Image::FORMAT_BC3; else if (sformat=="BC4") format=Image::FORMAT_BC4; else if (sformat=="BC5") format=Image::FORMAT_BC5; else if (sformat=="PVRTC2") format=Image::FORMAT_PVRTC2; else if (sformat=="PVRTC2_ALPHA") format=Image::FORMAT_PVRTC2_ALPHA; else if (sformat=="PVRTC4") format=Image::FORMAT_PVRTC4; else if (sformat=="PVRTC4_ALPHA") format=Image::FORMAT_PVRTC4_ALPHA; else if (sformat=="ATC") format=Image::FORMAT_ATC; else if (sformat=="ATC_ALPHA_EXPLICIT") format=Image::FORMAT_ATC_ALPHA_EXPLICIT; else if (sformat=="ATC_ALPHA_INTERPOLATED") format=Image::FORMAT_ATC_ALPHA_INTERPOLATED; else if (sformat=="CUSTOM") format=Image::FORMAT_CUSTOM; else { r_err_str="Invalid image format: '"+sformat+"'"; return ERR_PARSE_ERROR; }; int len = Image::get_image_data_size(width,height,format,mipmaps); DVector<uint8_t> buffer; buffer.resize(len); if (buffer.size()!=len) { r_err_str="Couldn't allocate image buffer of size: "+itos(len); } { DVector<uint8_t>::Write w=buffer.write(); for(int i=0;i<len;i++) { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected number"; return ERR_PARSE_ERROR; } w[i]=int(token.value); } } Image img(width,height,mipmaps,format,buffer); value=img; return OK; } else if (id=="NodePath") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_STRING) { r_err_str="Expected string as argument for NodePath()"; return ERR_PARSE_ERROR; } value=NodePath(String(token.value)); get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } } else if (id=="RID") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected number as argument"; return ERR_PARSE_ERROR; } value=token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } return OK; } else if (id=="Resource" || id=="SubResource" || id=="ExtResource") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } if (p_res_parser && id=="Resource" && p_res_parser->func){ RES res; Error err = p_res_parser->func(p_res_parser->userdata,p_stream,res,line,r_err_str); if (err) return err; value=res; return OK; } else if (p_res_parser && id=="ExtResource" && p_res_parser->ext_func){ RES res; Error err = p_res_parser->ext_func(p_res_parser->userdata,p_stream,res,line,r_err_str); if (err) return err; value=res; return OK; } else if (p_res_parser && id=="SubResource" && p_res_parser->sub_func){ RES res; Error err = p_res_parser->sub_func(p_res_parser->userdata,p_stream,res,line,r_err_str); if (err) return err; value=res; return OK; } else { get_token(p_stream,token,line,r_err_str); if (token.type==TK_STRING) { String path=token.value; RES res = ResourceLoader::load(path); if (res.is_null()) { r_err_str="Can't load resource at path: '"+path+"'."; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } value=res; return OK; } else { r_err_str="Expected string as argument for Resource()."; return ERR_PARSE_ERROR; } } return OK; } else if (id=="InputEvent") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_IDENTIFIER) { r_err_str="Expected identifier"; return ERR_PARSE_ERROR; } String id = token.value; InputEvent ie; if (id=="KEY") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } ie.type=InputEvent::KEY; get_token(p_stream,token,line,r_err_str); if (token.type==TK_IDENTIFIER) { String name=token.value; ie.key.scancode=find_keycode(name); } else if (token.type==TK_NUMBER) { ie.key.scancode=token.value; } else { r_err_str="Expected string or integer for keycode"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type==TK_COMMA) { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_IDENTIFIER) { r_err_str="Expected identifier with modifier flas"; return ERR_PARSE_ERROR; } String mods=token.value; if (mods.findn("C")!=-1) ie.key.mod.control=true; if (mods.findn("A")!=-1) ie.key.mod.alt=true; if (mods.findn("S")!=-1) ie.key.mod.shift=true; if (mods.findn("M")!=-1) ie.key.mod.meta=true; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } } else if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')' or modifier flags."; return ERR_PARSE_ERROR; } } else if (id=="MBUTTON") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } ie.type=InputEvent::MOUSE_BUTTON; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected button index"; return ERR_PARSE_ERROR; } ie.mouse_button.button_index = token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } } else if (id=="JBUTTON") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } ie.type=InputEvent::JOYSTICK_BUTTON; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected button index"; return ERR_PARSE_ERROR; } ie.joy_button.button_index = token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')'"; return ERR_PARSE_ERROR; } } else if (id=="JAXIS") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ','"; return ERR_PARSE_ERROR; } ie.type=InputEvent::JOYSTICK_MOTION; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected axis index"; return ERR_PARSE_ERROR; } ie.joy_motion.axis = token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_COMMA) { r_err_str="Expected ',' after axis index"; return ERR_PARSE_ERROR; } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_NUMBER) { r_err_str="Expected axis sign"; return ERR_PARSE_ERROR; } ie.joy_motion.axis_value = token.value; get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_CLOSE) { r_err_str="Expected ')' for jaxis"; return ERR_PARSE_ERROR; } } else { r_err_str="Invalid input event type."; return ERR_PARSE_ERROR; } value=ie; return OK; } else if (id=="ByteArray") { Vector<uint8_t> args; Error err = _parse_construct<uint8_t>(p_stream,args,line,r_err_str); if (err) return err; DVector<uint8_t> arr; { int len=args.size(); arr.resize(len); DVector<uint8_t>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=args[i]; } } value=arr; return OK; } else if (id=="IntArray") { Vector<int32_t> args; Error err = _parse_construct<int32_t>(p_stream,args,line,r_err_str); if (err) return err; DVector<int32_t> arr; { int len=args.size(); arr.resize(len); DVector<int32_t>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=int(args[i]); } } value=arr; return OK; } else if (id=="FloatArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; DVector<float> arr; { int len=args.size(); arr.resize(len); DVector<float>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=args[i]; } } value=arr; return OK; } else if (id=="StringArray") { get_token(p_stream,token,line,r_err_str); if (token.type!=TK_PARENTHESIS_OPEN) { r_err_str="Expected '('"; return ERR_PARSE_ERROR; } Vector<String> cs; bool first=true; while(true) { if (!first) { get_token(p_stream,token,line,r_err_str); if (token.type==TK_COMMA) { //do none } else if (token.type==TK_PARENTHESIS_CLOSE) { break; } else { r_err_str="Expected ',' or ')'"; return ERR_PARSE_ERROR; } } get_token(p_stream,token,line,r_err_str); if (token.type!=TK_STRING) { r_err_str="Expected string"; return ERR_PARSE_ERROR; } first=false; cs.push_back(token.value); } DVector<String> arr; { int len=cs.size(); arr.resize(len); DVector<String>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=cs[i]; } } value=arr; return OK; } else if (id=="Vector2Array") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; DVector<Vector2> arr; { int len=args.size()/2; arr.resize(len); DVector<Vector2>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=Vector2(args[i*2+0],args[i*2+1]); } } value=arr; return OK; } else if (id=="Vector3Array") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; DVector<Vector3> arr; { int len=args.size()/3; arr.resize(len); DVector<Vector3>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=Vector3(args[i*3+0],args[i*3+1],args[i*3+2]); } } value=arr; return OK; } else if (id=="ColorArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream,args,line,r_err_str); if (err) return err; DVector<Color> arr; { int len=args.size()/4; arr.resize(len); DVector<Color>::Write w = arr.write(); for(int i=0;i<len;i++) { w[i]=Color(args[i*4+0],args[i*4+1],args[i*4+2],args[i*4+3]); } } value=arr; return OK; } else if (id=="key") { // compatibility with engine.cfg Vector<String> params; Error err = _parse_enginecfg(p_stream,params,line,r_err_str); if (err) return err; ERR_FAIL_COND_V(params.size()!=1 && params.size()!=2,ERR_PARSE_ERROR); int scode=0; if (params[0].is_numeric()) { scode=params[0].to_int(); if (scode < 10) { scode=KEY_0+scode; } } else scode=find_keycode(params[0]); InputEvent ie; ie.type=InputEvent::KEY; ie.key.scancode=scode; if (params.size()==2) { String mods=params[1]; if (mods.findn("C")!=-1) ie.key.mod.control=true; if (mods.findn("A")!=-1) ie.key.mod.alt=true; if (mods.findn("S")!=-1) ie.key.mod.shift=true; if (mods.findn("M")!=-1) ie.key.mod.meta=true; } value=ie; return OK; } else if (id=="mbutton") { // compatibility with engine.cfg Vector<String> params; Error err = _parse_enginecfg(p_stream,params,line,r_err_str); if (err) return err; ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR); InputEvent ie; ie.type=InputEvent::MOUSE_BUTTON; ie.device=params[0].to_int(); ie.mouse_button.button_index=params[1].to_int(); value=ie; return OK; } else if (id=="jbutton") { // compatibility with engine.cfg Vector<String> params; Error err = _parse_enginecfg(p_stream,params,line,r_err_str); if (err) return err; ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR); InputEvent ie; ie.type=InputEvent::JOYSTICK_BUTTON; ie.device=params[0].to_int(); ie.joy_button.button_index=params[1].to_int(); value=ie; return OK; } else if (id=="jaxis") { // compatibility with engine.cfg Vector<String> params; Error err = _parse_enginecfg(p_stream,params,line,r_err_str); if (err) return err; ERR_FAIL_COND_V(params.size()!=2,ERR_PARSE_ERROR); InputEvent ie; ie.type=InputEvent::JOYSTICK_MOTION; ie.device=params[0].to_int(); int axis=params[1].to_int(); ie.joy_motion.axis=axis>>1; ie.joy_motion.axis_value=axis&1?1:-1; value= ie; return OK; } else if (id=="img") { // compatibility with engine.cfg
Vector3 Printer::getLetterBaseLocalization(char letter) { return Vector3(0.0, 0.0, 0.0); }
void QCharacterController::update(float delta) { mAccumulation += delta; while(mAccumulation>=mTimeStep) { btVector3 upVectorFinal = QVector3Nx(mPhysicsManager->getLocalGravity(Vector3(NxVector3(mController->getPosition()))));//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition())); NxVec3 GravityVector = upVectorFinal; upVectorFinal.normalize(); upVectorFinal*=-1; bool testing = false; NxVec3 opo = NxVec3(0,0,0); NxVec3 fpo = NxVec3(0,0,0); float abbc = mPhysicsManager->getLocalGravity(NxVector3(mController->getPosition()+mController->getUpVector())).length();//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition()+mController->getUpVector())).magnitude(); q_1 = q_2; if(mController->getUpVector()!=upVectorFinal&&Ogre::Degree(NxVector3(mController->getUpVector()).angleBetween(NxVector3(upVectorFinal)))>Ogre::Degree(0.075f)&&abbc>0.2f) { testing = true; Ogre::Vector3 up1 = NxVector3(mController->getUpVector()); //std::cout<<"pos1: "<<mController->cctp[0]->getPosition().x()<<"\n"; mController->setUpVector(upVectorFinal,mTimeStep); //std::cout<<"pos2: "<<mController->cctp[0]->getPosition().x()<<"\n"; Ogre::Vector3 up2 = NxVector3(mController->getUpVector()); Ogre::Quaternion q2 = up1.getRotationTo(up2,Ogre::Vector3::UNIT_X); q_2 = Quaternion(q2*q_1.toOgre()); } //dnode02->setOrientation(Ogre::Quaternion::IDENTITY); //dnode02->setDirection(NxVector3(mController->getUpVector()),Ogre::SceneNode::TS_LOCAL,Ogre::Vector3::UNIT_Y); opo = mController->position; bool mMidair = false;// = inAir(); float playerSpeed = 0; if(mController->move_) { Ogre::Vector3 v3 = Ogre::Vector3(moveV.x,moveV.y,moveV.z); Ogre::Plane pln = Ogre::Plane(NxVector3(mController->getUpVector()),0); pln.projectVector(v3); v3.normalise(); moveV = Ogre::Vector3(moveV.x,moveV.y,moveV.z); /// run = 6.225 /// walk = 2.225 float spdd = mPlayerSpeedStart*(1-mPlayerSpeedInterpolation)+mPlayerSpeedTop*(mPlayerSpeedInterpolation);//7.0f;//2.225f*(1-runTimer) + 6.225*runTimer if(abbc<0.2) { mController->move(NxVec3(moveV.x,moveV.y,moveV.z)*mTimeStep*spdd,true,mTimeStep,true); } else { //std::cout<<"Try move....\n"; mController->move(NxVec3(moveV.x,moveV.y,moveV.z)*mTimeStep*spdd,true,mTimeStep); } fpo = mController->position; playerSpeed = Ogre::Math::Abs((fpo-opo).length()); //playerMotionDir = NxVector3(fpo-opo); //std::cout<<"Speed: "<<playerSpeed/(gmgr->tmgr->getTimeSpeed()/60.0f)<<"\n"; } else { playerSpeed = 0; //playerMotionDir = Ogre::Vector3(0,0,0); } mMidair = inAir(); float lastSpeed = mPlayerSpeedLast; mPlayerSpeedLast = playerSpeed; if(mPlayerSpeedLast>lastSpeed) { mPlayerSpeedInterpolation+=(mTimeStep/mPlayerSpeedAccel); mGracePeriod = 0; } else if((mPlayerSpeedLast<mPlayerSpeedStart*mTimeStep||mHittingGround)&&!mMidair) { // we give a little bit of padding so if a gravity issue ir something stops it for a frame // it doesn't slow abruptly. ++mGracePeriod; if(mGracePeriod>=2) { mPlayerSpeedInterpolation=0; } } else { mGracePeriod = 0; } if(mMidair) { //mPlayerSpeedLast = 0; } if(mPlayerSpeedInterpolation<0) { mPlayerSpeedInterpolation = 0; } if(mPlayerSpeedInterpolation>1) { mPlayerSpeedInterpolation = 1; } NxVec3 gravityCont = QVector3Nx(mPhysicsManager->getLocalGravity(NxVector3(mController->getPosition()+mController->getUpVector())))*0.9f;//gmgr->gvmgr->getGravityLocalCCT(NxVector3(mController->getPosition()+mController->getUpVector()))*0.9f; NxVec3 gcN = gravityCont; gcN.normalize(); if(NxVector3(gcN).angleBetween(Ogre::Vector3(0,1,0))<Ogre::Degree(1)) { gravityCont = NxVec3(0,1,0)*gravityCont.length(); } if(NxVector3(gcN).angleBetween(Ogre::Vector3(0,-1,0))<Ogre::Degree(1)) { gravityCont = NxVec3(0,-1,0)*gravityCont.length(); } //||NxVector3(gravityCont).angleBetween(Ogre::Vector3(0,-1,0))<Ogre::Degree(1)) if(mIsJumping) { gravityCont = gravityCont - gravityCont*mJumpFactor; mJumpFactor -= 1.f*static_cast<Real>(mTimeStep); if(mJumpFactor<0) { mJumpFactor = 0; mIsJumping = false; } } NxVec3 ogp = mController->getPosition(); float ff = 1.0; if(testing ) { ff=0.5f*(1-mController->mUpInterp)+(mController->mUpInterp*1.0f); mPlayerGravityInterpolation = mPlayerGravityInterpolation/5; } if(abbc>0.2f) { mController->move(ff*((gravityCont*(mPlayerGravityBase*(1-mPlayerGravityInterpolation)+mPlayerGravityTerminal*(mPlayerGravityInterpolation)))*mTimeStep),false,mTimeStep); } NxVec3 pogp = mController->getPosition(); float lastGravity = mPlayerGravityLast; mPlayerGravityLast = btVector3(ogp-pogp).length(); if(mMidair&&!mHittingGround) { mGroundImpact = mPlayerGravityLast/mTimeStep*1.45f; } if(mPlayerGravityLast>lastGravity) { mPlayerGravityInterpolation+=(mTimeStep/mPlayerGravityAccel); } else if(mPlayerGravityLast<mPlayerGravityBase*mTimeStep) { mPlayerGravityInterpolation=0; } if(mPlayerGravityInterpolation<0) { mPlayerGravityInterpolation = 0; } if(mPlayerGravityInterpolation>1) { mPlayerGravityInterpolation = 1; } if(mIsJumping&&mJumpFactor>1) { NxVec3 fgp = mController->getPosition(); Ogre::Vector3 dirT = NxVector3(fgp-ogp); dirT.normalise(); Ogre::Vector3 upVC = NxVector3(gravityCont*mTimeStep*ff); upVC.normalise(); if(!dirT.directionEquals(upVC,Ogre::Radian(Ogre::Degree(45.0f)))) { mJumpFactor = 1; } } //Ogre::Vector3 pMoDir = NxVector3(opo - player->position); // takes gravity into account //Ogre::Vector3 velocity = pMoDir/deltaTT; //float vel[] = {velocity.x,velocity.y,velocity.z}; //alListenerfv(AL_VELOCITY,vel); if(mCrouching) { if(mCrouched) { float oldCrouch = mController->offset; mCrouchLevel+=mTimeStep*1.f; if(mCrouchLevel>mOffset) { mCrouchLevel = mOffset; mCrouched = false; mCrouching = false; } mController->offset = mCrouchLevel; if(!mController->setPosition(mController->getPosition(),false,mController->getUpVector(),false)) { mController->offset = oldCrouch; mCrouchLevel = oldCrouch; } else { } } else { float oldCrouch = mController->offset; mCrouchLevel-=mTimeStep*0.5f; if(mCrouchLevel<0.06f) { mCrouchLevel = 0.06f; mCrouched = true; mCrouching = false; } mController->offset = mCrouchLevel; if(!mController->setPosition(mController->getPosition(),false,mController->getUpVector(),false)) { mController->offset = oldCrouch; mCrouchLevel = oldCrouch; } else { } } } if(mInAirLast2&&!mHittingGround) { mHittingGround = true; if(mGroundImpact>0.05&&false) { mGroundImpactSpd = mGroundImpact; mGroundImpact/=40.f; } else { mHittingGround = false; mGroundImpactSpd = 0.f; mGroundImpact = 0.f; } //mGroundImpact } if(mImpactLevel>0) { //float recoverSpeed = 1.0f; mImpactLevel-=mTimeStep*1.6f; if(mImpactLevel<0) { mImpactLevel = 0; } } if(mHittingGround) { float spdC = 1.0f; spdC = 0.9f*((mGroundImpact/(mGroundImpactSpd/40)))+(0.095f*(1-(mGroundImpact/(mGroundImpactSpd/40)))); mImpactLevel+=mTimeStep*mGroundImpactSpd*spdC; if(mImpactLevel>0.8f) { mImpactLevel = 0.8f; } mGroundImpact-=mTimeStep*(mGroundImpactSpd*0.5f)*spdC; if(mGroundImpact<0) { mGroundImpact = 0; mHittingGround = false; } } if(mBobSwap) { if(!mMidair) mBobPeriod+=mPlayerSpeedLast*1.2f; } else { if(!mMidair) mBobPeriod-=mPlayerSpeedLast*1.2f; } if(abs(mBobPeriod)>=1.0f) { if(mBobPeriod>0) { mBobPeriod = 0.99f; } else { mBobPeriod = -0.99f; mBobLR = !mBobLR; if(mBobLRPeriod>0) { mBobLRPeriod = 1.99f; } else { mBobLRPeriod = -1.99f; } } mBobSwap = !mBobSwap; } NxVec3 upvv = mController->getUpVector(); upvv*=(mImpactLevel+mBobPeriod*0.f); Vector3 right1 = Ogre::Root::getSingletonPtr()->getSceneManager("mSceneManager")->getCamera("mMainCam")->getDerivedRight(); if(mBobLR) { if(!mMidair) mBobLRPeriod -= mPlayerSpeedLast*1.2f; } else { if(!mMidair) mBobLRPeriod += mPlayerSpeedLast*1.2f; } if(mBobLRPeriod>0) { right1*=(0.0625f*((mBobLRPeriod))); } else { right1*=(0.0625f*((mBobLRPeriod))); } right1*=0; p_2 = p_1; //p_1 = Vector3(mController->getEyePosition().x(),mController->getEyePosition().y(),mController->getEyePosition().z()); p_1 = Vector3(mController->getEyePosition().x()-upvv.x()-right1.x,mController->getEyePosition().y()-upvv.y()-right1.y,mController->getEyePosition().z()-upvv.z()-right1.z); // if our speed has gone up then increment the interpolation thingy mAccumulation -= mTimeStep; } mInterpolation = mAccumulation/mTimeStep; }
Vector3 Vector3::Cross2(Vector3 vect,Vector3 vect2){ return Vector3( (vect.x * vect2.z) - (vect.z * vect2.x), vect.y, (vect.z * vect2.x) - (vect.x * vect2.z) ); }
void SceneTexture::Init() { // Init VBO here glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Set background color glEnable(GL_DEPTH_TEST); // Enable depth buffer and depth testing glEnable(GL_CULL_FACE); // Enable back face culling glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Default to fill mode //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Generate a default VAO for now glGenVertexArrays(1, &m_vertexArrayID); glBindVertexArray(m_vertexArrayID); m_programID = LoadShaders("Shader//Texture.vertexshader", "Shader//Texture.fragmentshader"); m_parameters[U_MVP] = glGetUniformLocation(m_programID, "MVP"); m_parameters[U_MODELVIEW] = glGetUniformLocation(m_programID, "MV"); m_parameters[U_MODELVIEW_INVERSE_TRANSPOSE] = glGetUniformLocation(m_programID, "MV_inverse_transpose"); m_parameters[U_MATERIAL_AMBIENT] = glGetUniformLocation(m_programID, "material.kAmbient"); m_parameters[U_MATERIAL_DIFFUSE] = glGetUniformLocation(m_programID, "material.kDiffuse"); m_parameters[U_MATERIAL_SPECULAR] = glGetUniformLocation(m_programID, "material.kSpecular"); m_parameters[U_MATERIAL_SHININESS] = glGetUniformLocation(m_programID, "material.kShininess"); m_parameters[U_LIGHT0_POSITION] = glGetUniformLocation(m_programID, "lights[0].position_cameraspace"); m_parameters[U_LIGHT0_COLOR] = glGetUniformLocation(m_programID, "lights[0].color"); m_parameters[U_LIGHT0_POWER] = glGetUniformLocation(m_programID, "lights[0].power"); m_parameters[U_LIGHT0_KC] = glGetUniformLocation(m_programID, "lights[0].kC"); m_parameters[U_LIGHT0_KL] = glGetUniformLocation(m_programID, "lights[0].kL"); m_parameters[U_LIGHT0_KQ] = glGetUniformLocation(m_programID, "lights[0].kQ"); m_parameters[U_LIGHTENABLED] = glGetUniformLocation(m_programID, "lightEnabled"); m_parameters[U_NUMLIGHTS] = glGetUniformLocation(m_programID, "numLights"); //in case you missed out practical 7 // Get a handle for our "colorTexture" uniform m_parameters[U_COLOR_TEXTURE_ENABLED] = glGetUniformLocation(m_programID, "colorTextureEnabled"); m_parameters[U_COLOR_TEXTURE] = glGetUniformLocation(m_programID, "colorTexture"); glUseProgram(m_programID); //variable to rotate geometry //Initialize camera settings camera.Init(Vector3(4, 3, 3), Vector3(0, 0, 0), Vector3(0, 1, 0)); meshList[GEO_AXES] = MeshBuilder::GenerateAxes("AXES", 1000, 1000, 1000); Mtx44 projection; projection.SetToPerspective(45.f, 4.f / 3.f, 0.1f, 1000.f); projectionStack.LoadMatrix(projection); light[0].position.Set(0, 20, 0); light[0].color.Set(1, 1, 1); light[0].power = 1; light[0].kC = 1.f; light[0].kL = 0.01f; light[0].kQ = 0.001f; // Make sure you pass uniform parameters after glUseProgram() glUniform3fv(m_parameters[U_LIGHT0_COLOR], 1, &light[0].color.r); glUniform1f(m_parameters[U_LIGHT0_POWER], light[0].power); glUniform1f(m_parameters[U_LIGHT0_KC], light[0].kC); glUniform1f(m_parameters[U_LIGHT0_KL], light[0].kL); glUniform1f(m_parameters[U_LIGHT0_KQ], light[0].kQ); glUniform1i(m_parameters[U_NUMLIGHTS], 1); meshList[GEO_LIGHTBALL] = MeshBuilder::GenerateSphere("LIGHT", Color(1, 1, 1), 36, 36); meshList[GEO_QUAD] = MeshBuilder::GenerateQuad("quad", Color(1, 1, 1)); meshList[GEO_QUAD]->textureID = LoadTGA("Image//color2.tga"); }
bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result) { //give me back regular physics engine logic //this is madness //and most people using this function will think //what it does is simpler than using physics //this took about a week to get right.. //but is it right? who knows at this point.. if (r_result) { r_result->collider_id = 0; r_result->collider_shape = 0; } AABB body_aabb; for (int i = 0; i < p_body->get_shape_count(); i++) { if (i == 0) body_aabb = p_body->get_shape_aabb(i); else body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); } // Undo the currently transform the physics server is aware of and apply the provided one body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); body_aabb = body_aabb.grow(p_margin); Transform body_transform = p_from; { //STEP 1, FREE BODY IF STUCK const int max_results = 32; int recover_attempts = 4; Vector3 sr[max_results * 2]; do { PhysicsServerSW::CollCbkData cbk; cbk.max = max_results; cbk.amount = 0; cbk.ptr = sr; PhysicsServerSW::CollCbkData *cbkptr = &cbk; CollisionSolverSW::CallbackResult cbkres = PhysicsServerSW::_shape_col_cbk; bool collided = false; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int j = 0; j < p_body->get_shape_count(); j++) { if (p_body->is_shape_set_as_disabled(j)) continue; Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); ShapeSW *body_shape = p_body->get_shape(j); for (int i = 0; i < amount; i++) { const CollisionObjectSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; if (CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { collided = cbk.amount > 0; } } } if (!collided) { break; } Vector3 recover_motion; for (int i = 0; i < cbk.amount; i++) { Vector3 a = sr[i * 2 + 0]; Vector3 b = sr[i * 2 + 1]; recover_motion += (b - a) * 0.4; } if (recover_motion == Vector3()) { collided = false; break; } body_transform.origin += recover_motion; body_aabb.position += recover_motion; recover_attempts--; } while (recover_attempts); } real_t safe = 1.0; real_t unsafe = 1.0; int best_shape = -1; { // STEP 2 ATTEMPT MOTION AABB motion_aabb = body_aabb; motion_aabb.position += p_motion; motion_aabb = motion_aabb.merge(body_aabb); int amount = _cull_aabb_for_body(p_body, motion_aabb); for (int j = 0; j < p_body->get_shape_count(); j++) { if (p_body->is_shape_set_as_disabled(j)) continue; Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); ShapeSW *body_shape = p_body->get_shape(j); Transform body_shape_xform_inv = body_shape_xform.affine_inverse(); MotionShapeSW mshape; mshape.shape = body_shape; mshape.motion = body_shape_xform_inv.basis.xform(p_motion); bool stuck = false; real_t best_safe = 1; real_t best_unsafe = 1; for (int i = 0; i < amount; i++) { const CollisionObjectSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; //test initial overlap, does it collide if going all the way? Vector3 point_A, point_B; Vector3 sep_axis = p_motion.normalized(); Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); //test initial overlap, does it collide if going all the way? if (CollisionSolverSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { //print_line("failed motion cast (no collision)"); continue; } sep_axis = p_motion.normalized(); if (!CollisionSolverSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { //print_line("failed motion cast (no collision)"); stuck = true; break; } //just do kinematic solving real_t low = 0; real_t hi = 1; Vector3 mnormal = p_motion.normalized(); for (int i = 0; i < 8; i++) { //steps should be customizable.. real_t ofs = (low + hi) * 0.5; Vector3 sep = mnormal; //important optimization for this to work fast enough mshape.motion = body_shape_xform_inv.basis.xform(p_motion * ofs); Vector3 lA, lB; bool collided = !CollisionSolverSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep); if (collided) { //print_line(itos(i)+": "+rtos(ofs)); hi = ofs; } else { point_A = lA; point_B = lB; low = ofs; } } if (low < best_safe) { best_safe = low; best_unsafe = hi; } } if (stuck) { safe = 0; unsafe = 0; best_shape = j; //sadly it's the best break; } if (best_safe == 1.0) { continue; } if (best_safe < safe) { safe = best_safe; unsafe = best_unsafe; best_shape = j; } } } bool collided = false; if (safe >= 1) { //not collided collided = false; if (r_result) { r_result->motion = p_motion; r_result->remainder = Vector3(); r_result->motion += (body_transform.get_origin() - p_from.get_origin()); } } else { //it collided, let's get the rest info in unsafe advance Transform ugt = body_transform; ugt.origin += p_motion * unsafe; _RestCallbackData rcd; rcd.best_len = 0; rcd.best_object = NULL; rcd.best_shape = 0; Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape); ShapeSW *body_shape = p_body->get_shape(best_shape); body_aabb.position += p_motion * unsafe; int amount = _cull_aabb_for_body(p_body, body_aabb); for (int i = 0; i < amount; i++) { const CollisionObjectSW *col_obj = intersection_query_results[i]; int shape_idx = intersection_query_subindex_results[i]; rcd.object = col_obj; rcd.shape = shape_idx; bool sc = CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, NULL, p_margin); if (!sc) continue; } if (rcd.best_len != 0) { if (r_result) { r_result->collider = rcd.best_object->get_self(); r_result->collider_id = rcd.best_object->get_instance_id(); r_result->collider_shape = rcd.best_shape; r_result->collision_local_shape = best_shape; r_result->collision_normal = rcd.best_normal; r_result->collision_point = rcd.best_contact; //r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape); const BodySW *body = static_cast<const BodySW *>(rcd.best_object); //Vector3 rel_vec = r_result->collision_point - body->get_transform().get_origin(); // r_result->collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); r_result->motion = safe * p_motion; r_result->remainder = p_motion - safe * p_motion; r_result->motion += (body_transform.get_origin() - p_from.get_origin()); } collided = true; } else { if (r_result) { r_result->motion = p_motion; r_result->remainder = Vector3(); r_result->motion += (body_transform.get_origin() - p_from.get_origin()); } collided = false; } } return collided; }
#include "Vector3.h" #include "Vector4.h" #include "Matrix.h" #include "Converter.h" const Vector3 Vector3::zero = Vector3(0, 0, 0); const Vector3 Vector3::one = Vector3(1, 1, 1); const Vector3 Vector3::right = Vector3(1, 0, 0); const Vector3 Vector3::up = Vector3(0, 1, 0); const Vector3 Vector3::forward = Vector3(0, 0, 1); const Vector3 Vector3::left = -Vector3::right; const Vector3 Vector3::down = -Vector3::up; const Vector3 Vector3::back = -Vector3::forward; Vector3::Vector3() : D3DXVECTOR3(0, 0, 0) {} Vector3::Vector3(D3DVECTOR v) : D3DXVECTOR3(v.x, v.y, v.z) {} Vector3::Vector3(float f) : D3DXVECTOR3(f, f, f) {} Vector3::Vector3(float x, float y, float z) : D3DXVECTOR3(x, y, z) {} Vector3::Vector3(const D3DXVECTOR3& v) : D3DXVECTOR3(v) {} Vector3::Vector3(const Vector2& v) : D3DXVECTOR3(v.x, v.y, 1) {} Vector3::Vector3(const D3DCOLORVALUE& v) : D3DXVECTOR3(v.r, v.g, v.b) {} Vector3 Vector3::v; Vector3::operator D3DCOLORVALUE() const {
// Cross product Vector3 Vector3::cross(const Vector3& v) const { return Vector3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
Vector3 ILocatable::rotate(float X,float Y,float Z) {return rotate(Vector3(X,Y,Z));}
Vector3 Vector3::normalized() const { float m = magnitude(); return Vector3(x/m, y/m, z/m); }
void MeshLibraryEditor::_import_scene(Node *p_scene, Ref<MeshLibrary> p_library, bool p_merge) { if (!p_merge) p_library->clear(); for(int i=0;i<p_scene->get_child_count();i++) { Node *child = p_scene->get_child(i); if (!child->cast_to<MeshInstance>()) { if (child->get_child_count()>0) { child=child->get_child(0); if (!child->cast_to<MeshInstance>()) { continue; } } else continue; } MeshInstance *mi = child->cast_to<MeshInstance>(); Ref<Mesh> mesh=mi->get_mesh(); if (mesh.is_null()) continue; int id = p_library->find_item_name(mi->get_name()); if (id<0) { id=p_library->get_last_unused_item_id(); p_library->create_item(id); p_library->set_item_name(id,mi->get_name()); } p_library->set_item_mesh(id,mesh); Ref<Shape> collision; for(int j=0;j<mi->get_child_count();j++) { #if 1 Node *child2 = mi->get_child(j); if (!child2->cast_to<StaticBody>()) continue; StaticBody *sb = child2->cast_to<StaticBody>(); if (sb->get_shape_count()==0) continue; collision=sb->get_shape(0); if (!collision.is_null()) break; #endif } if (!collision.is_null()) { p_library->set_item_shape(id,collision); } Ref<NavigationMesh> navmesh; for(int j=0;j<mi->get_child_count();j++) { Node *child2 = mi->get_child(j); if (!child2->cast_to<NavigationMeshInstance>()) continue; NavigationMeshInstance *sb = child2->cast_to<NavigationMeshInstance>(); navmesh=sb->get_navigation_mesh(); if (!navmesh.is_null()) break; } if(!navmesh.is_null()){ p_library->set_item_navmesh(id, navmesh); } } //generate previews! if (1) { Vector<int> ids = p_library->get_item_list(); RID vp = VS::get_singleton()->viewport_create(); VS::ViewportRect vr; vr.x=0; vr.y=0; vr.width=EditorSettings::get_singleton()->get("editors/grid_map/preview_size"); vr.height=EditorSettings::get_singleton()->get("editors/grid_map/preview_size"); VS::get_singleton()->viewport_set_rect(vp,vr); VS::get_singleton()->viewport_set_as_render_target(vp,true); VS::get_singleton()->viewport_set_render_target_update_mode(vp,VS::RENDER_TARGET_UPDATE_ALWAYS); RID scen = VS::get_singleton()->scenario_create(); VS::get_singleton()->viewport_set_scenario(vp,scen); RID cam = VS::get_singleton()->camera_create(); VS::get_singleton()->camera_set_transform(cam, Transform() ); VS::get_singleton()->viewport_attach_camera(vp,cam); RID light = VS::get_singleton()->light_create(VS::LIGHT_DIRECTIONAL); RID lightinst = VS::get_singleton()->instance_create2(light,scen); VS::get_singleton()->camera_set_orthogonal(cam,1.0,0.01,1000.0); EditorProgress ep("mlib",TTR("Creating Mesh Library"),ids.size()); for(int i=0;i<ids.size();i++) { int id=ids[i]; Ref<Mesh> mesh = p_library->get_item_mesh(id); if (!mesh.is_valid()) continue; AABB aabb= mesh->get_aabb(); print_line("aabb: "+aabb); Vector3 ofs = aabb.pos + aabb.size*0.5; aabb.pos-=ofs; Transform xform; xform.basis=Matrix3().rotated(Vector3(0,1,0),-Math_PI*0.25); xform.basis = Matrix3().rotated(Vector3(1,0,0),Math_PI*0.25)*xform.basis; AABB rot_aabb = xform.xform(aabb); print_line("rot_aabb: "+rot_aabb); float m = MAX(rot_aabb.size.x,rot_aabb.size.y)*0.5; if (m==0) continue; m=1.0/m; m*=0.5; print_line("scale: "+rtos(m)); xform.basis.scale(Vector3(m,m,m)); xform.origin=-xform.basis.xform(ofs); //-ofs*m; xform.origin.z-=rot_aabb.size.z*2; RID inst = VS::get_singleton()->instance_create2(mesh->get_rid(),scen); VS::get_singleton()->instance_set_transform(inst,xform); ep.step(TTR("Thumbnail.."),i); VS::get_singleton()->viewport_queue_screen_capture(vp); Main::iteration(); Image img = VS::get_singleton()->viewport_get_screen_capture(vp); ERR_CONTINUE(img.empty()); Ref<ImageTexture> it( memnew( ImageTexture )); it->create_from_image(img); p_library->set_item_preview(id,it); //print_line("loaded image, size: "+rtos(m)+" dist: "+rtos(dist)+" empty?"+itos(img.empty())+" w: "+itos(it->get_width())+" h: "+itos(it->get_height())); VS::get_singleton()->free(inst); } VS::get_singleton()->free(lightinst); VS::get_singleton()->free(light); VS::get_singleton()->free(vp); VS::get_singleton()->free(cam); VS::get_singleton()->free(scen); } }
// Arithmetic operators Vector3 Vector3::operator-() const { return Vector3(-x, -y, -z); }
Plane::Plane(const Vector3 *normal, FLOAT d) { Normal = Vector3(normal->X,normal->Y,normal->Z); D = d; };
SpotLight::SpotLight(void) : SpotLight(Color::White, Vector3(0.f, 0.f, 0.f)) { }
Vector3 TerrainFractal::getPoint(double x, double y) const { return x > 0 && x < terrain_width && y > 0 && y < terrain_height ? Vector3(x, y, Noise::noise(x, y)) : Constante::noIntersectVec; }
#include "Matrix3.h" #include "OGRE/OgreMatrix3.h" #include <math.h> #include <iomanip> //________________________________________________________________________ const Matrix3 Matrix3::ZERO(0.0f); const Matrix3 Matrix3::IDENTITY(Vector3(1.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f), Vector3(0.0f, 0.0f, 1.0f)); //________________________________________________________________________ namespace { Vector3 CalculateBasisVectorForRotationAxis(const Vector3& v, const Vector3& vRotationAxis, const float& fRotationInRadians) { const Vector3 vNormalizedRotationAxis = Normalize(vRotationAxis); const Vector3 vProjV = Dot(v, vNormalizedRotationAxis) * vNormalizedRotationAxis; const Vector3 vPerpV = v - vProjV; return vProjV + (cosf(fRotationInRadians) * vPerpV) + (sinf(fRotationInRadians) * Cross(vNormalizedRotationAxis, v)); } } //________________________________________________________________________
// Negation const Vector3 operator-(void) const { return Vector3(-x, -y, -z); }
Vector3 operator*(const Matrix3& a, const Vector3& v) { return Vector3(Dot(a.GetRow1(), v), Dot(a.GetRow2(), v), Dot(a.GetRow3(), v)); }
Vector3 Matrix4::GetRight() const { return Vector3(m[0][0], m[1][0], m[2][0]); }
//Cross Products Vector3 Vector3::Cross(Vector3 vect){ return Vector3( y * vect.z - z * vect.y, z * vect.x - x * vect.z, x * vect.y - y * vect.x); }