/**
 * Extract the material names from the Apex Render Mesh contained within an Apex Destructible Asset.
 * @param ImportData - SkeletalMesh import data into which we are extracting information
 * @param ApexDestructibleAsset - the Apex Destructible Asset
 */
static void ImportMaterialsForSkelMesh(FSkeletalMeshImportData &ImportData, const NxDestructibleAsset& ApexDestructibleAsset)
{
	physx::PxU32 SubmeshCount = 0;

	// Get the submesh count from the Destructible Asset's Render Mesh
	const physx::NxRenderMeshAsset* ApexRenderMesh = ApexDestructibleAsset.getRenderMeshAsset();
	if (ApexRenderMesh != NULL)
	{
		SubmeshCount = ApexRenderMesh->getSubmeshCount();
	}

	if( SubmeshCount == 0 )
	{
		// No material info, create a default material slot
		++SubmeshCount;
		UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("No material associated with skeletal mesh - using default"));
	}
	else
	{
		UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("Using default materials for material slot"));
	}

	// Create material slots
	UMaterial* DefaultMaterial = UMaterial::GetDefaultMaterial(MD_Surface);
	if (DefaultMaterial)
	{
		for (uint32 MatIndex = 0; MatIndex < SubmeshCount; MatIndex++)
		{
			ImportData.Materials.Add( VMaterial() );

			ImportData.Materials.Last().Material = DefaultMaterial;
			ImportData.Materials.Last().MaterialImportName = DefaultMaterial->GetName();
		}
	}
}
/**
 * Create the bones needed to hold the transforms for the destructible chunks associated with an Apex Destructible Asset.
 * @param ImportData - SkeletalMesh import data into which we are extracting information
 * @param ApexDestructibleAsset - the Apex Destructible Asset
 */
