Beispiel #1
0
/*! Uses the stored vectors of vertices and triangles to initialize geometry; if
  these are not yet in memory, will first ask the manager to load them.
*/
int GeomGraspitDBModel::loadGeometry()
{
  // if geometry has not been already loaded, ask the manager to load it
  if (GetVertices().empty()) {
    if (!mManager) {
      DBGA("Cannot load geometry from database; missing manager");
      return FAILURE;
    }
    if (!mManager->LoadModelGeometry(this)) {
      DBGA("Manager failed to load geometry for model from database");
      return FAILURE;
    }
    if (GetVertices().empty() || GetTriangles().empty()) {
      DBGA("Empty geometry loaded from database");
      return FAILURE;
    }
  }
  //convert geometry to a format that graspit understands and load it
  std::vector<position> vertices;
  if (GetVertices().size() % 3 != 0) {
    DBGA("Load model geometry from database: size of vertices vector is not a multiple of 3");
    return FAILURE;
  }
  for (size_t i = 0; i < GetVertices().size() / 3; i++) {
    vertices.push_back(position(GetVertices().at(3 * i + 0), GetVertices().at(3 * i + 1), GetVertices().at(3 * i + 2)));
  }

  return mGraspableBody->loadGeometryMemory(vertices, GetTriangles());
}
void MD3Model::GetIndices(uint32_t s, GLushort*& indexData, uint32_t& triangleCount) const {
    assert(s < header->numSurfaces);

    MD3::Surface_t*    surface = surfaces[s];
    MD3::Triangle_t* triangles = GetTriangles(s);
    
    triangleCount = surface->numTriangles;
    indexData = new GLushort[3*triangleCount];

    // Could probably re-index this and play with pointer arithmetic
    // to do this in less lines
    for (uint32_t i=0; i<triangleCount; ++i) {
        indexData[3*i]   = (GLushort)triangles[i].a;
        indexData[3*i+1] = (GLushort)triangles[i].c;
        indexData[3*i+2] = (GLushort)triangles[i].b;
    }
}
Beispiel #3
0
void ConvexClipper<Real>::Convert (ConvexPolyhedron<Real>& polyhedron)
{
    // Get visible vertices.
    int numVertices = (int)mVertices.size();
    std::vector<Vector3<Real> > points;
    int* vMap = new1<int>(numVertices);
    memset(vMap, 0xFF, numVertices*sizeof(int));
    for (int v = 0; v < numVertices; ++v)
    {
        const Vertex& vertex = mVertices[v];
        if (vertex.Visible)
        {
            vMap[v] = (int)points.size();
            points.push_back(vertex.Point);
        }
    }

    std::vector<int> indices;
    std::vector<Plane3<Real> > planes;
    GetTriangles(indices, planes);

    // Reorder the indices.
    for (int c = 0; c < (int)indices.size(); ++c)
    {
        int oldC = indices[c];
        assertion(0 <= oldC && oldC < numVertices, "Index out of range.\n");
        int newC = vMap[oldC];
        assertion(0 <= newC && newC < (int)points.size(),
            "Index out of range.\n");
        indices[c] = newC;
    }

    delete1(vMap);

    polyhedron.Create(points, indices, planes);
}
Beispiel #4
0
  void Mesh::AddData(const Mesh& mesh, const ezTransform& transform)
  {
    ezMat4 transformMat = transform.GetAsMat4();
    ezMat4 normalTransformMat = transformMat.GetInverse(0.0f).GetTranspose();

    // Create new triangles.
    ezUInt32 oldTriangleCount = GetNumTriangles();
    AddTriangles(mesh.GetNumTriangles());

    ezArrayPtr<const Mesh::Triangle> sourceTriangles = mesh.GetTriangles();
    ezArrayPtr<const Mesh::Triangle> targetTriangles = GetTriangles().GetSubArray(oldTriangleCount);
    EZ_ASSERT_DEBUG(sourceTriangles.GetCount() == targetTriangles.GetCount(), "Something is wrong with triangle allocation!");

    for (auto it = mesh.m_VertexDataStreams.GetIterator(); it.IsValid(); ++it)
    {
      const VertexDataStream* sourceStream = it.Value();
      VertexDataStream* targetStream = AddDataStream(static_cast<ezGALVertexAttributeSemantic::Enum>(it.Key()),
                                                     sourceStream->GetNumElementsPerVertex(), sourceStream->GetElementType());
      if (!targetStream)
      {
        ezLog::SeriousWarning("Cannot merge mesh {0} properly since it has a vertex data stream with semantic {1} that uses {2} elements "
                              "instead of 'unkown' which is used by the merge target. Skipping this data stream.",
                              mesh.m_Name, it.Key(), sourceStream->GetNumElementsPerVertex());
        continue;
      }

      // Copy data.
      ezUInt32 targetBaseDataIndex = targetStream->m_Data.GetCount();
      targetStream->m_Data.PushBackRange(sourceStream->m_Data);

      // Transform data.
      if (!transform.IsIdentical(ezTransform::IdentityTransform()))
      {
        const ezUInt32 attributeSize = targetStream->GetAttributeSize();

        // Positions
        if (it.Key() == ezGALVertexAttributeSemantic::Position)
        {
          for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize)
          {
            ezVec3& pos = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]);
            pos = transformMat.TransformPosition(pos);
          }
        }
        // Directions
        else if (it.Key() == ezGALVertexAttributeSemantic::Normal || it.Key() == ezGALVertexAttributeSemantic::Tangent ||
                 it.Key() == ezGALVertexAttributeSemantic::BiTangent)
        {
          for (ezUInt32 i = targetBaseDataIndex; i < targetStream->m_Data.GetCount(); i += attributeSize)
          {
            ezVec3& dir = *reinterpret_cast<ezVec3*>(&targetStream->m_Data[i]);
            dir = normalTransformMat.TransformDirection(dir);
          }
        }
      }

      // Set mapping
      for (ezUInt32 tri = 0; tri < sourceTriangles.GetCount(); ++tri)
      {
        for (int v = 0; v < 3; ++v)
        {
          VertexDataIndex sourceDataIndex = sourceStream->GetDataIndex(sourceTriangles[tri].m_Vertices[v]);
          if (sourceDataIndex.IsValid())
            targetStream->SetDataIndex(targetTriangles[tri].m_Vertices[v], targetBaseDataIndex + sourceDataIndex.GetValue());
        }
      }
    }

    // Add submeshes.
    ezUInt32 oldSubMeshCount = m_SubMeshes.GetCount();
    m_SubMeshes.PushBackRange(mesh.m_SubMeshes);
    for (ezUInt32 i = oldSubMeshCount; i < m_SubMeshes.GetCount(); ++i)
    {
      m_SubMeshes[i].m_uiFirstTriangle += oldTriangleCount;
    }

    // Add skeleton if existent
    // TODO: What if multiple, incompatible skeletons are found(?)
    // For now: Remove skeleton and import unskinned
    // if (mesh.m_pSkeleton)
    //{
    //  if (m_pSkeleton)
    //  {
    //    if (!m_pSkeleton->IsCompatibleWith(mesh.m_pSkeleton.Borrow()))
    //    {
    //      ezLog::Warning("Found incompatible skeletons during mesh merging in mesh '{0}', import will be without skeletons!",
    //      m_Name.GetData()); m_pSkeleton.Reset();
    //    }
    //  }
    //  else
    //  {
    //    m_pSkeleton = EZ_DEFAULT_NEW(ezSkeleton, *mesh.m_pSkeleton);
    //  }
    //}
  }
