diff --git a/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset b/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset
index f542f83efa30009ee89233fe71d8158451a5504d..85eb9af14c8ea1ab56e73777bd65a3ea07accf86 100644
Binary files a/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset and b/Content/Blueprints/OptiXVRPawnStandaloneBP.uasset differ
diff --git a/Content/Blueprints/OpticalTable.uasset b/Content/Blueprints/OpticalTable.uasset
index 2abe0034ea4d690c667a7b302f4ca795960a023e..ea173175cb8d2e338799557b019833b4f530eb5f 100644
Binary files a/Content/Blueprints/OpticalTable.uasset and b/Content/Blueprints/OpticalTable.uasset differ
diff --git a/Source/OptiX/OptiX.Build.cs b/Source/OptiX/OptiX.Build.cs
index a42b7c140debd5302d45731e35b32bdf236ff371..2769424749469ba63b9229ee616d7536ebe7d9b5 100644
--- a/Source/OptiX/OptiX.Build.cs
+++ b/Source/OptiX/OptiX.Build.cs
@@ -8,11 +8,13 @@ public class OptiX : ModuleRules
 
         PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
 
-        bEnableExceptions = true;        
+        bEnableExceptions = true;   
+        
 
         string EnginePath = Path.GetFullPath(Target.RelativeEnginePath);
         string ModulePath = ModuleDirectory;
 
+        Definitions.Add("MALLOC_LEAKDETECTION=0");
 
 
         PublicIncludePaths.AddRange(
diff --git a/Source/OptiX/Private/OptiXContextManager.cpp b/Source/OptiX/Private/OptiXContextManager.cpp
index 4880f361656d8e01476548c09ba5040a9dfb4ecd..149e097382b90a539bb2b078a8a2c156026dc4ab 100644
--- a/Source/OptiX/Private/OptiXContextManager.cpp
+++ b/Source/OptiX/Private/OptiXContextManager.cpp
@@ -522,9 +522,7 @@ void FOptiXContextManager::InitRendering()
 	Height = CurrentViewport->GetSizeXY().Y;
 
 	UE_LOG(LogTemp, Display, TEXT("Got viewport sizes: %i, %i"), Width, Height);
-
-
-	//UE_LOG(LogTemp, Warning, TEXT("Res: %i %i"), Width, Height);
+	UE_LOG(LogTemp, Warning, TEXT("Full Res: %i %i"), Width * 2, Height);
 
 
 	// Apparently those can be 0 in a packaged build? 
diff --git a/Source/OptiX/Private/OptiXLensComponent.cpp b/Source/OptiX/Private/OptiXLensComponent.cpp
index 64d5a240093d998e634efe319a12d20a2d7fbf5c..c63a042a0115b5c02e8ac15b9e42ed6e8cb747cd 100644
--- a/Source/OptiX/Private/OptiXLensComponent.cpp
+++ b/Source/OptiX/Private/OptiXLensComponent.cpp
@@ -154,7 +154,6 @@ void UOptiXLensComponent::InitOptiXGroups()
 	OptiXContext->GetGroup("top_object")->AddChild(OptiXTransform);
 	MarkDirty();
 
-
 	// hook into WL update:
 	FOptiXModule::Get().GetOptiXContextManager()->WavelengthChangedEvent.AddUFunction(this, "OnWavelengthChangedEvent");
 }
@@ -253,6 +252,17 @@ void UOptiXLensComponent::CleanOptiXComponent()
 
 }
 
+void UOptiXLensComponent::InitFromData(const FLensData& Data)
+{
+	SetLensRadius(Data.LensRadius);
+	SetRadius1(Data.Radius1);
+	SetRadius2(Data.Radius2);
+	SetThickness(Data.Thickness);
+	SetLensType1(Data.LensTypeSide1);
+	SetLensType2(Data.LensTypeSide2);
+	SetGlassType(Data.GlassType);
+}
+
 void UOptiXLensComponent::SetThickness(float Thickness)
 {
 	UE_LOG(LogTemp, Display, TEXT("Setting Thickness: %f"), Thickness);
diff --git a/Source/OptiX/Private/OptiXModule.cpp b/Source/OptiX/Private/OptiXModule.cpp
index bc03d1b606b0bd64c67045d097494576b1bf2d12..7f0c82c419cca6a195b96ace7fddfd7c88f09e50 100644
--- a/Source/OptiX/Private/OptiXModule.cpp
+++ b/Source/OptiX/Private/OptiXModule.cpp
@@ -6,6 +6,8 @@
 #include <Runtime/Engine/Classes/Engine/Engine.h>
 #include "Json.h"
 #include "JsonObjectConverter.h"
+#include "Misc/FileHelper.h"
+
 
 #include "OptiXContextManager.h"
 
@@ -51,6 +53,7 @@ void FOptiXModule::StartupModule()
 	Singleton = this;
 
 	LoadGlassDefinitions();
+	LoadSceneData();
 
 	// Set optix compiled shader path
 	OptiXPTXDir = FPaths::ProjectContentDir() / TEXT("ptx/");
@@ -130,6 +133,209 @@ void FOptiXModule::LoadGlassDefinitions()
 	}
 }
  