static void CreateBones(FSkeletalMeshImportData &ImportData, const NxDestructibleAsset& ApexDestructibleAsset)
{
	// Just need to create ApexDestructibleAsset.getChunkCount() bones, all with identity transform poses
	const uint32 ChunkCount = ApexDestructibleAsset.getChunkCount();
	if( ChunkCount == 0 )
	{
		UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("%s has no chunks"), ANSI_TO_TCHAR(ApexDestructibleAsset.getName()) );
		return;
	}

	const uint32 BoneCount = ChunkCount + 1;	// Adding one more bone for the root bone, required by the skeletal mesh

	// Format for bone names
	uint32 Q = ChunkCount-1;
	int32 MaxNumberWidth = 1;
	while ((Q /= 10) != 0)
	{
		++MaxNumberWidth;
	}

	// Turn parts into bones
	for (uint32 BoneIndex=0; BoneIndex<BoneCount; ++BoneIndex)
	{
		ImportData.RefBonesBinary.Add( VBone() );
		// Set bone
		VBone& Bone = ImportData.RefBonesBinary[BoneIndex];
		if (BoneIndex == 0)
		{
			// Bone 0 is the required root bone
			Bone.Name = TEXT("Root");
			Bone.NumChildren = ChunkCount;
			Bone.ParentIndex = INDEX_NONE;
		}
		else
		{
			// The rest are the parts
			Bone.Name = FString::Printf( TEXT("Part%0*d"), MaxNumberWidth, BoneIndex-1);
			Bone.NumChildren = 0;
			// Creates a simple "flat" hierarchy
			Bone.ParentIndex = 0;
		}

		// Set transform to identity
		VJointPos& JointMatrix = Bone.BonePos;
		JointMatrix.Orientation = FQuat(0.0f,0.0f,0.0f,1.0f);
		JointMatrix.Position = FVector(0.0f,0.0f,0.0f);
		JointMatrix.Length = 1.0f;
		JointMatrix.XSize = 100.0f;
		JointMatrix.YSize = 100.0f;
		JointMatrix.ZSize = 100.0f;
	}
}
void FDestructibleMeshEditorViewportClient::Draw( const FSceneView* View,FPrimitiveDrawInterface* PDI )
{
	FEditorViewportClient::Draw(View, PDI);

#if WITH_APEX
	const bool DrawChunkMarker = true;

	UDestructibleComponent* Comp = PreviewDestructibleComp.Get();
	
	if (Comp)
	{
		if (Comp->DestructibleMesh != NULL && Comp->DestructibleMesh->FractureSettings != NULL)
		{
			if (Comp->DestructibleMesh->ApexDestructibleAsset != NULL)
			{
				NxDestructibleAsset* Asset = Comp->DestructibleMesh->ApexDestructibleAsset;
				const NxRenderMeshAsset* RenderMesh = Asset->getRenderMeshAsset();

				for (uint32 i=0; i < Asset->getChunkCount(); ++i)
				{
					int32 PartIdx = Asset->getPartIndex(i);
					int32 BoneIdx = i+1;

					if ( SelectedChunkIndices.Contains(i) )
					{
						PxBounds3 PBounds = RenderMesh->getBounds(PartIdx);

						FVector Center = P2UVector(PBounds.getCenter()) + Comp->GetBoneLocation(Comp->GetBoneName(BoneIdx));
						FVector Extent = P2UVector(PBounds.getExtents());

						FBox Bounds(Center - Extent, Center + Extent);
						DrawWireBox(PDI, Bounds, FColor::Blue, SDPG_World);
					}
				}
			}
		}
	}
#endif // WITH_APEX
}
bool SetApexDestructibleAsset(UDestructibleMesh& DestructibleMesh, NxDestructibleAsset& ApexDestructibleAsset, FSkeletalMeshImportData* OutData, EDestructibleImportOptions::Type Options)
{
	DestructibleMesh.PreEditChange(NULL);

	ExistingDestMeshData * ExistDestMeshDataPtr = SaveExistingDestMeshData(&DestructibleMesh);
	
	// The asset is going away, which will destroy any actors created from it.  We must destroy the physics state of any destructible mesh components before we release the asset.
	for(TObjectIterator<UDestructibleComponent> It; It; ++It)
	{
		UDestructibleComponent* DestructibleComponent = *It;
		if(DestructibleComponent->SkeletalMesh == &DestructibleMesh && DestructibleComponent->IsPhysicsStateCreated())
		{
			DestructibleComponent->DestroyPhysicsState();
		}
	}

	// Release old NxDestructibleAsset if it exists
	if (DestructibleMesh.ApexDestructibleAsset != NULL && DestructibleMesh.ApexDestructibleAsset != &ApexDestructibleAsset)
	{
		GPhysCommandHandler->DeferredRelease(DestructibleMesh.ApexDestructibleAsset);
	}

	// BRGTODO - need to remove the render data from the ApexDestructibleAsset, no longer need it
	// Removing const cast ... we'll have to make it non-const anyway when we modify it
	DestructibleMesh.ApexDestructibleAsset = &ApexDestructibleAsset;

	if ( !(Options&EDestructibleImportOptions::PreserveSettings) )
	{
		// Resize the depth parameters array to the appropriate size
		DestructibleMesh.DefaultDestructibleParameters.DepthParameters.Init(FDestructibleDepthParameters(), ApexDestructibleAsset.getDepthCount());

		// Resize the fracture effects array to the appropriate size
		DestructibleMesh.FractureEffects.AddZeroed(ApexDestructibleAsset.getDepthCount());

		// Load the UnrealEd-editable parameters from the destructible asset
		DestructibleMesh.LoadDefaultDestructibleParametersFromApexAsset();
	}
		
	// Create body setup for the destructible mesh
	DestructibleMesh.CreateBodySetup();

#if 0	// BRGTODO
	// warning for missing smoothing group info
	CheckSmoothingInfo(FbxMesh);
#endif
	
	FSkeletalMeshImportData TempData;
	// Fill with data from buffer
	FSkeletalMeshImportData* SkelMeshImportDataPtr = &TempData;
	if( OutData )
	{
		SkelMeshImportDataPtr = OutData;
	}
	
	// Get all material names here
	ImportMaterialsForSkelMesh(*SkelMeshImportDataPtr, ApexDestructibleAsset);

	// Import animation hierarchy, although this is trivial for an Apex Destructible Asset
	CreateBones(*SkelMeshImportDataPtr, ApexDestructibleAsset);

	// Import graphics data
	bool bHaveNormals, bHaveTangents;
	if (!FillSkelMeshImporterFromApexDestructibleAsset(*SkelMeshImportDataPtr, ApexDestructibleAsset, bHaveNormals, bHaveTangents))
	{
		return false;
	}

#if 0	// BRGTODO - what is this?
	if( SkelMeshImportDataPtr->Materials.Num() == FbxMatList.Num() )
	{
		// reorder material according to "SKinXX" in material name
		SetMaterialSkinXXOrder(*SkelMeshImportDataPtr, FbxMatList );
	}
#endif

#if 0	// BRGTODO - what is this?
	if( ImportOptions->bSplitNonMatchingTriangles )
	{
		DoUnSmoothVerts(*SkelMeshImportDataPtr);
	}
#endif

	// process materials from import data
	ProcessImportMeshMaterials( DestructibleMesh.Materials,*SkelMeshImportDataPtr );
	
	// process reference skeleton from import data
	int32 SkeletalDepth=0;
	if(!ProcessImportMeshSkeleton(DestructibleMesh.RefSkeleton, SkeletalDepth, *SkelMeshImportDataPtr))
	{
		return false;
	}
	UE_LOG(LogApexDestructibleAssetImport, Warning, TEXT("Bones digested - %i  Depth of hierarchy - %i"), DestructibleMesh.RefSkeleton.GetNum(), SkeletalDepth);

	// process bone influences from import data
	ProcessImportMeshInfluences(*SkelMeshImportDataPtr);

	FSkeletalMeshResource& DestructibleMeshResource = *DestructibleMesh.GetImportedResource();
	check(DestructibleMeshResource.LODModels.Num() == 0);
	DestructibleMeshResource.LODModels.Empty();
	new(DestructibleMeshResource.LODModels)FStaticLODModel();

	DestructibleMesh.LODInfo.Empty();
	DestructibleMesh.LODInfo.AddZeroed();
	DestructibleMesh.LODInfo[0].LODHysteresis = 0.02f;

	// Create initial bounding box based on expanded version of reference pose for meshes without physics assets. Can be overridden by artist.
	FBox BoundingBox(SkelMeshImportDataPtr->Points.GetData(), SkelMeshImportDataPtr->Points.Num());
	DestructibleMesh.Bounds= FBoxSphereBounds(BoundingBox);

	// Store whether or not this mesh has vertex colors
	DestructibleMesh.bHasVertexColors = SkelMeshImportDataPtr->bHasVertexColors;

	FStaticLODModel& LODModel = DestructibleMeshResource.LODModels[0];
	
	// Pass the number of texture coordinate sets to the LODModel.  Ensure there is at least one UV coord
	LODModel.NumTexCoords = FMath::Max<uint32>(1,SkelMeshImportDataPtr->NumTexCoords);
//	if( bCreateRenderData )	// We always create render data
	{
		// copy vertex data needed to generate skinning streams for LOD
		TArray<FVector> LODPoints;
		TArray<FMeshWedge> LODWedges;
		TArray<FMeshFace> LODFaces;
		TArray<FVertInfluence> LODInfluences;
		TArray<int32> LODPointToRawMap;
		SkelMeshImportDataPtr->CopyLODImportData(LODPoints,LODWedges,LODFaces,LODInfluences,LODPointToRawMap);

		IMeshUtilities& MeshUtilities = FModuleManager::Get().LoadModuleChecked<IMeshUtilities>("MeshUtilities");

		// Create actual rendering data.
		if (!MeshUtilities.BuildSkeletalMesh(DestructibleMeshResource.LODModels[0], DestructibleMesh.RefSkeleton, LODInfluences,LODWedges,LODFaces,LODPoints,LODPointToRawMap,false,!bHaveNormals,!bHaveTangents))
		{
			DestructibleMesh.MarkPendingKill();
			return false;
		}

		// Presize the per-section shadow casting array with the number of sections in the imported LOD.
		const int32 NumSections = LODModel.Sections.Num();

		for ( int32 SectionIndex = 0 ; SectionIndex < NumSections ; ++SectionIndex )
		{
			DestructibleMesh.LODInfo[0].TriangleSortSettings.AddZeroed();
		}

		if (ExistDestMeshDataPtr)
		{
			RestoreExistingDestMeshData(ExistDestMeshDataPtr, &DestructibleMesh);
			delete ExistDestMeshDataPtr;
			ExistDestMeshDataPtr = NULL;
		}

		DestructibleMesh.CalculateInvRefMatrices();
		DestructibleMesh.PostEditChange();
		DestructibleMesh.MarkPackageDirty();

#if 0 // BRGTODO : Check, we don't need this, do we?
		// We have to go and fix any AnimSetMeshLinkup objects that refer to this skeletal mesh, as the reference skeleton has changed.
		for(TObjectIterator<UAnimSet> It;It;++It)
		{
			UAnimSet* AnimSet = *It;

			// Get DestructibleMesh path name
			FName SkelMeshName = FName( *DestructibleMesh.GetPathName() );

			// See if we have already cached this Skeletal Mesh.
			const int32* IndexPtr = AnimSet->SkelMesh2LinkupCache.Find( SkelMeshName );

			if( IndexPtr )
			{
				AnimSet->LinkupCache( *IndexPtr ).BuildLinkup( &DestructibleMesh, AnimSet );
			}
		}
#endif

		// Now iterate over all skeletal mesh components re-initialising them.
		for(TObjectIterator<UDestructibleComponent> It; It; ++It)
		{
			UDestructibleComponent* DestructibleComponent = *It;
			if(DestructibleComponent->SkeletalMesh == &DestructibleMesh)
			{
				FComponentReregisterContext ReregisterContext(DestructibleComponent);
			}
		}
	}

#if INVERT_Y_AND_V
	// Apply transformation for Y inversion
	const physx::PxMat44 MirrorY = physx::PxMat44(physx::PxVec4(1.0f, -1.0f, 1.0f, 1.0f));
#if !USE_TEMPORARY_TRANSFORMATION_FUNCTION
	ApexDestructibleAsset.applyTransformation(MirrorY, 1.0f);
#else
	ApplyTransformationToApexDestructibleAsset( ApexDestructibleAsset, MirrorY );
#endif
#endif

	return true;
}
/**
 * Fill an FSkeletalMeshImportData with data from an APEX Destructible Asset.
 *
 * @param ImportData - SkeletalMesh import data into which we are extracting information
 * @param ApexDestructibleAsset - the Apex Destructible Asset
 * @param bHaveAllNormals - if the function is successful, this value is true iff every submesh has a normal channel
 * @param bHaveAllTangents - if the function is successful, this value is true iff every submesh has a tangent channel
 *
 * @return Boolean true iff the operation is successful
 */
