截至UE4 4.10 runtime 无法生成BSP类 ,只能通过自定义的Mesh的Vertex 进行绘制 ( Google 考证,能改UE4源码的请忽略 )
可用到的 UE4 集成的Render Plugins :
CustomMeshComponent
ProceduralMeshComponent
以下是参考
参考文献:
https://wiki.unrealengine.com/Procedural_Mesh_Generation
https://answers.unrealengine.com/questions/100323/how-to-create-spawn-boxes-with-box-brush-in-c.html
https://forums.unrealengine.com/showthread.php?1552-Generate-Procedural-Mesh
https://answers.unrealengine.com/questions/22696/undefined.html
https://answers.unrealengine.com/questions/3096/procedural-geometry-in-c.html
复制粘贴备份:
Realtime subtractive geometry
Basically what I am looking to do is move one piece of geometry through another, and have the volume 'carved' out of it, similar to the effect seen here using a subtractive cylinder What I was going to attempt was to have a subtractive brush move along while creating duplicates of itself, however I can't seem to find a means to actually move these 'brush' objects at runtime or instantiate them at all. If this is possible to do, please advise me of how I can achieve it. If it cannot be done like this, I would love to hear an alternate solution to 'carve' geometry in real time. Thank you :) |
I don't think BSP was meant to be used at runtime. If you plan on making only slight modifications to the mesh you could use dynamically created geometry like CustomMeshComponent and recalculate/update the vertices yourself. But if you thing about some serious changes to the shape my suggestion would be to look into voxel-based geometry instead. Thanks for your response, I was originally thinking that some kind of high density voxel-based geometry would be ideal actually, however I was unaware that you could do that kind of thing in Unreal Engine. I saw someone mention something similar in this question, however the link in the response doesn't work for me:https://answers.unrealengine.com/questions/3096/procedural-geometry-in-c.html Also when I search for "voxel based geometry unreal engine" or similar search terms all I get is stuff about Voxel Cone Tracing. If you have any idea of how to get voxel based geometry in Unreal Engine 4 please let me know, or if someone could at least point me in the right direction it would really help me out :) Those are old forum links, not sure if there is still some way to access them. AFAIK there is no built-in voxel in UE4, you will have to do some implementation ;) Unfortunately I never worked with voxels so can't help you any further, but might be worth looking around the forums. Good luck! :) |
Procedural Mesh Generation
This is a very simple demonstration on how to generate procedural meshes and spawn them in game. It is not to be taken as an example of proper programming technique, but only as an indication to help you generate your own meshes.
You can get this up-to-date demo code in a working UE 4.7 project on GitHub. Please note that this no longer works in 4.8 because Epic added an official component with the same name (UProceduralMeshComponent) and similar functionality.
The following assumes you already have a project created. However, you will need to add RHI, RenderCore and ShaderCore modules in your build file.
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "RHI", "RenderCore", "ShaderCore" });
Contents
[hide]Creating a Generated Mesh class
The Unreal Engine 4 sources come with a CustomMeshComponent under EnginePluginsRuntimeCustomMeshComponent. I had trouble with using it as a plugin (link error), so I have reimplemented it. Essentially, copy the files to your project and rename them GeneratedMeshComponent (.h/.cpp). Replace all occurences of "Custom" to "Generated". You will need to add your project header to the cpp file. Otherwise, the code as I have use it is untouched.
Here they are as they appear in my test project:
GeneratedMeshComponent.h
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GeneratedMeshComponent.generated.h"
USTRUCT(BlueprintType)
struct FGeneratedMeshTriangle
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, Category=Triangle)
FVector Vertex0;
UPROPERTY(EditAnywhere, Category=Triangle)
FVector Vertex1;
UPROPERTY(EditAnywhere, Category=Triangle)
FVector Vertex2;
};
/** Component that allows you to specify custom triangle mesh geometry */
UCLASS(editinlinenew, meta=(BlueprintSpawnableComponent), ClassGroup=Rendering)
class UGeneratedMeshComponent : public UMeshComponent, public IInterface_CollisionDataProvider
{
GENERATED_UCLASS_BODY()
public:
/** Set the geometry to use on this triangle mesh */
UFUNCTION(BlueprintCallable, Category="Components|GeneratedMesh")
bool SetGeneratedMeshTriangles(const TArray<FGeneratedMeshTriangle>& Triangles);
/** Description of collision */
UPROPERTY(BlueprintReadOnly, Category="Collision")
class UBodySetup* ModelBodySetup;
// Begin UMeshComponent interface.
virtual int32 GetNumMaterials() const OVERRIDE;
// End UMeshComponent interface.
// Begin Interface_CollisionDataProvider Interface
virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) OVERRIDE;
virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const OVERRIDE;
virtual bool WantsNegXTriMesh() OVERRIDE { return false; }
// End Interface_CollisionDataProvider Interface
// Begin UPrimitiveComponent interface.
virtual FPrimitiveSceneProxy* CreateSceneProxy() OVERRIDE;
virtual class UBodySetup* GetBodySetup() OVERRIDE;
// End UPrimitiveComponent interface.
void UpdateBodySetup();
void UpdateCollision();
private:
// Begin USceneComponent interface.
virtual FBoxSphereBounds CalcBounds(const FTransform & LocalToWorld) const OVERRIDE;
// Begin USceneComponent interface.
/** */
TArray<FGeneratedMeshTriangle> GeneratedMeshTris;
friend class FGeneratedMeshSceneProxy;
};
GeneratedMeshComponent.cpp
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "MyProject5.h"
#include "DynamicMeshBuilder.h"
#include "GeneratedMeshComponent.h"
#include "Runtime/Launch/Resources/Version.h" // for ENGINE_xxx_VERSION
/** Vertex Buffer */
class FGeneratedMeshVertexBuffer : public FVertexBuffer
{
public:
TArray<FDynamicMeshVertex> Vertices;
virtual void InitRHI()
{
#if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 3
FRHIResourceCreateInfo CreateInfo;
VertexBufferRHI = RHICreateVertexBuffer(Vertices.Num() * sizeof(FDynamicMeshVertex),BUF_Static,CreateInfo);
#else
VertexBufferRHI = RHICreateVertexBuffer(Vertices.Num() * sizeof(FDynamicMeshVertex),NULL,BUF_Static);
#endif
// Copy the vertex data into the vertex buffer.
void* VertexBufferData = RHILockVertexBuffer(VertexBufferRHI,0,Vertices.Num() * sizeof(FDynamicMeshVertex), RLM_WriteOnly);
FMemory::Memcpy(VertexBufferData,Vertices.GetTypedData(),Vertices.Num() * sizeof(FDynamicMeshVertex));
RHIUnlockVertexBuffer(VertexBufferRHI);
}
};
/** Index Buffer */
class FGeneratedMeshIndexBuffer : public FIndexBuffer
{
public:
TArray<int32> Indices;
virtual void InitRHI()
{
#if ENGINE_MAJOR_VERSION >= 4 && ENGINE_MINOR_VERSION >= 3
FRHIResourceCreateInfo CreateInfo;
IndexBufferRHI = RHICreateIndexBuffer(sizeof(int32),Indices.Num() * sizeof(int32),BUF_Static,CreateInfo);
#else
IndexBufferRHI = RHICreateIndexBuffer(sizeof(int32),Indices.Num() * sizeof(int32),NULL,BUF_Static);
#endif
// Write the indices to the index buffer.
void* Buffer = RHILockIndexBuffer(IndexBufferRHI,0,Indices.Num() * sizeof(int32),RLM_WriteOnly);
FMemory::Memcpy(Buffer,Indices.GetTypedData(),Indices.Num() * sizeof(int32));
RHIUnlockIndexBuffer(IndexBufferRHI);
}
};
/** Vertex Factory */
class FGeneratedMeshVertexFactory : public FLocalVertexFactory
{
public:
FGeneratedMeshVertexFactory()
{}
/** Initialization */
void Init(const FGeneratedMeshVertexBuffer* VertexBuffer)
{
check(!IsInRenderingThread());
ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
InitGeneratedMeshVertexFactory,
FGeneratedMeshVertexFactory*,VertexFactory,this,
const FGeneratedMeshVertexBuffer*,VertexBuffer,VertexBuffer,
{
// Initialize the vertex factory's stream components.
DataType NewData;
NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer,FDynamicMeshVertex,Position,VET_Float3);
NewData.TextureCoordinates.Add(
FVertexStreamComponent(VertexBuffer,STRUCT_OFFSET(FDynamicMeshVertex,TextureCoordinate),sizeof(FDynamicMeshVertex),VET_Float2)
);
NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer,FDynamicMeshVertex,TangentX,VET_PackedNormal);
NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer,FDynamicMeshVertex,TangentZ,VET_PackedNormal);
NewData.ColorComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT