diff --git a/Content/DynamicLineMaterial-Unoptimized.uasset b/Content/DynamicLineMaterial-Unoptimized.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..00cd4efcf8507ee0abbf45cf2ad43e44494c54b2
Binary files /dev/null and b/Content/DynamicLineMaterial-Unoptimized.uasset differ
diff --git a/Content/DynamicLineMaterial.uasset b/Content/DynamicLineMaterial.uasset
index e4529ef79a4492ebb3bb941980aab51f06487134..caea7d8737eb5a2668617a54dfc47b98154aecdf 100644
Binary files a/Content/DynamicLineMaterial.uasset and b/Content/DynamicLineMaterial.uasset differ
diff --git a/Content/DynamicLineMaterialNewBackup.uasset b/Content/DynamicLineMaterialNewBackup.uasset
index 8941aaff1f87b80799abf485b6497bb4d5b034be..cd0056d098d43cf45c8aafbcf08c79609961a3f3 100644
Binary files a/Content/DynamicLineMaterialNewBackup.uasset and b/Content/DynamicLineMaterialNewBackup.uasset differ
diff --git a/Content/DynamicLineMaterialOldBackup.uasset b/Content/DynamicLineMaterialOldBackup.uasset
index 91d3640c2277496afadde2c9499505066c57455e..2187dc645856e8d11f7368184d65fe2f9fc3932c 100644
Binary files a/Content/DynamicLineMaterialOldBackup.uasset and b/Content/DynamicLineMaterialOldBackup.uasset differ
diff --git a/Content/DynamicLineMaterialTesting.uasset b/Content/DynamicLineMaterialTesting.uasset
index 9b4c6fd06cc86ca8e0d37fe60f303c7ef5892f7d..79d7b52111d4169ebbaba1e1eef3c472ce6f4c40 100644
Binary files a/Content/DynamicLineMaterialTesting.uasset and b/Content/DynamicLineMaterialTesting.uasset differ
diff --git a/Content/line.uasset b/Content/line.uasset
index e53730b60727f78b76728d091c3f56474d3dc599..5eef0bfd3997b72daff8b796b43dfe1f06c9375d 100644
Binary files a/Content/line.uasset and b/Content/line.uasset differ
diff --git a/Content/optimized_line.uasset b/Content/optimized_line.uasset
new file mode 100644
index 0000000000000000000000000000000000000000..d03b0c31a0886d08d020f9d0b27d847d777b0140
Binary files /dev/null and b/Content/optimized_line.uasset differ
diff --git a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
index 687d43f5644036086f2697aab03c51a2cc180176..17a5b81849fd5ec8ad14418ae59962b3027835de 100644
--- a/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
+++ b/Source/InstancedMeshLineRendering/Private/GPUInstancedLineComponent.cpp
@@ -13,7 +13,7 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer&
 	
 	CurrentTextureMarker = FIntPoint(0, 0);
 	CurrentTextureIndex = 0,
-	NextFreeId = 0;
+	//NextFreeId = 0;
 
 	TextureWidth = 2048;
 	TextureHeight = 2048;