+void FOptiXModule::LoadSceneData()
+{
+	FString SceneDataDirectory = FPaths::ProjectContentDir() / TEXT("SceneData");
+
+	IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
+	if (!PlatformFile.DirectoryExists(*SceneDataDirectory))
+	{
+		UE_LOG(LogTemp, Error, TEXT("Scene Data Directory does not exist! '%s'."), *SceneDataDirectory);
+		return;
+	}
+
+	TArray<FString> FoundFiles;
+
+	PlatformFile.FindFiles(FoundFiles, *SceneDataDirectory, TEXT(".zmx"));
+
+	for (const FString& SceneFile : FoundFiles)
+	{
+		UE_LOG(LogTemp, Display, TEXT("Found scene file: '%s'."), *SceneFile);
+
+		FSceneData SceneData;
+		
+
+		SceneData.SceneName = SceneFile;
+		SceneData.SceneName.RemoveFromEnd(".zmx");
+		SceneData.SceneName.RemoveFromStart(SceneDataDirectory);
+
+		TArray<FString> Lines;
+		FFileHelper::LoadFileToStringArray(Lines, *SceneFile);
+
+		float AccDist = NAN;
+		float Curvature = NAN;
+		float Pos = NAN;
+		float Diameter = NAN;
+
+		float Curvature2 = NAN;
+		float Thickness = NAN;
+		float Diameter2 = NAN;
+
+		bool bFirstSide = true;
+
+		FString GlassType = "";
+
+		for (const FString& Line : Lines)
+		{
+			TArray<FString> Arguments;
+
+			Line.ParseIntoArrayWS(Arguments); // Apparently O(n^2)
+			if (Arguments.Num() == 0)
+				continue;
+
+			if (Arguments[0] == "WAVM")
+			{
+				if(Arguments.IsValidIndex(2))
+					SceneData.Wavelength = FCString::Atof(*Arguments[2]) *1000.0f;
+				else
+					UE_LOG(LogTemp, Warning, TEXT("Could not parse wavelength, using defualt of 500.0. Line is: '%s'."), *Line);
+			}
+			else if (Arguments[0] == "SURF")
+			{
+				if (bFirstSide) // Gathering values for side 1 of the lense
+				{
+					// Check if we have gathered all values
+					if (!isnan(Curvature) && !isnan(Diameter) && GlassType.Len() > 0)
+						bFirstSide = false; // Start gathering data for second side
+					else // reset, not a lens
+					{
+						bFirstSide = true;
+						GlassType = "";
+						Curvature = NAN;
+						Curvature2 = NAN;
+						Diameter = NAN;
+						Diameter2 = NAN;
+						Thickness = NAN;
+						Pos = NAN;
+					}
+				}
+				else // first side is completed, check if second side is valid
+				{
+					if (!isnan(Curvature2) && !isnan(Diameter2) && !isnan(Thickness) && GlassType.Len() > 0)
+					{
+						FLensData LensData;
+						LensData.GlassType = GlassType;
+						LensData.Position = Pos;
+						LensData.LensRadius = Diameter / 2.0;
+						LensData.Radius1 = 1.0f / FMath::Abs(Curvature);
+						LensData.Radius2 = 1.0f / FMath::Abs(Curvature2);
+						if (Curvature == 0)
+							LensData.LensTypeSide1 = ELensSideType::PLANE;
+						else if (Curvature < 0)
+							LensData.LensTypeSide1 = ELensSideType::CONVEX;
+						else
+							LensData.LensTypeSide1 = ELensSideType::CONCAVE;
+
+						if (Curvature2 == 0)
+							LensData.LensTypeSide2 = ELensSideType::PLANE;
+						else if (Curvature2 < 0)
+							LensData.LensTypeSide2 = ELensSideType::CONVEX;
+						else
+							LensData.LensTypeSide2 = ELensSideType::CONCAVE;
+
+						LensData.Thickness = Thickness;
+						SceneData.LensData.Push(LensData);
+
+						bFirstSide = true;
+						GlassType = "";
+						Curvature = NAN;
+						Curvature2 = NAN;
+						Diameter = NAN;
+						Diameter2 = NAN;
+						Thickness = NAN;
+						Pos = NAN;
+
+					}
+				}
+			}
+			else if (Arguments[0] == "CURV")
+			{
+				if (Arguments.IsValidIndex(1))
+				{
+					if (bFirstSide)
+						Curvature = FCString::Atof(*Arguments[1]);
+					else 
+						Curvature2 = FCString::Atof(*Arguments[1]);
+				}
+				else
+					UE_LOG(LogTemp, Warning, TEXT("Could not parse curvature, Line is: '%s'."), *Line);
+			}
+			else if (Arguments[0] == "DISZ")
+			{
+				if (Arguments.IsValidIndex(1))
+				{
+					if (bFirstSide)
+					{
+						Thickness = FCString::Atof(*Arguments[1]) / 10.0f;	// in cm
+						Pos = isnan(AccDist) ? 0 : AccDist;
+					}
+					if(isnan(AccDist))
+						AccDist = FCString::Atof(*Arguments[1]) / 10.0f;	// in cm
+					else
+						AccDist += FCString::Atof(*Arguments[1]) / 10.0f;	// in cm
+				}
+				else
+					UE_LOG(LogTemp, Warning, TEXT("Could not parse disz, Line is: '%s'."), *Line);
+			}
+			else if (Arguments[0] == "DIAM")
+			{
+				if (Arguments.IsValidIndex(1))
+				{
+					if (bFirstSide)
+						Diameter = FCString::Atof(*Arguments[1]) / 10.0f; // in cm
+					else
+						Diameter2 = FCString::Atof(*Arguments[1]) / 10.0f;	// in cm
+				}
+				else
+					UE_LOG(LogTemp, Warning, TEXT("Could not parse diameter, Line is: '%s'."), *Line);
+			}
+			else if (Arguments[0] == "GLAS")
+			{
+				if (Arguments.IsValidIndex(1))
+				{
+					GlassType = Arguments[1];
+				}
+				else
+					UE_LOG(LogTemp, Warning, TEXT("Could not parse glass, Line is: '%s'."), *Line);
+			}
+
+		}
+
+		SceneData.LaserPosition = isnan(Pos) ? Pos : 0.0f;
+
+		SceneDataArray.Push(SceneData);
+
+	}
+
+
+	// Debug:
+
+	const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, TEXT("ELensSideType"), true);
+
+	for (const FSceneData& Scene: SceneDataArray)
+	{
+		UE_LOG(LogTemp, Display, TEXT("Imported Scene with Name: '%s'."), *Scene.SceneName);
+		UE_LOG(LogTemp, Display, TEXT("  Wavelength: %f"), Scene.Wavelength);
+		UE_LOG(LogTemp, Display, TEXT("  Laser Position: %f"), Scene.LaserPosition);
+		UE_LOG(LogTemp, Display, TEXT("  Lens Number: %i"), Scene.LensData.Num());
+		UE_LOG(LogTemp, Display, TEXT("  Lens Data: \n---------------------------------------------------"));
+		for (const FLensData& Lens : Scene.LensData)
+		{
+			FString Type1 = (EnumPtr == nullptr) ? FString::FromInt(static_cast<uint8>(Lens.LensTypeSide1)) : EnumPtr->GetNameStringByValue(static_cast<int64>(Lens.LensTypeSide1));
+			FString Type2 = (EnumPtr == nullptr) ? FString::FromInt(static_cast<uint8>(Lens.LensTypeSide2)) : EnumPtr->GetNameStringByValue(static_cast<int64>(Lens.LensTypeSide1));
+
+			UE_LOG(LogTemp, Display, TEXT("    Lens Position: %f"), Lens.Position);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Radius: %f"), Lens.LensRadius);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Radius Side 1: %f"), Lens.Radius1);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Radius Side 2: %f"), Lens.Radius2);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Type Side 1: %s"), *Type1);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Type Side 2: %s"), *Type2);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Thickness: %f"), Lens.Thickness);
+			UE_LOG(LogTemp, Display, TEXT("    Lens Glass: %s"), *Lens.GlassType);
+			UE_LOG(LogTemp, Display, TEXT("    ---------------------------------------------------"));
+		}
+	}
+}
 
 // Init the context manager. This is called from the game thread in initgame, NOT on module startup.
 void FOptiXModule::Init()
