"Find Collision UV" always returns zero for Skeletal Meshes

Hi,

In UE 4.14.0, the blueprint “Find Collision UV” functions doesn’t work properly with Skeletal Meshes. While it works fine for all other objects, it returns X=0.0, Y=0.0 for any place on Epic mannequin.

How to reproduce:

  • Place the mannequin from UE4 starter content
  • In a blueprint, do MultiLineTraceForObjects —> (check for skeletal, if needed) —> Find Collision UV —> Print

http://i.imgur.com/LIfmtKT.jpg

Hi Oskar,

Thank you for the report. I was able to reproduce this behavior and I’ve created JIRA UE-39787. Our developers will be investigating further. Follow that link to monitor the status of the bug and please feel free to vote.

Cheers,

TJ

Oh no I was going to do a cool hit impact effect with this! I have voted. Also it seems like even for static meshes it returns the wrong value as I get both sub 0 and over 1.0 values returned.

Same problem, had good idea with blood on character, and cant do it, cause Find UV not works(

More information by Ryan about his workaround:

The concept works like this:

  1. Have a scenecapture2D follow your skelmesh. Set it to not capture every frame.

  2. After damage, change the material of your skelmesh to use a UV unwrap material. If set to render out the worldposition excluding offsets, it will actually include the skinned positions since its your actual gameplay mesh.

  3. Send event to scenecapture2d to Capture. This will push the current world positions into the UV layout. Then you can project your decal or blood splat /whatever using either a spheremask or a projection matrix. You can accumulate these into the same RT so the decals build up and they should match the skinned positions.

  4. Set your character material back to its default. Since all the above happened in one tick, nothing changes on screen other than how you choose to use the accumulated render target.


Hope this helps.

Also a new solution seems to be on the way. Looking forward to this upcoming plugin:

This is definitely a neat workaround , but I’m concerned about the performance cost (requires two RTs and a scene capture component). It’s also a bit of a pain to set up. There’s a fair few more steps than you have covered in your explanation :wink:

DON’s Mesh painting looks cool, but If it’s just decals I guess that means you can’t get the same kind of vertex deformation stuff that Ryan has going on. It looks like it’d be great for say, a paintball game, but it’s not going to be able to simulate a piece of meat torn out of a body, or a bullet hole with an exit wound.

It’s really a shame that there isn’t any “out of the box” hitmask support in UE4. It was a pretty neat feature back in UE3, and was quite simple to set up and performed quite well.

Looks like the ticket has been marked “broken as intended” , lol.

One major limitation of Ryan’s method I’m noticing is that the UV capture doesn’t seem to work if the mesh has been rotated. Animation is ok, but if you have a character that’s spinning around or flying / swimming it seems to distort the unwrap capture really bad.

For anyone interested, make sure that your scene capture component uses absolute rotation , and not relative. However you also need to make sure to include any relative offsets that have been applied to the mesh. i.e If your mesh is yawed -90 , your attached scene capture should include this as a world rotation offset! This also goes for any scaling or translation your mesh has applied!

Any news on this? I know Ryan has a workaround: http://shaderbits.com/blog/uv-dilation
I thank him so much for his work and this might stay my permanent solution, yet I’d love to see the bug fixed or have a more elegant solution, something like “find nearest UV from world position”.

I am just very curious why this has been marked as “By Design”. Can you explain any further?

Hi Phyro,

This is not supported. Normally traces against skeletal meshes hit the physics asset shapes, which do not have UVs.

I found this way as only solution for making wound system for example - I read whole possible documentation. Now looks like this is no more available. So what alternative for dynamic painting on skeletal meshes?

this is the only one I’m aware of.

Yes, this is only I know about render hits on skeletal meshes. I have assets, I read tutorials but this all not works now and I don’t know other way how to do it, however possible - look DoN plugin. No problem with painting on static meshes, but on skeletal looks like a mission impossible.

It does work, but it requires some additional work to be functional. Ryan’s concept is sound, but his shaderbits demo has a number of issues that you will have to correct. One of the largest of these is that the hitmask painting only works at the world origin (0,0,0). You will need to adapt the materials to deal in local space.

For a run down of this issue see my comment on his video here :

Thank’s @AJQuick. I read your comment before and others too. I tried in 0,0,0 and translate vector to local space, but problem is, all this solutions are based on Find Collision UV what not working more with skeletal meshes. It works perfect with static meshes. I’m sure I miss something. My best result is random position paint on mesh when I get from hit impact normal

I don’t want to drain this thread more, I can start new one and accept your help, or maybe you can join my discord? Discord I’m sure I’m doing stupid error here, I need this feature :smiley:

Ryan’s solution does not use “FindCollisionUV” It unwraps mesh UVs with a scene capture component. You should go back and read the documentation on that method, it’s very clever.

Thank’s, I will. Here a lot steps where I can lost, it’s why I have errors.

Hi guys i think this will help. I made a function based on FindCollisionUV and did some changes on it.

    struct FSortVertexByDistance
    {
    	FSortVertexByDistance(const FVector& InSourceLocation)
    		: SourceLocation(InSourceLocation)
    	{
    
    	}
    
    	FVector SourceLocation;
    
    	bool operator()(const FSoftSkinVertex A, const FSoftSkinVertex B) const
    	{
    		float DistanceA = FVector::DistSquared(SourceLocation, A.Position);
    		float DistanceB = FVector::DistSquared(SourceLocation, B.Position);
    
    		return DistanceA < DistanceB;
    	}
    };
    
    void UYourGameplayLibrary::FindCollisionUVOnSkeletalMesh(const struct FHitResult& Hit,  FVector2D& UV)
    {
    	UPrimitiveComponent* HitPrimComp = Hit.Component.Get();
    	USkeletalMeshComponent* SkelMeshComp = Cast<USkeletalMeshComponent>(HitPrimComp);
    	USkeletalMesh* SkelMesh = SkelMeshComp->SkeletalMesh;
    	FSkeletalMeshModel* SkelModel = SkelMesh->GetImportedModel();
    	FSkeletalMeshLODModel* LODModel = &SkelModel->LODModels[0];
    
    	const FVector LocalHitPos = HitPrimComp->GetComponentToWorld().InverseTransformPosition(Hit.Location);
    
    	TArray<FSoftSkinVertex> Vertices;
    	LODModel->GetVertices(Vertices);
    
    	// Sort Shortest Vertex from LocalHitPos
    	Vertices.Sort(FSortVertexByDistance(LocalHitPos));
    
    
    	// Get three vertex for computing barycentric coords
    	FVector Pos0 = Vertices[0].Position;
    	FVector Pos1 = Vertices[3].Position;
    	FVector Pos2 = Vertices[6].Position;
    		
    	FVector2D UV0 = Vertices[0].UVs[0];
    	FVector2D UV1 = Vertices[3].UVs[0];
    	FVector2D UV2 = Vertices[6].UVs[0];
    
    	// Transform hit location from world to local space.
    	// Find barycentric coords
    	FVector BaryCoords = FMath::ComputeBaryCentric2D(LocalHitPos, Pos0, Pos1, Pos2);
    	// Use to blend UVs
    	UV = (BaryCoords.X * UV0) + (BaryCoords.Y * UV1) + (BaryCoords.Z * UV2);
    }