示例#1
0
// Triangulate a no convex polygon
void glc::triangulatePolygon(QList<GLuint>* pIndexList, const QList<float>& bulkList)
{
	int size= pIndexList->size();
	if (polygonIsConvex(pIndexList, bulkList))
	{
		QList<GLuint> indexList(*pIndexList);
		pIndexList->clear();
		for (int i= 0; i < size - 2; ++i)
		{
			pIndexList->append(indexList.at(0));
			pIndexList->append(indexList.at(i + 1));
			pIndexList->append(indexList.at(i + 2));
		}
	}
	else
	{
		// Get the polygon vertice
		QList<GLC_Point3d> originPoints;
		QHash<int, int> indexMap;

		QList<int> face;
		GLC_Point3d currentPoint;
		int delta= 0;
		for (int i= 0; i < size; ++i)
		{
			const int currentIndex= pIndexList->at(i);
			currentPoint= GLC_Point3d(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2));
			if (!originPoints.contains(currentPoint))
			{
				originPoints.append(GLC_Point3d(bulkList.at(currentIndex * 3), bulkList.at(currentIndex * 3 + 1), bulkList.at(currentIndex * 3 + 2)));
				indexMap.insert(i - delta, currentIndex);
				face.append(i - delta);
			}
			else
			{
				qDebug() << "Multi points";
				++delta;
			}
		}
		// Values of PindexList must be reset
		pIndexList->clear();

		// Update size
		size= size - delta;

		// Check new size
		if (size < 3) return;

		//-------------- Change frame to mach polygon plane
			// Compute face normal
			const GLC_Point3d point1(originPoints[0]);
			const GLC_Point3d point2(originPoints[1]);
			const GLC_Point3d point3(originPoints[2]);

			const GLC_Vector3d edge1(point2 - point1);
			const GLC_Vector3d edge2(point3 - point2);

			GLC_Vector3d polygonPlaneNormal(edge1 ^ edge2);
			polygonPlaneNormal.normalize();

			// Create the transformation matrix
			GLC_Matrix4x4 transformation;

			GLC_Vector3d rotationAxis(polygonPlaneNormal ^ Z_AXIS);
			if (!rotationAxis.isNull())
			{
				const double angle= acos(polygonPlaneNormal * Z_AXIS);
				transformation.setMatRot(rotationAxis, angle);
			}

			QList<GLC_Point2d> polygon;
			// Transform polygon vertexs
			for (int i=0; i < size; ++i)
			{
				originPoints[i]= transformation * originPoints[i];
				// Create 2d vector
				polygon << originPoints[i].toVector2d(Z_AXIS);
			}
			// Create the index
			QList<int> index= face;

			const bool faceIsCounterclockwise= isCounterclockwiseOrdered(polygon);

			if(!faceIsCounterclockwise)
			{
				//qDebug() << "face Is Not Counterclockwise";
				const int max= size / 2;
				for (int i= 0; i < max; ++i)
				{
					polygon.swap(i, size - 1 -i);
					int temp= face[i];
					face[i]= face[size - 1 - i];
					face[size - 1 - i]= temp;
				}
			}

            QList<int> tList;
			triangulate(polygon, index, tList);
			size= tList.size();
			for (int i= 0; i < size; i+= 3)
			{
				// Avoid normal problem
				if (faceIsCounterclockwise)
				{
					pIndexList->append(indexMap.value(face[tList[i]]));
					pIndexList->append(indexMap.value(face[tList[i + 1]]));
					pIndexList->append(indexMap.value(face[tList[i + 2]]));
				}
				else
				{
					pIndexList->append(indexMap.value(face[tList[i + 2]]));
					pIndexList->append(indexMap.value(face[tList[i + 1]]));
					pIndexList->append(indexMap.value(face[tList[i]]));
				}
			}
			Q_ASSERT(size == pIndexList->size());
	}

}
void XMLParserCollisionsMap::parse(DataUnion& data) {
    std::vector<StructCollision*>* result = new std::vector<StructCollision*>();

    //get root node
    tinyxml2::XMLElement* detailsMap = doc->FirstChildElement("map");
    if (detailsMap == nullptr) {
        std::cout << "Vacio?" << std::endl;
    }

    //get the node of collisions
    tinyxml2::XMLElement* collisions = detailsMap->FirstChildElement("objectgroup");
    //get the object/collision 
    tinyxml2::XMLElement* object = collisions->FirstChildElement("object");
    while (object) {
        //creo el objeto colisionable a crear
        StructCollision* collisionObject = new StructCollision();
        collisionObject->vertices = new sf::VertexArray();

        //get the position
        sf::Vector2f position(object->DoubleAttribute("x"), object->DoubleAttribute("y"));
        collisionObject->position = position;
        collisionObject->typeCollision = object->Attribute("type");
        
        if(collisionObject->typeCollision.compare("ChangeLevel")==0){
            collisionObject->data=new std::string(object->Attribute("level"));
        }else{
            collisionObject->data=nullptr;
        }
        
        //get the points
        tinyxml2::XMLElement* vertices = object->FirstChildElement("polyline");

        //recojo los puntos
        char* points = strdup(vertices->Attribute("points"));
        //trato la tira de puntos
        char* number = strtok(points, " ,");
        sf::Vertex vertex;
        vertex.color = sf::Color::Red;
        bool isX = true;
        while (number != nullptr) {
            if (isX) {
                vertex = sf::Vertex();
                vertex.position.x = atof(number);
            } else {
                vertex.position.y = atof(number);
                collisionObject->vertices->append(vertex);
                
            }
            isX = !isX;
            number = strtok(nullptr, " ,");
        }

        //compruebo que el poligono esté bien formado
        //assert(polygonIsConvex(collisionObject));
        if (!polygonIsConvex(collisionObject)) {
            std::cout << "No es convexo" << std::endl;
        }
        result->push_back(collisionObject);
        object = object->NextSiblingElement("object");
    }

    data.collisions = result;
}