static bool FillSkelMeshImporterFromApexDestructibleAsset(FSkeletalMeshImportData& ImportData, const NxDestructibleAsset& ApexDestructibleAsset, bool& bHaveAllNormals, bool& bHaveAllTangents)
{
	// The APEX Destructible Asset contains an APEX Render Mesh Asset, get a pointer to this
	const physx::NxRenderMeshAsset* ApexRenderMesh = ApexDestructibleAsset.getRenderMeshAsset();
	if (ApexRenderMesh == NULL)
	{
		return false;
	}

	if (ApexDestructibleAsset.getChunkCount() != ApexRenderMesh->getPartCount())
	{
		UE_LOG(LogApexDestructibleAssetImport, Warning,TEXT("Chunk count does not match part count.  APEX Destructible Asset with chunk instancing not yet supported."));
		return false;
	}

	// Apex Render Mesh uses triangle lists only, currently.  No need to triangulate.

	// Assume there are no vertex colors
	ImportData.bHasVertexColors = false;

	// Different submeshes can have different UV counts.  Get the max.
	uint32 UniqueUVCount = 0;

	// Count vertices and triangles
	uint32 VertexCount = 0;
	uint32 TriangleCount = 0;

	for (uint32 SubmeshIndex = 0; SubmeshIndex < ApexRenderMesh->getSubmeshCount(); ++SubmeshIndex)
	{
		const NxRenderSubmesh& Submesh = ApexRenderMesh->getSubmesh(SubmeshIndex);
		const NxVertexBuffer& VB = Submesh.getVertexBuffer();
		const NxVertexFormat& VBFormat = VB.getFormat();

		// Count UV channels in this VB
		uint32 UVNum;
		for (UVNum = 0; UVNum < NxVertexFormat::MAX_UV_COUNT; ++UVNum)
		{
			const NxVertexFormat::BufferID BufferID = VBFormat.getSemanticID((NxRenderVertexSemantic::Enum)(NxRenderVertexSemantic::TEXCOORD0 + UVNum));
			if (VBFormat.getBufferIndexFromID(BufferID) < 0)
			{
				break;
			}
		}
		UniqueUVCount = FMath::Max<uint32>( UniqueUVCount, UVNum );

		// See if this VB has a color channel
		const NxVertexFormat::BufferID BufferID = VBFormat.getSemanticID(NxRenderVertexSemantic::COLOR);
		if (VBFormat.getBufferIndexFromID(BufferID) >= 0)
		{
			ImportData.bHasVertexColors = true;
		}

		// Count vertices
		VertexCount += VB.getVertexCount();

		// Count triangles
		uint32 IndexCount = 0;
		for (uint32 PartIndex = 0; PartIndex < ApexRenderMesh->getPartCount(); ++PartIndex)
		{
			IndexCount += Submesh.getIndexCount(PartIndex);
		}
		check(IndexCount%3 == 0);
		TriangleCount += IndexCount/3;
	}

	// One UV set is required but only import up to MAX_TEXCOORDS number of uv layers
	ImportData.NumTexCoords = FMath::Clamp<uint32>(UniqueUVCount, 1, MAX_TEXCOORDS);

	// Expand buffers in ImportData:
	ImportData.Points.AddUninitialized(VertexCount);
	ImportData.Influences.AddUninitialized(VertexCount);

	ImportData.Wedges.AddUninitialized(3*TriangleCount);
	uint32 WedgeIndex = 0;

	ImportData.Faces.AddUninitialized(TriangleCount);
	uint32 TriangleIndex = 0;

	uint32 VertexIndexBase = 0;

	// True until proven otherwise
	bHaveAllNormals = true;
	bHaveAllTangents = true;

	// APEX render meshes are organized by submesh (render elements)
	// Looping through submeshes first, can be done either way
	for (uint32 SubmeshIndex = 0; SubmeshIndex < ApexRenderMesh->getSubmeshCount(); ++SubmeshIndex)
	{
		// Submesh data
		const NxRenderSubmesh& Submesh = ApexRenderMesh->getSubmesh(SubmeshIndex);
		const NxVertexBuffer& VB = Submesh.getVertexBuffer();
		const NxVertexFormat& VBFormat = VB.getFormat();
		const physx::PxU32 SubmeshVertexCount = VB.getVertexCount();

		// Get VB data semantic indices:

		// Positions
		const PxI32 PositionBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID(NxRenderVertexSemantic::POSITION));
		if (!VB.getBufferData(&ImportData.Points[VertexIndexBase], physx::NxRenderDataFormat::FLOAT3, sizeof(FVector), PositionBufferIndex, 0, SubmeshVertexCount))
		{
			return false;	// Need a position buffer!
		}

#if INVERT_Y_AND_V
		for (uint32 VertexNum = 0; VertexNum < SubmeshVertexCount; ++VertexNum)
		{
			ImportData.Points[VertexIndexBase + VertexNum].Y *= -1.0f;
		}
#endif

		// Normals
		const PxI32 NormalBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID(NxRenderVertexSemantic::NORMAL));
		TArray<FVector> Normals;
		Normals.AddUninitialized(SubmeshVertexCount);
		const bool bHaveNormals = VB.getBufferData(Normals.GetData(), physx::NxRenderDataFormat::FLOAT3, sizeof(FVector), NormalBufferIndex, 0, SubmeshVertexCount);
		if (!bHaveNormals)
		{
			FMemory::Memset(Normals.GetData(), 0, SubmeshVertexCount*sizeof(FVector));	// Fill with zeros
		}

		// Tangents
		const PxI32 TangentBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID(NxRenderVertexSemantic::TANGENT));
		TArray<FVector> Tangents;
		Tangents.AddUninitialized(SubmeshVertexCount);
		const bool bHaveTangents = VB.getBufferData(Tangents.GetData(), physx::NxRenderDataFormat::FLOAT3, sizeof(FVector), TangentBufferIndex, 0, SubmeshVertexCount);
		if (!bHaveTangents)
		{
			FMemory::Memset(Tangents.GetData(), 0, SubmeshVertexCount*sizeof(FVector));	// Fill with zeros
		}

		// Update bHaveAllNormals and bHaveAllTangents
		bHaveAllNormals = bHaveAllNormals && bHaveNormals;
		bHaveAllTangents = bHaveAllTangents && bHaveTangents;

		// Binormomals
		const PxI32 BinormalBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID(NxRenderVertexSemantic::BINORMAL));
		TArray<FVector> Binormals;
		Binormals.AddUninitialized(SubmeshVertexCount);
		bool bHaveBinormals = VB.getBufferData(Binormals.GetData(), physx::NxRenderDataFormat::FLOAT3, sizeof(FVector), BinormalBufferIndex, 0, SubmeshVertexCount);
		if (!bHaveBinormals)
		{
			bHaveBinormals = bHaveNormals && bHaveTangents;
			for (uint32 i = 0; i < SubmeshVertexCount; ++i)
			{
				Binormals[i] = Normals[i]^Tangents[i];	// Build from normals and tangents.  If one of these doesn't exist we'll get (0,0,0)'s
			}
		}

		// Colors
		const PxI32 ColorBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID(NxRenderVertexSemantic::COLOR));
		TArray<FColor> Colors;
		Colors.AddUninitialized(SubmeshVertexCount);
		const bool bHaveColors = VB.getBufferData(Colors.GetData(), physx::NxRenderDataFormat::B8G8R8A8, sizeof(FColor), ColorBufferIndex, 0, SubmeshVertexCount);
		if (!bHaveColors)
		{
			FMemory::Memset(Colors.GetData(), 0xFF, SubmeshVertexCount*sizeof(FColor));	// Fill with 0xFF
		}

		// UVs
		TArray<FVector2D> UVs[NxVertexFormat::MAX_UV_COUNT];
		for (uint32 UVNum = 0; UVNum < ImportData.NumTexCoords; ++UVNum)
		{
			const PxI32 UVBufferIndex = VBFormat.getBufferIndexFromID(VBFormat.getSemanticID((NxRenderVertexSemantic::Enum)(NxRenderVertexSemantic::TEXCOORD0 + UVNum)));
			UVs[UVNum].AddUninitialized(SubmeshVertexCount);
			if (!VB.getBufferData(&UVs[UVNum][0].X, physx::NxRenderDataFormat::FLOAT2, sizeof(FVector2D), UVBufferIndex, 0, SubmeshVertexCount))
			{
				FMemory::Memset(&UVs[UVNum][0].X, 0, SubmeshVertexCount*sizeof(FVector2D));	// Fill with zeros
			}
		}

		// Bone indices will not be imported - they're implicitly the PartIndex

		// Each submesh is partitioned into parts.  Currently we're assuming a 1-1 correspondence between chunks and parts,
		// which means that instanced chunks are not supported.  However, we will not assume that the chunk and part ordering is the same.
		// Therefore, instead of looping through parts, we loop through chunks here, and get the part index.
		for (uint32 ChunkIndex = 0; ChunkIndex < ApexDestructibleAsset.getChunkCount(); ++ChunkIndex)
		{
			const physx::PxU32 PartIndex = ApexDestructibleAsset.getPartIndex(ChunkIndex);
			const physx::PxU32* PartIndexBuffer = Submesh.getIndexBuffer(PartIndex);
			const physx::PxU32* PartIndexBufferStop = PartIndexBuffer + Submesh.getIndexCount(PartIndex);
			while (PartIndexBuffer < PartIndexBufferStop)
			{
				physx::PxU32 SubmeshVertexIndex[3];
#if !INVERT_Y_AND_V
				SubmeshVertexIndex[2] = *PartIndexBuffer++;
				SubmeshVertexIndex[1] = *PartIndexBuffer++;
				SubmeshVertexIndex[0] = *PartIndexBuffer++;
#else
				SubmeshVertexIndex[0] = *PartIndexBuffer++;
				SubmeshVertexIndex[1] = *PartIndexBuffer++;
				SubmeshVertexIndex[2] = *PartIndexBuffer++;
#endif

				// Fill triangle
				VTriangle& Triangle = ImportData.Faces[TriangleIndex++];

				// set the face smoothing by default. It could be any number, but not zero
				Triangle.SmoothingGroups = 255; 

				// Material index
				Triangle.MatIndex = SubmeshIndex;
				Triangle.AuxMatIndex = 0;

				// Per-vertex
				for (uint32 V = 0; V < 3; ++V)
				{
					// Tangent basis
					Triangle.TangentX[V] = Tangents[SubmeshVertexIndex[V]];
					Triangle.TangentY[V] = Binormals[SubmeshVertexIndex[V]];
					Triangle.TangentZ[V] = Normals[SubmeshVertexIndex[V]];
#if INVERT_Y_AND_V
					Triangle.TangentX[V].Y *= -1.0f;
					Triangle.TangentY[V].Y *= -1.0f;
					Triangle.TangentZ[V].Y *= -1.0f;
#endif

					// Wedges
					Triangle.WedgeIndex[V] = WedgeIndex;
					VVertex& Wedge = ImportData.Wedges[WedgeIndex++];
					Wedge.VertexIndex = VertexIndexBase + SubmeshVertexIndex[V];
					Wedge.MatIndex = Triangle.MatIndex;
					Wedge.Color = Colors[SubmeshVertexIndex[V]];
					Wedge.Reserved = 0;
					for (uint32 UVNum = 0; UVNum < ImportData.NumTexCoords; ++UVNum)
					{
						const FVector2D& UV = UVs[UVNum][SubmeshVertexIndex[V]];
#if !INVERT_Y_AND_V
						Wedge.UVs[UVNum] = UV;
#else
						Wedge.UVs[UVNum] = FVector2D(UV.X, 1.0f-UV.Y);
#endif
					}
				}
			}

			// Bone influences
			const physx::PxU32 PartVertexStart = Submesh.getFirstVertexIndex(PartIndex);
			const physx::PxU32 PartVertexStop = PartVertexStart + Submesh.getVertexCount(PartIndex);
			for (uint32 PartVertexIndex = PartVertexStart; PartVertexIndex < PartVertexStop; ++PartVertexIndex)
			{
				const physx::PxU32 VertexIndex = VertexIndexBase + PartVertexIndex;
				// Note, by using ChunkIndex instead of PartInedx we are effectively setting PartIndex = ChunkIndex, which is OK since we won't be supporting instancing with the SkeletalMesh.
				ImportData.Influences[VertexIndex].BoneIndex = ChunkIndex + 1;	// Adding 1, since the 0 bone will have no geometry from the Apex Destructible Asset.
				ImportData.Influences[VertexIndex].Weight = 1.0;
				ImportData.Influences[VertexIndex].VertexIndex = VertexIndex;
			}
		}

		VertexIndexBase += SubmeshVertexCount;
	}

	// Create mapping from import to raw- @TODO trivial at the moment, do we need this info for destructibles?
	ImportData.PointToRawMap.AddUninitialized(ImportData.Points.Num());
	for(int32 PointIdx=0; PointIdx<ImportData.PointToRawMap.Num(); PointIdx++)
	{
		ImportData.PointToRawMap[PointIdx] = PointIdx;
	}

	return true;
}
void FDestructibleMeshEditorViewportClient::ProcessClick( class FSceneView& View, class HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY )
{
#if WITH_APEX
	bool bKeepSelection = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
	bool bSelectionChanged = false;

	if (Key == EKeys::LeftMouseButton && Event == EInputEvent::IE_Released)
	{
		UDestructibleComponent* Comp = PreviewDestructibleComp.Get();
		NxDestructibleAsset* Asset = Comp->DestructibleMesh->ApexDestructibleAsset;
		const NxRenderMeshAsset* RenderMesh = Asset->getRenderMeshAsset();

		FVector2D ScreenPos(HitX, HitY);
		FVector ClickOrigin, ViewDir;
		View.DeprojectFVector2D(ScreenPos, ClickOrigin, ViewDir);

		float NearestHitDistance = FLT_MAX;
		int32 ClickedChunk = -1;

		for (uint32 i=0; i < Asset->getChunkCount(); ++i)
		{
			int32 PartIdx = Asset->getPartIndex(i);
			int32 BoneIdx = i+1;
			
			if (!Comp->IsBoneHidden(BoneIdx))
			{
				PxBounds3 PBounds = RenderMesh->getBounds(PartIdx);

				FVector Center = P2UVector(PBounds.getCenter()) + Comp->GetBoneLocation(Comp->GetBoneName(BoneIdx));
				FVector Extent = P2UVector(PBounds.getExtents());

				FBox Bounds(Center - Extent, Center + Extent);

				FVector HitLoc, HitNorm;
				float HitTime;
				
				if (FMath::LineExtentBoxIntersection(Bounds, ClickOrigin, ClickOrigin + ViewDir * 1000.0f, FVector(0,0,0), HitLoc, HitNorm, HitTime))
				{
					float dist = (HitLoc - ClickOrigin).SizeSquared();

					if (dist < NearestHitDistance)
					{
						NearestHitDistance = dist;
						ClickedChunk = i;
					}
				}
			}
		}

		if (ClickedChunk >= 0)
		{
			int32 Idx = SelectedChunkIndices.Find(ClickedChunk);
		
			if (Idx < 0)
			{
				if (!bKeepSelection) { SelectedChunkIndices.Empty(); }

				SelectedChunkIndices.Add(ClickedChunk);
				bSelectionChanged = true;
			}
			else
			{
				SelectedChunkIndices.RemoveAt(Idx);
				bSelectionChanged = true;
			}
		}
		else if (!bKeepSelection)
		{
			SelectedChunkIndices.Empty();
 			bSelectionChanged = true;
		}
	}

	if (bSelectionChanged)
	{
		UpdateChunkSelection(SelectedChunkIndices);
	}
#endif // WITH_APEX
}