Reputation: 21
I am new to Unreal Engine, coming from Unity and as well new to C++. I am trying to import PDB files directly into the engine by using fscanf.
The section of the PDB file which I am attempting to capture is shown below:
ATOM 15 H1 ATHR A 1 3.035 -14.005 16.173 0.75 6.58 H
ATOM 16 H1 BTHR A 1 2.914 -14.713 18.488 0.25 11.77 H
ATOM 17 H2 ATHR A 1 2.830 -14.148 17.523 0.75 6.58 H
ATOM 18 H2 BTHR A 1 4.980 -14.983 15.512 0.25 11.77 H
ATOM 19 H3 ATHR A 1 3.680 -15.162 17.238 0.75 6.58 H
ATOM 20 H3 BTHR A 1 9.013 -8.192 18.474 0.25 11.77 H
ATOM 21 HA ATHR A 1 3.181 -11.806 16.823 0.75 4.19 H
ATOM 22 HA BTHR A 1 3.605 -12.290 17.060 0.25 5.98 H
ATOM 23 HB ATHR A 1 5.699 -13.731 17.989 0.75 4.53 H
ATOM 24 HB BTHR A 1 4.523 -12.115 19.103 0.25 9.37 H
ATOM 25 HG1ATHR A 1 3.314 -12.887 19.057 0.75 8.30 H
ATOM 26 HG1BTHR A 1 4.049 -10.109 18.478 0.25 15.91 H
ATOM 27 HG21ATHR A 1 6.468 -11.628 19.047 0.75 7.89 H
I have found some other examples in libraries that use specifiers such as:
const char atom_line_iformat_[] = "ATOM %5d%*1c%4c%1c%3c%*c%1c%4d%1c%*1c%*1c%*1c%8f%8f%8f%6f%6f%*1c%*1c%*1c%*1c%*1c%*1c%4c%2c%2c";
However, when attempting to use the above specifiers, unreal engine will crash every time if the "ATOM" specifier is present.
My current solution manages to extract the 3D co-ordinate data but as well parses in other lines from the pdb file that are unwanted. There also seems to be duplicate lines in the output as shown in the below image.
[
You can also see here are more incorrect outputs, first image is the log output, second is the data from the pdb files that is being incorrectly read as it is not an ATOM record.
I believe I need a specifier that checks that the first string is "ATOM", but I have not be able to find a working solution.
Any advice would be greatly appreciated!
Code found below:
FString directory = FPaths::ProjectContentDir();
IPlatformFile& file = FPlatformFileManager::Get().GetPlatformFile();
if (file.CreateDirectory(*directory)) {
FString myFile = directory + "/" + fileName + ".pdb";
const char* fileLocation = TCHAR_TO_ANSI(*myFile);
FILE* ptr = fopen(fileLocation, "r");
if (ptr == NULL) {
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("FILE NOT FOUND."));
return atomPositions;
}
else {
double xValue = 0;
double yValue = 0;
double zValue = 0;
UE_LOG(LogTemp, Warning, TEXT("RUNNING"));
while (fscanf(ptr, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*s\n", &xValue,
&yValue, &zValue) != EOF)
{
UE_LOG(LogTemp, Warning, TEXT("X: %lf, Y: %lf, Z: %lf"), xValue, yValue, zValue);
}
}
}
Upvotes: 1
Views: 735
Reputation: 153328
Code is tagged C++ and scanf - a strange combination.
I'll go forward with a fgets()
, sscanf()
explanation, yet using getline()
and other parsing code is more C++ like.
*scanf()
and friends are terrible at recovering from input that does not match the expected format.
As input is line orientation, best to read a line and then parse it.
char buffer[200];
while (fgets(buffer, sizeof buffer, ptr)) {
if (sscanf(buffer, "%*s %*d %*s %*s %*s %*d %lf %lf %lf %*lf %*lf %*s\n",
&xValue, &yValue, &zValue) != 3) {
fprintf(stderr, "Unable to parse <%s>\n", buffer);
exit(-1):
}
UE_LOG(LogTemp, Warning, TEXT("X: %lf, Y: %lf, Z: %lf"), xValue, yValue, zValue);
}
I am confident with a quick code exit of a failed to parsed line, OP will localize the scanning problem.
// Hint - format and input are mismatched
%*d %*s %*s %*s %*d
27 HG21ATHR A 1
Upvotes: 0