diff --git a/Source/OptiX/Public/OptiXContextManager.h b/Source/OptiX/Public/OptiXContextManager.h
index 5292332245a3c946876d7eb69ad1de5220021ab1..619a7445adbb209a3009f2918aa59b94777f3b2f 100644
--- a/Source/OptiX/Public/OptiXContextManager.h
+++ b/Source/OptiX/Public/OptiXContextManager.h
@@ -486,6 +486,34 @@ private:
 		UE_LOG(LogTemp, Display, TEXT("Starting Cleanup in Context Manager"));
 
 
+		if (bIsInitialized)
+		{
+			if(CudaResourceDepthLeft != NULL)
+				cudaGraphicsUnregisterResource(CudaResourceDepthLeft);
+			if (CudaResourceDepthRight != NULL)
+				cudaGraphicsUnregisterResource(CudaResourceDepthRight);
+			if (CudaResourceColorLeft != NULL)
+				cudaGraphicsUnregisterResource(CudaResourceColorLeft);
+			if(CudaResourceColorRight != NULL)
+				cudaGraphicsUnregisterResource(CudaResourceColorRight);
+			if(CudaResourceIntersections != NULL)
+				cudaGraphicsUnregisterResource(CudaResourceIntersections);
+
+			PrintLastCudaError("cudaGraphicsUnregisterResource");
+			if(CudaLinearMemoryDepth != NULL)
+				cudaFree(CudaLinearMemoryDepth);
+
+			if (CudaLinearMemoryColor != NULL)
+				cudaFree(CudaLinearMemoryColor);
+
+			if (CudaLinearMemoryIntersections != NULL)
+				cudaFree(CudaLinearMemoryIntersections);
+
+			PrintLastCudaError("cudaFree");
+		}
+
+
+
 		//check(IsInRenderingThread());
 		bStartTracing.AtomicSet(false);
 		bIsInitialized.AtomicSet(false);