@@ -27,7 +27,7 @@ UGPUInstancedLineComponent::UGPUInstancedLineComponent(const FObjectInitializer&
 
 	SetCanEverAffectNavigation(false);
 	
-	static ConstructorHelpers::FObjectFinder<UStaticMesh>LineMeshAsset(TEXT("StaticMesh'/InstancedMeshLineRendering/line.line'"));
+	static ConstructorHelpers::FObjectFinder<UStaticMesh>LineMeshAsset(TEXT("StaticMesh'/InstancedMeshLineRendering/optimized_line.optimized_line'"));
 	static ConstructorHelpers::FObjectFinder<UMaterial>LineMaterialAsset(TEXT("Material'/InstancedMeshLineRendering/DynamicLineMaterial.DynamicLineMaterial'"));
 	UStaticMesh* LineAsset = LineMeshAsset.Object;
 	UMaterial* LineMaterial = LineMaterialAsset.Object;
@@ -513,6 +513,13 @@ void UGPUInstancedLineComponent::ReserveMemory(int32 NumberOfSegments, int32 Num
 	LinearLineData.Reserve(NumberOfLines * (NumberOfSegments + 1));	
 }
 
+void UGPUInstancedLineComponent::ReserveMemoryWithoutSegments(int32 NumberOfLines, int32 NumberOfTotalPoints)
+{
+	PreAllocateInstancesMemory(NumberOfTotalPoints - NumberOfLines); // Allocates a bit too much
+	LineMap.Reserve(NumberOfTotalPoints - NumberOfLines);
+	LinearLineData.Reserve(NumberOfTotalPoints);
+}
+
 bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height)
 {
 	if (LinearLineData.Num() > Width * Height)
@@ -531,9 +538,9 @@ bool UGPUInstancedLineComponent::ResizeTexture(int32 Width, int32 Height)
 	// This might be a bit awkward as the line map is a *map*, and not just an array.
 	// Some lines might be re-ordered in the texture, but that should be fine.
 	
-	for(TPair<int32, FGPULineArray>& Line : LineMap)
+	for(int32 LineId = 0; LineId < LineMap.Num(); ++LineId)//  TPair<int32, FGPULineArray>& Line : LineMap)
 	{
-		for (FGPULineIndices& LineIndices : Line.Value.IndexArray)
+		for (FGPULineIndices& LineIndices : LineMap[LineId].IndexArray)
 		{
 			// Key is instance id, value is texture index.
 			if(LineIndices.InstanceIndex >= 0)
@@ -567,7 +574,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 		LinearLineData.Empty(); // Reset
 		LineMap.Empty();
 
-		NextFreeId = 0;
+		//NextFreeId = 0;
 		CurrentTextureIndex = 0;
 		CurrentTextureMarker = FIntPoint(0, 0);
 		ClearInstances();
@@ -590,8 +597,8 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 	{
 		const FLinearColor Color = UniformColor ? Colors[0] : Colors[LineIndex];
 		const float Width = UniformWidth ? Widths[0] : Widths[LineIndex];
-
-		FGPULineArray& NewLineArray = LineMap.Add(NextFreeId, FGPULineArray());
+		int32 Idx = LineMap.Add(FGPULineArray());
+		FGPULineArray& NewLineArray = LineMap[Idx];
 		NewLineArray.IndexArray.Reserve(NumberOfSegmentsPerLine + 1);
 		
 		for (int32 PointIndex = 0; PointIndex < NumberOfSegmentsPerLine; ++PointIndex)
@@ -601,7 +608,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 			SetCustomDataValue(InstanceId, 0, Color.R, false);
 			SetCustomDataValue(InstanceId, 1, Color.G, false);
 			SetCustomDataValue(InstanceId, 2, Color.B, false);
-			SetCustomDataValue(InstanceId, 3, Width, false);
+			SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 			SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start
 			NewLineArray.IndexArray.Add({InstanceId, LineIndex * (NumberOfSegmentsPerLine + 1) + PointIndex});
 			CurrentTextureIndex++;
@@ -611,7 +618,7 @@ void UGPUInstancedLineComponent::InitializeLinesInBulk(int32 NumberOfLines, int3
 		NewLineArray.IndexArray.Add({-1, LineIndex * (NumberOfSegmentsPerLine + 1) + NumberOfSegmentsPerLine});
 		MoveTextureMarker();
 		CurrentTextureIndex++;
-		NextFreeId++;
+		//NextFreeId++;
 	}
 
 	MarkRenderStateDirty();
@@ -627,11 +634,12 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
 		return -1;
 	}
 	// 1.
-	FGPULineArray& NewLineArray = LineMap.Add(NextFreeId, FGPULineArray());
+	const int32 LineId = LineMap.Add(FGPULineArray());
+	FGPULineArray& NewLineArray = LineMap[LineId];
 	NewLineArray.IndexArray.Reserve(Line.Num());
 
-	const int32 LineId = NextFreeId;
-	NextFreeId++; // TODO Fix Id system as this can possibly overflow.
+	//const int32 LineId = NextFreeId;
+	//NextFreeId++; // TODO Fix Id system as this can possibly overflow.
 
 
 		
@@ -646,7 +654,7 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
 		SetCustomDataValue(InstanceId, 0, Color.R, false);
 		SetCustomDataValue(InstanceId, 1, Color.G, false);		
 		SetCustomDataValue(InstanceId, 2, Color.B, false);
-		SetCustomDataValue(InstanceId, 3, Width, false);		
+		SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 		SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start
 		NewLineArray.IndexArray.Add({InstanceId, LinearLineData.Num() + PointIndex});
 		CurrentTextureIndex++;
@@ -685,6 +693,70 @@ int32 UGPUInstancedLineComponent::AddLine(const TArray<FVector>& Line, FLinearCo
 	return LineId;	
 }
 
+int32 UGPUInstancedLineComponent::AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width)
+{
+	if (Line.Num() < 2)
+	{
+		UE_LOG(LogLineRendering, Error, TEXT("UGPUInstancedLineComponent::AddLine : Can't add line with less than 2 points.")); // Actually we can!
+		return -1;
+	}
+	// 1.
+	const int32 LineId = LineMap.Add(FGPULineArray());
+	FGPULineArray& NewLineArray = LineMap[LineId];
+	NewLineArray.IndexArray.Reserve(Line.Num());
+
+
+
+	const int32 NumberSegments = Line.Num() - 1;
+
+	const FIntPoint InitialTextureMarker = CurrentTextureMarker;
+
+	for (int32 PointIndex = 0; PointIndex < NumberSegments; ++PointIndex)
+	{
+		// Add with a dummy transform
+		int32 InstanceId = AddInstance(FTransform::Identity);
+		SetCustomDataValue(InstanceId, 0, Color.R, false);
+		SetCustomDataValue(InstanceId, 1, Color.G, false);
+		SetCustomDataValue(InstanceId, 2, Color.B, false);
+		SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
+		SetCustomDataValue(InstanceId, 4, static_cast<float>(CurrentTextureIndex), false); // Segment Start
+		NewLineArray.IndexArray.Add({ InstanceId, LinearLineData.Num() + PointIndex });
+		CurrentTextureIndex++;
+
+		MoveTextureMarker();
+	}
+	// Add the last point which does not correspond to a transform/instance, but needs to be added to the texture still such that the second last instance can read it:
+	NewLineArray.IndexArray.Add({ -1, LinearLineData.Num() + NumberSegments });
+	MoveTextureMarker();
+	CurrentTextureIndex++;
+
+	// Recreate the data on the heap to allow asynchronous texture update.
+	TArray<FVector4>* TextureData = new TArray<FVector4>(MoveTemp(Line));
+
+
+	// Store the points in a linear array here
+	LinearLineData.Append(*TextureData);
+
+	int32 NumRegions = 0;
+	FUpdateTextureRegion2D* Regions = CalculateTextureRegions(InitialTextureMarker, TextureData->Num(), NumRegions);
+
+	const uint32 Pitch = TextureWidth;
+	PositionTexture->UpdateTextureRegions(0, NumRegions, Regions, Pitch * sizeof(FVector4), sizeof(FVector4), (uint8*)TextureData->GetData(),
+		[](auto InTextureData, auto InRegions)
+	{
+		// Clean up the copied data
+		delete InTextureData;
+		delete InRegions;
+	});
+
+	//UE_LOG(LogLineRendering, Display, TEXT("Added Line #%d"), LineId); // Actually we can!
+
+
+	return LineId;
+
+	
+}
+
 int32 UGPUInstancedLineComponent::AddLineFromEditorData(FEditorLineData& LineData)
 {
 	const TArray<FEditorPoint>* EditorLineDataPtr = &LineData.Points;
@@ -721,7 +793,7 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
 	SetCustomDataValue(InstanceId, 0, R, false);
 	SetCustomDataValue(InstanceId, 1, G, false);
 	SetCustomDataValue(InstanceId, 2, B, false);
-	SetCustomDataValue(InstanceId, 3, Width, false);
+	SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 	
 	// Update the latest dummy entry to point to the actual segment.
 	Line.IndexArray.Last().InstanceIndex = InstanceId;
@@ -731,7 +803,7 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
 	FVector4& PreviousLastPoint = LinearLineData[Indices.TextureIndex];
 	PreviousLastPoint.W = 1.0; // This isn't the line end anymore.
 
-	if(LineId == NextFreeId - 1)
+	if(LineId == LineMap.Num() - 1)
 	{
 		
 		LinearLineData.Add(FVector4(Point, -1)); // This is the last point now.
@@ -793,10 +865,10 @@ bool UGPUInstancedLineComponent::AddPoint(int32 LineId, const FVector& Point)
 
 	const int32 NewPointTextureIndex = Indices.TextureIndex + 1;
 
-	// Update all LineMap Indices that have a texture index larger than the newly inserted point. Todo: Make more efficient, maybe remove map and swap to array:
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	// Update all LineMap Indices that have a texture index larger than the newly inserted point.
+	//Todo: Make more efficient
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
 		if (LineArray.IndexArray[0].TextureIndex >= NewPointTextureIndex)
 		{
 			// Need to increase all indices by 1 and adjust the custom data
@@ -842,7 +914,7 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
 	SetCustomDataValue(InstanceId, 0, Color.R, false);
 	SetCustomDataValue(InstanceId, 1, Color.G, false);
 	SetCustomDataValue(InstanceId, 2, Color.B, false);
-	SetCustomDataValue(InstanceId, 3, Width, false);
+	SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 
 	LinearLineData.Insert(FVector4(Point), LinearDataIndex);
 
@@ -865,9 +937,8 @@ bool UGPUInstancedLineComponent::InsertPoint(int32 LineId, int32 SegmentId, cons
 	}
 
 	// Update all following lines
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
 		if (LineArray.IndexArray[0].TextureIndex > LinearDataIndex)
 		{
 			// Need to increase all indices by 1 and adjust the custom data
@@ -927,7 +998,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 	FVector4& PreviousLastPoint = LinearLineData[Indices.TextureIndex];
 	PreviousLastPoint.W = 1.0; // This isn't the line end anymore.
 
-	if (LineId == NextFreeId - 1)
+	if (LineId == LineMap.Num() - 1)
 	{
 		for (int32 PointIndex = 0; PointIndex < Points.Num(); ++PointIndex)
 		{
@@ -936,7 +1007,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 			SetCustomDataValue(InstanceId, 0, R, false);
 			SetCustomDataValue(InstanceId, 1, G, false);
 			SetCustomDataValue(InstanceId, 2, B, false);
-			SetCustomDataValue(InstanceId, 3, Width, false);
+			SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 			SetCustomDataValue(InstanceId, 4, static_cast<float>(PointTextureIndex + PointIndex), false);
 
 			// Update the latest dummy entry to point to the actual segment.
@@ -987,9 +1058,8 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 	const int32 NewPointTextureIndex = Indices.TextureIndex + 1;
 
 	// Update all LineMap Indices that have a texture index larger than the newly inserted point. Todo: Make more efficient, maybe remove map and swap to array:
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
 		if (LineArray.IndexArray[0].TextureIndex >= NewPointTextureIndex)
 		{
 			// Need to increase all indices by 1 and adjust the custom data
@@ -1008,7 +1078,7 @@ bool UGPUInstancedLineComponent::AddPoints(int32 LineId, const TArray<FVector>&
 		SetCustomDataValue(InstanceId, 0, R, false);
 		SetCustomDataValue(InstanceId, 1, G, false);
 		SetCustomDataValue(InstanceId, 2, B, false);
-		SetCustomDataValue(InstanceId, 3, Width, false);
+		SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 		SetCustomDataValue(InstanceId, 4, static_cast<float>(NewPointTextureIndex - 1 + PointIndex), false);
 
 		// Update the latest dummy entry to point to the actual segment.
@@ -1073,7 +1143,7 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
 		SetCustomDataValue(InstanceId, 0, R, false);
 		SetCustomDataValue(InstanceId, 1, G, false);
 		SetCustomDataValue(InstanceId, 2, B, false);
-		SetCustomDataValue(InstanceId, 3, Width, false);
+		SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 		
 		Line.IndexArray.Insert({ InstanceId, LinearDataIndex + PointIndex }, SegmentId + PointIndex);
 		SetCustomDataValue(InstanceId, 4, LinearDataIndex + PointIndex, false);
@@ -1089,9 +1159,9 @@ bool UGPUInstancedLineComponent::InsertPoints(int32 LineId, int32 SegmentId, con
 	}
 
 	// Update all following lines
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
+		//FGPULineArray& LineArray = Pair.Value;
 		if (LineArray.IndexArray[0].TextureIndex > LinearDataIndex)
 		{
 			// Need to increase all indices by 1 and adjust the custom data
@@ -1376,12 +1446,12 @@ bool UGPUInstancedLineComponent::RemoveLine(int32 LineId)
 	// Remove linear data:
 	LinearLineData.RemoveAt(LineTextureIndex, LineLength);
 	// Remove line from map, this invalidates above Line reference.
-	LineMap.Remove(LineId);
+	LineMap.RemoveAt(LineId);
 	
 	// Update all following lines
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
+		//FGPULineArray& LineArray = Pair.Value;
 		for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
 		{
 			if (LineArray.IndexArray[i].InstanceIndex >= InstancesToRemove[0])
@@ -1480,9 +1550,8 @@ bool UGPUInstancedLineComponent::RemovePoint(int32 LineId, int32 PointId)
 	Line.IndexArray.RemoveAt(PointId);
 
 	// Update all following lines
-	for (TPair<int32, FGPULineArray>& Pair : LineMap)
+	for (FGPULineArray& LineArray : LineMap)
 	{
-		FGPULineArray& LineArray = Pair.Value;
 		for (int32 i = 0; i < LineArray.IndexArray.Num(); ++i)
 		{
 			if (LineArray.IndexArray[i].InstanceIndex >= RemovedInstanceId)
@@ -1558,7 +1627,7 @@ bool UGPUInstancedLineComponent::SetLineWidth(int32 LineId, float Width)
 		const int32 InstanceId = LineIndices.InstanceIndex;
 		if (InstanceId >= 0)
 		{
-			SetCustomDataValue(InstanceId, 3, Width, false);
+			SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 		}
 	}
 	MarkRenderStateDirty();
@@ -1569,7 +1638,7 @@ bool UGPUInstancedLineComponent::SetSegmentWidth(int32 LineId, int32 SegmentId,
 {
 	const int32 InstanceId = LineMap[LineId].IndexArray[SegmentId].InstanceIndex;
 
-	SetCustomDataValue(InstanceId, 3, Width, false);
+	SetCustomDataValue(InstanceId, 3, Width / 2.0f, false);
 	return true;
 }
 //#pragma optimize("", on)
diff --git a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
index 2dbfe14ec283739aa35f2573988c2d2cc931052d..a949141c4c7a7e15b5fe14dff31c0c2e31038f81 100644
--- a/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
+++ b/Source/InstancedMeshLineRendering/Public/GPUInstancedLineComponent.h
@@ -155,6 +155,10 @@ public:
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
 	void ReserveMemory(int32 NumberOfSegments, int32 NumberOfLines);
 
+
+	void ReserveMemoryWithoutSegments(int32 NumberOfLines, int32 NumberOfTotalPoints);
+
+	
 	/**
 	 * Manually resized the texture to the specified width and height. Returns false if the texture couldn't be resized, e.g. if more lines are
 	 * being rendered than can be displayed in the texture.
@@ -198,6 +202,9 @@ public:
 	UFUNCTION(BlueprintCallable, Category = "Components|InstancedLineComponent")
 	int32 AddLine(const TArray<FVector>& Line, FLinearColor Color, float Width = 1.0);
 
+
+	int32 AddLine(TArray<FVector4>& Line, FLinearColor Color, float Width = 1.0);
+	
 	/**
 	 * Adds a line and returns the respective ID of the line, which can be used to identify it for updating, modifying and removing.
 	 *
@@ -462,7 +469,7 @@ public:
 	UMaterialInterface* LineMaterialInterface;
 	
 	UPROPERTY()
-	TMap<int32, FGPULineArray> LineMap;
+	TArray<FGPULineArray> LineMap;
 	
 //private:
 	
@@ -475,8 +482,8 @@ public:
 	UPROPERTY()
 	TArray<int32> EditorLineIds;
 
-	UPROPERTY()
-	int32 NextFreeId;
+	//UPROPERTY()
+	//int32 NextFreeId;
 
 	UPROPERTY()
 	int32 CurrentTextureIndex;