Skip to content
Snippets Groups Projects
Commit 38e14753 authored by aenneking's avatar aenneking
Browse files

initial commit

parents
Branches
No related tags found
No related merge requests found
{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "MultiLine",
"Description": "Drawing Multiple Lines with one draw call",
"Category": "Other",
"CreatedBy": "Me",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"Installed": false,
"Modules": [
{
"Name": "MultiLine",
"Type": "Runtime",
"LoadingPhase": "Default",
"AdditionalDependencies": [ "ProceduralMeshComponent" ]
}
],
"Plugins": [
{
"Name": "ProceduralMeshComponent",
"Enabled": true
}
]
}
\ No newline at end of file
Resources/Icon128.png

12.4 KiB

// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
using UnrealBuildTool;
public class MultiLine : ModuleRules
{
public MultiLine(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
// ... add other public dependencies that you statically link with here ...
}
);
PrivateDependencyModuleNames.AddRange(
new string[]
{
"CoreUObject",
"Engine",
"Slate",
"SlateCore",
"ProceduralMeshComponent"
// ... add private dependencies that you statically link with here ...
}
);
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
}
}
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#include "MultiLine.h"
#define LOCTEXT_NAMESPACE "FMultiLineModule"
void FMultiLineModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FMultiLineModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FMultiLineModule, MultiLine)
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#include "MultiLineActor.h"
#include "Runtime/Engine/Classes/GameFramework/PlayerController.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Engine/Engine.h"
// Sets default values
AMultiLineActor::AMultiLineActor()
{ // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
mesh_ = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("MultiLineMesh"));
static ConstructorHelpers::FObjectFinder<UMaterial> material(TEXT("/Game/vertex_color.vertex_color"));
if(material.Succeeded())
material_ = material.Object;
RootComponent = mesh_;
}
#pragma optimize( "", off )
void AMultiLineActor::CreateMesh(TArray<LineProps> line_props_vec, bool has_collision_context)
{
TArray<FLinearColor> vertex_colors;
FOccluderVertexArray vertices;
TArray<int32> triangles;
auto index_offset = 0;
for(auto i = 0; i < line_props_vec.Num(); ++i)
{
auto & line_props = line_props_vec[i];
CreateVertices(line_props, vertices);
const auto added_lines_cnt = (line_props.points.Num() - 1);
const auto added_vertex_cnt = added_lines_cnt * 8;
SetUpTriangles(index_offset, triangles);
index_offset += 4;
for(size_t j = 1; j < added_lines_cnt; ++j)
{
SetUpTriangles(index_offset, triangles);
index_offset += 4;
SetUpTriangles(index_offset, triangles);
index_offset += 4;
}
index_offset += 4;
for (auto j = 0; j < added_vertex_cnt; ++j)
vertex_colors.Add(line_props.linear_color);
}
auto uv = TArray<FVector2D>();
auto tangents = TArray<FProcMeshTangent>();
FOccluderVertexArray normals;
mesh_->CreateMeshSection_LinearColor(0, vertices, triangles, normals, uv, vertex_colors, tangents, false);
mesh_->ContainsPhysicsTriMeshData(false);
mesh_->SetMaterial(0, dynamic_cast<UMaterialInterface*>(material_));
}
void AMultiLineActor::UpdateMesh(TArray<LineProps> line_props_vec)
{
auto uv = TArray<FVector2D>();
auto tangents = TArray<FProcMeshTangent>();
FOccluderVertexArray normals;
TArray<FLinearColor> vertex_colors;
FOccluderVertexArray vertices;
for (auto i = 0; i < line_props_vec.Num(); ++i)
{
auto & line_props = line_props_vec[i];
CreateVertices(line_props, vertices);
for (auto j = 0; j < 8; ++j)
vertex_colors.Add(line_props.linear_color);
}
mesh_->UpdateMeshSection_LinearColor(0, vertices, normals, uv, vertex_colors, tangents );
}
void AMultiLineActor::SetFlatShading(bool use_flat_shading)
{
if(use_flat_shading)
material_->SetShadingModel(EMaterialShadingModel::MSM_Unlit);
else
material_->SetShadingModel(EMaterialShadingModel::MSM_DefaultLit);
}
#pragma optimize( "", on )
// Called when the game starts or when spawned
void AMultiLineActor::BeginPlay()
{
Super::BeginPlay();
}
void AMultiLineActor::CreateVertices(LineProps line_props, FOccluderVertexArray & vertices)
{
for(size_t i = 1; i < line_props.points.Num(); ++i)
{
auto line = line_props.points[i] - line_props.points[i-1];
line.Normalize();
auto tangent = FVector::CrossProduct(line, FVector(0.0f, 0.0f, 1.0f));
tangent.Normalize();
auto bi_tangent = FVector::CrossProduct(line, tangent);
bi_tangent.Normalize();
auto & p0 = line_props.points[i-1];
auto & p1 = line_props.points[i];
vertices.Add(p0 + line_props.width * FVector(tangent - bi_tangent));
vertices.Add(p0 + line_props.width * FVector(tangent + bi_tangent));
vertices.Add(p0 - line_props.width * FVector(tangent + bi_tangent));
vertices.Add(p0 - line_props.width * FVector(tangent - bi_tangent));
vertices.Add(p1 + line_props.width * FVector(tangent - bi_tangent));
vertices.Add(p1 + line_props.width * FVector(tangent + bi_tangent));
vertices.Add(p1 - line_props.width * FVector(tangent + bi_tangent));
vertices.Add(p1 - line_props.width * FVector(tangent - bi_tangent));
}
}
void AMultiLineActor::SetUpTriangles(size_t index_offset, TArray<int32> & triangles)
{
//left
triangles.Add(2 + index_offset);
triangles.Add(0 + index_offset);
triangles.Add(3 + index_offset);
triangles.Add(1 + index_offset);
triangles.Add(3 + index_offset);
triangles.Add(0 + index_offset);
//Right
triangles.Add(4 + index_offset);
triangles.Add(6 + index_offset);
triangles.Add(7 + index_offset);
triangles.Add(7 + index_offset);
triangles.Add(5 + index_offset);
triangles.Add(4 + index_offset);
//front
triangles.Add(1 + index_offset);
triangles.Add(0 + index_offset);
triangles.Add(4 + index_offset);
triangles.Add(1 + index_offset);
triangles.Add(4 + index_offset);
triangles.Add(5 + index_offset);
//top
triangles.Add(0 + index_offset);
triangles.Add(2 + index_offset);
triangles.Add(6 + index_offset);
triangles.Add(4 + index_offset);
triangles.Add(0 + index_offset);
triangles.Add(6 + index_offset);
//bottom
triangles.Add(3 + index_offset);
triangles.Add(1 + index_offset);
triangles.Add(7 + index_offset);
triangles.Add(1 + index_offset);
triangles.Add(5 + index_offset);
triangles.Add(7 + index_offset);
//back
triangles.Add(2 + index_offset);
triangles.Add(3 + index_offset);
triangles.Add(6 + index_offset);
triangles.Add(6 + index_offset);
triangles.Add(3 + index_offset);
triangles.Add(7 + index_offset);
}
// Called every frame
void AMultiLineActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
\ No newline at end of file
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
struct LineProps
{
LineProps(){}
LineProps(TArray<FVector> & p, FLinearColor color, float w) : points(p), linear_color(color), width(w)
{}
TArray<FVector> points;
FLinearColor linear_color;
float width;
};
// Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FMultiLineModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ProceduralMeshComponent.h"
#include "LineProps.h"
#include "MultiLineActor.generated.h"
UCLASS()
class MULTILINE_API AMultiLineActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AMultiLineActor();
void CreateMesh(TArray<LineProps> line_props_vec, bool has_collision_context = false);
void UpdateMesh(TArray<LineProps> line_props_vec);
UFUNCTION(BlueprintCallable, Category = "SunShine")
void SetFlatShading(bool use_flat_shading);
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
void CreateVertices(LineProps line_props, FOccluderVertexArray & vertices);
void SetUpTriangles(size_t index_offset, TArray<int32> & triangles);
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
private:
UPROPERTY(VisibleAnywhere)
UProceduralMeshComponent * mesh_;
UPROPERTY(VisibleAnywhere)
UMaterial* material_;
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment