Made Instanced Version of Stick/Ball Model from Blender Molecular Nodes CSV

This commit is contained in:
Simeon "Waldo" Wallrath 2026-02-04 17:07:07 +01:00
parent 704ba31fb9
commit e658df9854
39 changed files with 2914 additions and 45 deletions

View file

@ -1,12 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
//#include "VRExpPluginExample.h"
#include "EmptyClassForProject.h"
EmptyClassForProject::EmptyClassForProject()
{
}
EmptyClassForProject::~EmptyClassForProject()
{
}

View file

@ -1,27 +0,0 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "VRCharacter.h"
#include "GripMotionControllerComponent.h"
#include "VRBPDatatypes.h"
#include "VRGripInterface.h"
#include "VRPlayerController.h"
#include "VRExpansionFunctionLibrary.h"
#include "Grippables/GrippableBoxComponent.h"
#include "VRStereoWidgetComponent.h"
#include "VRCharacterMovementComponent.h"
#include "Misc/VRLogComponent.h"
#include "VRAIController.h"
#include "VRPathFollowingComponent.h"
#include "VRRootComponent.h"
/**
*
*/
class VREXPPLUGINEXAMPLE_API EmptyClassForProject
{
public:
EmptyClassForProject();
~EmptyClassForProject();
};

View file

@ -0,0 +1,61 @@
#include "MoleculeFunctionLibrary.h"
#include "Misc/Paths.h"
#include "Misc/FileHelper.h"
bool UMoleculeFunctionLibrary::ParsePDBFromString(const FString& PDBContent, TArray<FAtom>& OutAtoms, TArray<FBond>& OutBonds)
{
OutAtoms.Empty();
OutBonds.Empty();
if (PDBContent.IsEmpty())
{
UE_LOG(LogTemp, Warning, TEXT("ParsePDBFromString: Input string is empty"));
return false;
}
TArray<FString> Lines;
PDBContent.ParseIntoArrayLines(Lines, true);
for (const FString& Line : Lines)
{
if (!Line.StartsWith(TEXT("ATOM")) && !Line.StartsWith(TEXT("HETATM")))
continue;
if (Line.Len() < 54) // At least enough for X, Y, Z
continue;
FAtom Atom;
// Coordinates (columns are 1-indexed in spec)
Atom.Position.X = FCString::Atof(*Line.Mid(30, 8));
Atom.Position.Y = FCString::Atof(*Line.Mid(38, 8));
Atom.Position.Z = FCString::Atof(*Line.Mid(46, 8));
// Element symbol (columns 77-78), fallback to atom name (columns 13-16)
if (Line.Len() >= 78)
Atom.Element = Line.Mid(76, 2).TrimStartAndEnd();
if (Atom.Element.IsEmpty())
Atom.Element = Line.Mid(12, 4).TrimStartAndEnd().Left(1); // fallback
OutAtoms.Add(Atom);
}
// Bond inference: simple distance-based
const float MaxBondDistance = 1.6f; // can tweak for different atom types
for (int32 i = 0; i < OutAtoms.Num(); i++)
{
for (int32 j = i + 1; j < OutAtoms.Num(); j++)
{
if (FVector::Distance(OutAtoms[i].Position, OutAtoms[j].Position) <= MaxBondDistance)
{
FBond Bond;
Bond.AtomIndex1 = i;
Bond.AtomIndex2 = j;
OutBonds.Add(Bond);
}
}
}
UE_LOG(LogTemp, Log, TEXT("Parsed %d atoms and %d bonds from string"), OutAtoms.Num(), OutBonds.Num());
return true;
}

View file

@ -0,0 +1,52 @@
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "MoleculeFunctionLibrary.generated.h"
/**
* Struct representing an atom
*/
USTRUCT(BlueprintType)
struct FAtom
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="Molecule")
FString Element;
UPROPERTY(BlueprintReadWrite, Category="Molecule")
FVector Position; // Unreal coordinates
};
/**
* Struct representing a bond
*/
USTRUCT(BlueprintType)
struct FBond
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite, Category="Molecule")
int32 AtomIndex1;
UPROPERTY(BlueprintReadWrite, Category="Molecule")
int32 AtomIndex2;
};
/**
* Blueprint Function Library to parse PDB strings
*/
UCLASS()
class UMoleculeFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
/**
* Parses a PDB string and outputs arrays of atoms and bonds
*/
UFUNCTION(BlueprintCallable, Category="Molecule")
static bool ParsePDBFromString(const FString& PDBContent, TArray<FAtom>& OutAtoms, TArray<FBond>& OutBonds);
};