diff --git a/Source/OptiX/Public/OptiXGlassDefinitions.h b/Source/OptiX/Public/OptiXGlassDefinitions.h
index b1ff0e3f01b96001bd10f4c245930de8b4b4e55b..93dd0965309f478942961fe2770ca42e47a35f58 100644
--- a/Source/OptiX/Public/OptiXGlassDefinitions.h
+++ b/Source/OptiX/Public/OptiXGlassDefinitions.h
@@ -3,6 +3,70 @@
 
 #include "OptiXGlassDefinitions.generated.h"
 
+
+// todo move this to the right place:
+
+/**
+ * Lens Type Enum
+ */
+UENUM(BlueprintType)
+enum class ELensSideType : uint8 // Unreal seems to only support uint8 for blueprints, adjust values 
+{
+	PLANE = 0 		UMETA(DisplayName = "Plane"),
+	CONVEX = 1		UMETA(DisplayName = "Convex"),
+	CONCAVE = 2 	UMETA(DisplayName = "Concave")
+};
+
+
+USTRUCT(BlueprintType)
+struct OPTIX_API FLensData
+{
+	GENERATED_BODY()
+
+	UPROPERTY(BlueprintReadOnly)
+	float Position; // Along the main axis
+
+	UPROPERTY(BlueprintReadOnly)
+	float LensRadius;
+
+	UPROPERTY(BlueprintReadOnly)
+	float Radius1;
+
+	UPROPERTY(BlueprintReadOnly)
+	float Radius2;
+
+	UPROPERTY(BlueprintReadOnly)
+	ELensSideType LensTypeSide1;
+
+	UPROPERTY(BlueprintReadOnly)
+	ELensSideType LensTypeSide2;
+
+	UPROPERTY(BlueprintReadOnly)
+	float Thickness;
+
+	UPROPERTY(BlueprintReadOnly)
+	FString GlassType;
+};
+
+
+USTRUCT(BlueprintType)
+struct FSceneData
+{
+	GENERATED_BODY()
+
+	UPROPERTY(BlueprintReadOnly)
+	FString SceneName;
+
+	UPROPERTY(BlueprintReadOnly)
+	float LaserPosition = 0.0f; // Along main axis
+
+	UPROPERTY(BlueprintReadOnly)
+	float Wavelength = 500.0f;
+
+	UPROPERTY(BlueprintReadOnly)
+	TArray<FLensData> LensData;
+};
+
 // Okay, for some crazy reason glass definitions have been originally saved here... TODOOOOO
 USTRUCT(BlueprintType)
 struct FGlassDefinition
