[=dmacesic;9953]
I thought I had published that yesterday, did you do anything to make it public?
[/]
To clarify:
“His tutorial is now up and available here!”
I was just excitedly letting people know you already posted it
[=dmacesic;9953]
I thought I had published that yesterday, did you do anything to make it public?
[/]
To clarify:
“His tutorial is now up and available here!”
I was just excitedly letting people know you already posted it
Hey guys, just wanted to share what I’ve been tinkering around with on this stuff to be able to set UV’s for the custom meshes:
First, I split off the FCustomMeshTriangle struct into these two structs:
USTRUCT(BlueprintType)
struct FCustomMeshTriangleVertex
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, Category = Triangle)
FVector Position;
UPROPERTY(EditAnywhere, Category = Triangle)
float U;
UPROPERTY(EditAnywhere, Category = Triangle)
float V;
};
USTRUCT(BlueprintType)
struct FCustomMeshTriangle
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, Category=Triangle)
FCustomMeshTriangleVertex Vertex0;
UPROPERTY(EditAnywhere, Category=Triangle)
FCustomMeshTriangleVertex Vertex1;
UPROPERTY(EditAnywhere, Category=Triangle)
FCustomMeshTriangleVertex Vertex2;
};
Then, the constructor for the FCustomMeshSceneProxy class would change to this:
FCustomMeshSceneProxy(UCustomMeshComponent* Component)
: FPrimitiveSceneProxy(Component)
, MaterialRelevance(Component->GetMaterialRelevance())
{
const FColor VertexColor(255,255,255);
// Add each triangle to the vertex/index buffer
for(int TriIdx=0; TriIdx<Component->CustomMeshTris.Num(); TriIdx++)
{
FCustomMeshTriangle& Tri = Component->CustomMeshTris[TriIdx];
const FVector Edge01 = (Tri.Vertex1.Position - Tri.Vertex0.Position);
const FVector Edge02 = (Tri.Vertex2.Position - Tri.Vertex0.Position);
const FVector TangentX = Edge01.SafeNormal();
const FVector TangentZ = (Edge02 ^ Edge01).SafeNormal();
const FVector TangentY = (TangentX ^ TangentZ).SafeNormal();
FDynamicMeshVertex Vert0;
Vert0.Position = Tri.Vertex0.Position;
Vert0.Color = VertexColor;
Vert0.SetTangents(TangentX, TangentY, TangentZ);
Vert0.TextureCoordinate.Set(Tri.Vertex0.U, Tri.Vertex0.V);
int32 VIndex = VertexBuffer.Vertices.Add(Vert0);
IndexBuffer.Indices.Add(VIndex);
FDynamicMeshVertex Vert1;
Vert1.Position = Tri.Vertex1.Position;
Vert1.Color = VertexColor;
Vert1.SetTangents(TangentX, TangentY, TangentZ);
Vert1.TextureCoordinate.Set(Tri.Vertex1.U, Tri.Vertex1.V);
VIndex = VertexBuffer.Vertices.Add(Vert1);
IndexBuffer.Indices.Add(VIndex);
FDynamicMeshVertex Vert2;
Vert2.Position = Tri.Vertex2.Position;
Vert2.Color = VertexColor;
Vert2.SetTangents(TangentX, TangentY, TangentZ);
Vert2.TextureCoordinate.Set(Tri.Vertex2.U, Tri.Vertex2.V);
VIndex = VertexBuffer.Vertices.Add(Vert2);
IndexBuffer.Indices.Add(VIndex);
}
// Init vertex factory
VertexFactory.Init(&VertexBuffer);
// Enqueue initialization of render resource
BeginInitResource(&VertexBuffer);
BeginInitResource(&IndexBuffer);
BeginInitResource(&VertexFactory);
// Grab material
Material = Component->GetMaterial(0);
if(Material == NULL)
{
Material = UMaterial::GetDefaultMaterial(MD_Surface);
}
}
Lastly, to test this out I added a couple functions:
bool UCustomMeshComponent::ClearCustomMeshTriangles()
{
CustomMeshTris.Empty();
// Need to recreate scene proxy to send it over
MarkRenderStateDirty();
return true;
}
bool UCustomMeshComponent::AddCustomBox(const float& Size, const FVector& Position)
{
// make vertex positions
FVector p0 = FVector(Position.X, Position.Y, Position.Z);
FVector p1 = FVector(Position.X, Position.Y, Position.Z + Size);
FVector p2 = FVector(Position.X + Size, Position.Y, Position.Z + Size);
FVector p3 = FVector(Position.X + Size, Position.Y, Position.Z);
FVector p4 = FVector(Position.X + Size, Position.Y + Size, Position.Z);
FVector p5 = FVector(Position.X + Size, Position.Y + Size, Position.Z + Size);
FVector p6 = FVector(Position.X, Position.Y + Size, Position.Z + Size);
FVector p7 = FVector(Position.X, Position.Y + Size, Position.Z);
FCustomMeshTriangleVertex v0;
FCustomMeshTriangleVertex v1;
FCustomMeshTriangleVertex v2;
FCustomMeshTriangleVertex v3;
v0.U = 0; v0.V = 0;
v1.U = 0; v1.V = .5;
v2.U = .5; v2.V = .5;
v3.U = .5; v3.V = 0;
FCustomMeshTriangle t1;
FCustomMeshTriangle t2;
// front face
v0.Position = p0;
v1.Position = p1;
v2.Position = p2;
v3.Position = p3;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
//back face
v0.Position = p4;
v1.Position = p5;
v2.Position = p6;
v3.Position = p7;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
// left face
v0.Position = p7;
v1.Position = p6;
v2.Position = p1;
v3.Position = p0;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
// right face
v0.Position = p3;
v1.Position = p2;
v2.Position = p5;
v3.Position = p4;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
// top face
v0.Position = p1;
v1.Position = p6;
v2.Position = p5;
v3.Position = p2;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
// bottom face
v0.Position = p3;
v1.Position = p4;
v2.Position = p7;
v3.Position = p0;
t1.Vertex0 = v0;
t1.Vertex1 = v1;
t1.Vertex2 = v2;
t2.Vertex0 = v0;
t2.Vertex1 = v2;
t2.Vertex2 = v3;
CustomMeshTris.Add(t1);
CustomMeshTris.Add(t2);
MarkRenderStateDirty();
return true;
}
With all that, and using the AddCustomBox function, applying materials to the custom mesh components should now look something like this:
and then I went a little crazy with for loops:
[=FireOnHigh;10597]
and then I went a little crazy with for loops
[/]
Must have been a long loop…
Nice work!
[=FireOnHigh;10597]
Hey guys, just wanted to share what I’ve been tinkering around with on this stuff to be able to set UV’s for the custom meshes:
[/]
Cool stuff, feel free to adjust the wiki article if you wish: A new, community-hosted Unreal Engine Wiki - Announcements - Epic Developer Community Forums
Or perhaps make your own since I renamed the class.
This is very cool. And I have got it working with a dev/editor build. However, a shipping build with a cooked assets folder causes a crash as soon as the custom geometry creation is triggered.
How would one go about making procedural geometry work in a non-editor build?
I think another user actually found this bug yesterday, we’ll try and get a fix in for the next release!
Oh yeah, I just cooked my stuff and it does crash. Is there a bug report somewhere I can look at and perhaps add to?
[=dmacesic;11766]
Oh yeah, I just cooked my stuff and it does crash. Is there a bug report somewhere I can look at and perhaps add to?
[/]
My initial assumption was that I may be missing some specific material-assigning in my mesh-gen code, which in an editor-build, default materials/textures would be applied in places that I missed, but in a cooked build any undefined material refs would result in null (or random address) mat/tex pointers.
The problem with packaged builds is that it dereferences GEngine->WireframeMaterial, which is NULL after packaging the game without editor support. You can fix the problem by checking if WITH_EDITOR is true before dereferencing WireframeMaterial.
You can see the fix I made to my similar primitive component implementation here: https://.com/AndrewScheidecker/BrickGame/commit/767adc91a7881f149e9488df7b691e354b36728a
[=AndrewJSch;12131]
The problem with packaged builds is that it dereferences GEngine->WireframeMaterial, which is NULL after packaging the game without editor support. You can fix the problem by checking if WITH_EDITOR is true before dereferencing WireframeMaterial.
You can see the fix I made to my similar primitive component implementation here: https://.com/AndrewScheidecker/BrickGame/commit/767adc91a7881f149e9488df7b691e354b36728a
[/]
Yep! That’s fixed it!
I’m trying to confirm this, but I’m getting a bunch on link errors on cook (works fine in editor), investigating. E.g.
LogPlayLevel:Display: UnrealBuildTool: Creating library C:\dev\Unreal\Projects\MyProject5\Binaries\Win64\MyProject5.lib and object C:\dev\Unreal\Projects\MyProject5\Binaries\Win64\MyProject5.exp
LogPlayLevel:Display: UnrealBuildTool: MyProject5.h.obj : warning LNK4217: locally defined symbol ??0FName@@QEAA@PEBDW4EFindName@@_N@Z (public: __cdecl FName::FName(char const *,enum EFindName,bool)) imported in function "void __cdecl `dynamic initializer for 'NAME_DeviceType''(void)" (??__ENAME_DeviceType@@YAXXZ)
LogPlayLevel:Display: UnrealBuildTool: GameHUD.cpp.obj : warning LNK4049: locally defined symbol ??0FName@@QEAA@PEBDW4EFindName@@_N@Z (public: __cdecl FName::FName(char const *,enum EFindName,bool)) imported
LogPlayLevel:Display: UnrealBuildTool: MyProject5.h.obj : warning LNK4049: locally defined symbol ?ZeroVector@FVector@@2V1@B (public: static class FVector const FVector::ZeroVector) imported
LogPlayLevel:Display: UnrealBuildTool: GameHUD.cpp.obj : warning LNK4049: locally defined symbol ?ZeroVector@FVector@@2V1@B (public: static class FVector const FVector::ZeroVector) imported
LogPlayLevel:Display: UnrealBuildTool: GeneratedMeshComponent.cpp.obj : warning LNK4049: locally defined symbol ?ZeroVector@FVector@@2V1@B (public: static class FVector const FVector::ZeroVector) imported
LogPlayLevel:Display: UnrealBuildTool: MyProject5PlayerController.cpp.obj : warning LNK4049: locally defined symbol ?ZeroVector@FVector@@2V1@B (public: static class FVector const FVector::ZeroVector) imported
LogPlayLevel:Display: UnrealBuildTool: MyProject5PlayerController.cpp.obj : warning LNK4049: locally defined symbol ?Logf__VA@FMsg@@SAXPEBDHAEBVFName@@W4Type@ELogVerbosity@@PEB_WZZ (public: static void __cdecl FMsg::Logf__VA(char const *,int,class FName const &,enum ELogVerbosity::Type,wchar_t const *,...)) imported
LogPlayLevel:Display: UnrealBuildTool: GameGeneratedActor.cpp.obj : warning LNK4217: locally defined symbol ?Logf__VA@FMsg@@SAXPEBDHAEBVFName@@W4Type@ELogVerbosity@@PEB_WZZ (public: static void __cdecl FMsg::Logf__VA(char const *,int,class FName const &,enum ELogVerbosity::Type,wchar_t const *,...)) imported in function "public: class UGeneratedMeshComponent * __cdecl FPostConstructInitializeProperties::CreateDefaultSubobject<class UGeneratedMeshComponent,class UGeneratedMeshComponent>(class UObject *,class FName,bool,bool,bool)const " (??$CreateDefaultSubobject@VUGeneratedMeshComponent@@V1@@FPostConstructInitializeProperties@@QEBAPEAVUGeneratedMeshComponent@@PEAVUObject@@VFName@@_N22@Z)
LogPlayLevel:Display: UnrealBuildTool: GameHUD.cpp.obj : warning LNK4049: locally defined symbol ?Logf__VA@FMsg@@SAXPEBDHAEBVFName@@W4Type@ELogVerbosity@@PEB_WZZ (public: static void __cdecl FMsg::Logf__VA(char const *,int,class FName const &,enum ELogVerbosity::Type,wchar_t const *,...)) imported
etc...
In your code it should simply be a single line change in GeneratedMeshComponent.cpp: -
[]
virtual void DrawDynamicElements(FPrimitiveDrawInterface* PDI, const FSceneView* View)
{
QUICK_SCOPE_CYCLE_COUNTER(STAT_GeneratedMeshSceneProxy_DrawDynamicElements);
const bool bWireframe = View->Family->EngineShowFlags.Wireframe;
FColoredMaterialRenderProxy WireframeMaterialInstance(
//GEngine->WireframeMaterial->GetRenderProxy(IsSelected()),
WITH_EDITOR ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : NULL,
FLinearColor(0, 0.5f, 1.f)
);
[/]
[=AndrewJSch;12131]
The problem with packaged builds is that it dereferences GEngine->WireframeMaterial, which is NULL after packaging the game without editor support. You can fix the problem by checking if WITH_EDITOR is true before dereferencing WireframeMaterial.
You can see the fix I made to my similar primitive component implementation here: https://.com/AndrewScheidecker/BrickGame/commit/767adc91a7881f149e9488df7b691e354b36728a
[/]
Good work, I’ve updated the Procedural Mesh Generation code example on the wiki with your solution.
And now to figure out why my Launch button won’t build properly and gives me unresolved externals when cooking and running in the editor work fine… (not related to this fix)
Hi ,
I based my work on CustomMeshComponent to allow per-vertex and uv animation.
Everything started quite well and i can now animate like expected.
Unfortunately i am stuck to one big issue : i cant see the applied material to this mesh.
My mesh is rendered in plain color (ranging from white to black depending on the lighting and … luck… ).
I added support for UVs just like HighOnFire did, the material is attached and gettable with GetMaterial(0)…
If you guys ran into these kind of issues and know how to adapt the code for it to work, i would really appreciate
Thanks
**UVs For GeneratedMesh**
You have to modify the procedure mesh code to use DynamicMeshVertex data rather than just FVector
Then when you cache the vertices the UVs will be included!
Here's the section you need to look at, with my modified code (it wont look the same as what you have currently)
```
FGeneratedMeshSceneProxy(UVictoryMeshComponent* Component)
: FPrimitiveSceneProxy(Component)
, MaterialRelevance(Component->GetMaterialRelevance())
{
// Add each triangle to the vertex/index buffer
for(int TriIdx=0; TriIdx<Component->GeneratedMeshTris.Num(); TriIdx++)
{
FVMeshTri& Tri = Component->GeneratedMeshTris[TriIdx];
IndexBuffer.Indices.Add(
VertexBuffer.Vertices.Add(Tri.Vertex0) //returns new index
);
IndexBuffer.Indices.Add(
VertexBuffer.Vertices.Add(Tri.Vertex1) //returns new index
);
IndexBuffer.Indices.Add(
VertexBuffer.Vertices.Add(Tri.Vertex2) //returns new index
);
}
// Init vertex factory
VertexFactory.Init(&VertexBuffer);
```
I modified my triangle struct to look like this (which is the unit for GeneratedMeshTris)
```
USTRUCT()
struct FVMeshTri
{
GENERATED_USTRUCT_BODY()
FDynamicMeshVertex Vertex0;
FDynamicMeshVertex Vertex1;
FDynamicMeshVertex Vertex2;
FVMeshTri()
{
}
};
```
**DynamicMeshVertex has support for UVs in its TextureCoordinate**
So now pass the entire DynamicMeshVertex into VertexBuffer.Vertices.Add(
and UVs will work correctly!
**I've already proven this in my own project,** resulting in fact that now I can make dynamic UV'ed meshes with collision (thanks Dmacesic!)
https://www.mediafire.com/convkey/e081/27c39zzh11o41z06g.jpg
PS: UPROPERTY() doesnt work with DynamicMeshVertex so I took that out
Thank you for the input .
I finally found out the issue… again something stupid and tricky…
I was actually using FDynamicMeshVertex to build the vertex buffer BUT instead of adding the whole structure i was only adding the FVector position component…:eek:
I wish someone told me about it at compile time
How can we add the support for simulating physics for this generated mesh?
[=arkenthera;17531]
How can we add the support for simulating physics for this generated mesh?
[/]
I cant post the code here for legal reasons, but check out SphereComponent.cpp
and the AggGeom.
adding to AggGeom you can create a physics composite shape to match your mesh!
This does require a lot of careful manual arrangement, just like the UE4 Physics Editor / Phat.
So you will have to do this per shape that you create
[=;17621]
I cant post the code here for legal reasons, but check out SphereComponent.cpp
and the AggGeom.
adding to AggGeom you can create a physics composite shape to match your mesh!
This does require a lot of careful manual arrangement, just like the UE4 Physics Editor / Phat.
So you will have to do this per shape that you create
[/]
Thank you! Will try this for sure and post here if I could achieve it
Hi ,
Is there a way to create multiple instances of the same CustomMeshComponent? Like InstancedStaticMeshComponent?
Thanks