Beispiel #5
0
bool
AreaSurfaceMesh::GetLineSegmentFacesAndMesh(
	__in const NWN::Vector2 & Start,
	__in const NWN::Vector2 & End,
	__in_opt const TileSurfaceMesh * ExcludeSurfaceMesh,
	__in bool Walkable,
	__out const SurfaceMeshFace * * Face1,
	__out const SurfaceMeshFace * * Face2,
	__out const TileSurfaceMesh * * SurfaceMesh
	) const
/*++

Routine Description:

	Given the start and end bounding points of a line segment, which must
	reside entirely within the same tile surface mesh (although it may reside
	upon a seam), this routine returns the walk mesh faces that contain the
	start and end points, respectively.  Both faces are guaranteed to be joined
	to the same tile surface mesh, which is also returned.

	Only walkable faces are returned.

Arguments:

	Start - Supplies the first point of the line segment.  The line segment
	        must reside entirely within one tile surface mesh.

	End - Supplies the second point of the line segment.  The line segment must
	      reside entirely within one tile surface mesh.

	ExcludeSurfaceMesh - Optionally supplies a surface mesh to exclude if there
	                     should be be a tie between which surface mesh to pick
	                     for a particular triangle.  If the caller is following
	                     a line through several intersecting segments, then
	                     subsequent calls must specify the previous surface
	                     mesh in order to ensure forward progress.

	Walkable - Supplies a Boolean value indicating whether only walkable faces
	           are to be considered.

	Face1 - Receives the face containing the Start point.

	Face2 - Receives the face containing the End point.

	SurfaceMesh - Receives the tile surface mesh that both faces are joined to.

Return Value:

	Returns true two faces joined to the same tile surface mesh and containing
	the Start and End points could be located.  Otherwise, the routine returns
	false.

Environment:

	User mode.

--*/
{
	const SurfaceMeshFace * f1;
	const TileSurfaceMesh * t1;
	const SurfaceMeshFace * f2;
	const TileSurfaceMesh * t2;

	f1 = FindFace( Start, &t1 );

	if (f1 == NULL)
		return false;

	if ((Walkable) && (!(f1->Flags & SurfaceMeshFace::WALKABLE)))
		return false;

	f2 = FindFace( End, &t2 );

	if (f2 == NULL)
		return false;

	if ((Walkable) && (!(f2->Flags & SurfaceMeshFace::WALKABLE)))
		return false;

//	WriteText( "Try (%f, %f) and (%f, %f)\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

	//
	// If the points were not in the same surface mesh then it's possible
	// that we picked the wrong one.  This may happen as it is not very
	// well defined what the behavior should be should we be right on a
	// seam between tile surface walkmesh objects.
	//
	// In the seam case, we iterate through all neighbor edges, looking for
	// the edge that matches the line.  Once we've got the edge, we'll pick
	// the two triangles that are in the same tiele surface walkmesh.
	//

	if ((t1 != t2) || (t1 == ExcludeSurfaceMesh))
	{
		const SurfaceMeshFace * faces[ 4 ];
		const SurfaceMeshEdge * e1;
		const SurfaceMeshEdge * e2;
		NWN::Vector2            v1;
		NWN::Vector2            v2;
		NWN::Vector2            I0;
		unsigned long           TestFaceId;
		bool                    Parallel;

//		WriteText( "We weren't in the same walkmesh!\n" );

		//
		// Build a list of candidate faces.  We start with the two that we've
		// originally found, but these may be on the wrong sides -- that is,
		// they might not be on the correct tile surface walkmesh.  Check the
		// other sides (if applicable); two of the faces will be on opposite
		// walkmesh tiles (i.e. the triangle we just walked through, and the
		// triangle that we'll walk through after we pass through this next
		// walkmesh.  Conversely, two of the faces will be on the correct
		// walkmesh tile -- the next walkmesh tile up.
		//

		faces[ 0 ] = f1;
		faces[ 1 ] = NULL;
		faces[ 2 ] = f2;
		faces[ 3 ] = NULL;

		for (unsigned long i = 0; i < 3; i += 1)
		{
			e1 = &GetEdges( )[ f1->Edges[ i ] ];

			//
			// Check that the edge intersects with our line segment's overlap
			// coordinate set.
			//

			v1.x = GetPoints( )[ e1->Points1 ].x;
			v1.y = GetPoints( )[ e1->Points1 ].y;
			v2.x = GetPoints( )[ e1->Points2 ].x;
			v2.y = GetPoints( )[ e1->Points2 ].y;

			if (!Math::IntersectSegments2( Start, End, v1, v2, I0, Parallel ))
			{
				e1 = NULL;
				continue;
			}

			//
			// We want the triangle on the other edge of this face.  Try it
			// too.
			//

			if (GetFaceId( f1 ) != e1->Triangles1)
				TestFaceId = e1->Triangles1;
			else
				TestFaceId = e1->Triangles2;

			if (TestFaceId == (unsigned long) -1)
				continue;

			faces[ 1 ] = &GetTriangles( )[ TestFaceId ];

			if (!IsPointInTriangle( faces[ 1 ], Start, GetPoints( ) ))
			{
				faces[ 1 ] = NULL;
				continue;
			}

			break;
		}

		for (unsigned long i = 0; i < 3; i += 1)
		{
			e2 = &GetEdges( )[ f2->Edges[ i ] ];

			//
			// Check that the edge intersects with our line segment's overlap
			// coordinate set.
			//

			v1.x = GetPoints( )[ e2->Points1 ].x;
			v1.y = GetPoints( )[ e2->Points1 ].y;
			v2.x = GetPoints( )[ e2->Points2 ].x;
			v2.y = GetPoints( )[ e2->Points2 ].y;

			if (!Math::IntersectSegments2( Start, End, v1, v2, I0, Parallel ))
			{
				e2 = NULL;
				continue;
			}

			//
			// We want the triangle on the other edge of this face.  Try it
			// too.
			//

			if (GetFaceId( f2 ) != e2->Triangles1)
				TestFaceId = e2->Triangles1;
			else
				TestFaceId = e2->Triangles2;

			if (TestFaceId == (unsigned long) -1)
				continue;

			faces[ 3 ] = &GetTriangles( )[ TestFaceId ];

			if (!IsPointInTriangle( faces[ 3 ], End, GetPoints( )))
			{
				faces[ 3 ] = NULL;
				continue;
			}

			break;
		}

//		faces[ 0 ] = e1->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e1->Triangles1 ];
//		faces[ 1 ] = e1->Triangles2 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e1->Triangles2 ];
//		faces[ 2 ] = e2->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e2->Triangles1 ];
//		faces[ 3 ] = e2->Triangles1 == (unsigned long) -1 ? NULL : &GetTriangles( )[ e2->Triangles2 ];

		f1 = NULL;
		f2 = NULL;

		//
		// Check each triangle/edge permutation for the two that have the
		// same tile surface mesh.  These two triangles will be the ones
		// that we're looking for.
		//

		for (unsigned long i = 0; i < 2 && f1 == NULL; i += 1)
		{
			if (faces[ i + 0 ] == NULL)
				continue;

			for (unsigned long j = 0; j < 2; j += 1)
			{
				if (faces[ j + 2 ] == NULL)
					continue;

//				if ((!IsPointInTriangle( faces[ i + 0 ], Start, GetPoints( ) )) ||
//				    (!IsPointInTriangle( faces[ j + 2 ], End, GetPoints( ) )))
//					continue;

				f1 = faces[ i + 0 ];
				f2 = faces[ j + 2 ];
				t1 = &GetTileSurfaceMesh( f1 );
				t2 = &GetTileSurfaceMesh( f2 );

//				WriteText( "Try again: (%f, %f) and (%f, %f)\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

				if ((t1 == t2) &&
				    (t1 != ExcludeSurfaceMesh))
					break;

				f1 = NULL;
				f2 = NULL;
			}
		}

		if (f1 == NULL)
		{
//			WriteText( "No triangles sharing our edge have the same TSM???\n" );
			return false;
		}
	}

//	WriteText( "%f %f %f %f\n", f1->Centroid2.x, f1->Centroid2.y, f2->Centroid2.x, f2->Centroid2.y );

	*Face1 = f1;
	*Face2 = f2;
	*SurfaceMesh = t1;

	return true;
}