diff --git a/Source/OptiX/Public/OptiXIncludes.h b/Source/OptiX/Public/OptiXIncludes.h
index eb8eebbc95b06fb1da67a6338cb5e7e5ae512187..341588b4e3ab09f59f69ef74658c98cdd000104d 100644
--- a/Source/OptiX/Public/OptiXIncludes.h
+++ b/Source/OptiX/Public/OptiXIncludes.h
@@ -1,5 +1,8 @@
 #pragma once
 
+//#define MALLOC_LEAKDETECTION 1
+//#include "MallocLeakDetection.h"
+
 THIRD_PARTY_INCLUDES_START
 
 #if PLATFORM_WINDOWS
diff --git a/Source/OptiX/Public/OptiXLensComponent.h b/Source/OptiX/Public/OptiXLensComponent.h
index 30c035a0e1509fbb8ece911c610639e626b9281b..956f68e492bb1486bdcb3135b8c66b8534f996d4 100644
--- a/Source/OptiX/Public/OptiXLensComponent.h
+++ b/Source/OptiX/Public/OptiXLensComponent.h
@@ -11,16 +11,7 @@
 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLensRadiusChanged, float, Radius);
 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnLensThicknessChanged, float, Thickness);
 
-/**
- * Lens Type Enum
- */
-UENUM(BlueprintType)
-enum class ELensSideType : uint8 // Unreal seems to only support uint8 for blueprints, adjust values 
-{
-	PLANE = 0 		UMETA(DisplayName = "Plane"),
-	CONVEX = 1		UMETA(DisplayName = "Convex"),
-	CONCAVE = 2 	UMETA(DisplayName = "Concave")
-};
+
 
 ///**
 // * Glass Type Enum
@@ -75,6 +66,9 @@ public:
 	// This sadly only works in the editor itself, leave it for now
 	//virtual void PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent) override;
 
+	UFUNCTION(BlueprintCallable, /*meta = (BlueprintProtected)*/ Category = "OptiXLensComponent")
+	void InitFromData(const FLensData& Data);
+
 	UFUNCTION(BlueprintCallable, /*meta = (BlueprintProtected)*/ Category = "OptiXLensComponent")
 		void SetThickness(float Thickness);
 	UFUNCTION(BlueprintPure, BlueprintCallable, /*meta = (BlueprintProtected)*/ Category = "OptiXLensComponent")
diff --git a/Source/OptiX/Public/OptiXModule.h b/Source/OptiX/Public/OptiXModule.h
index e7fb2811ddb06fb183d847a21510a58b14acb02b..cacb573a7caea71905b9f1f7000ee771b9cb0483 100644
--- a/Source/OptiX/Public/OptiXModule.h
+++ b/Source/OptiX/Public/OptiXModule.h
@@ -10,6 +10,7 @@
 
 DECLARE_LOG_CATEGORY_EXTERN(OptiXPlugin, Log, All);
 
+
 class OPTIX_API FOptiXModule : public IModuleInterface
 {
 public:
@@ -45,6 +46,11 @@ public:
 		return GlassDefinitionsMap;
 	}
 
+	const TArray<FSceneData>& GetSceneDataArray()
+	{
+		return SceneDataArray;
+	}
+
 public:
 	FString OptiXPTXDir;
 
@@ -60,6 +66,7 @@ private:
 	void UnloadDLLs();
 
 	void LoadGlassDefinitions();
+	void LoadSceneData();
 
 	void* CudaRtHandle;
 	void* OptixHandle;
@@ -70,5 +77,7 @@ private:
 
 	TMap<FString, FGlassDefinition> GlassDefinitionsMap;
 
+	TArray<FSceneData> SceneDataArray;
+
 	static FOptiXModule* Singleton;
 };
\ No newline at end of file