Преглед на файлове

Render Scene and Rays to Obj

main
Felix Brendel преди 4 години
родител
ревизия
49569f7f9b
променени са 8 файла, в които са добавени 412 реда и са изтрити 48 реда
  1. +1
    -0
      .gitignore
  2. +14
    -0
      dist/scene1.txt
  3. Двоични данни
     
  4. +2
    -1
      src/dt_pathtrace.cpp
  5. +163
    -47
      src/main.cpp
  6. +5
    -0
      src/ray_pack.hpp
  7. +225
    -0
      src/scene.cpp
  8. +2
    -0
      src/scene.hpp

+ 1
- 0
.gitignore Целия файл

@@ -3,3 +3,4 @@
/dist/*
!/dist/*.xyz
!/dist/*.txt
!/dist/*.blend

+ 14
- 0
dist/scene1.txt Целия файл

@@ -0,0 +1,14 @@
GridFile = cloud-049.xyz
Extinction = 0.8, 0.9, 0.8
ScatteringAlbedo = 0.9, 0.9, 0.9
G = 0.3, 0.3, 0.3

CameraPos = -2, -2, -2
CameraLookAt = 0, 0, 0
CameraFOV = 10

ResX = 10
ResY = 10
SamplesPerPixel = 100

Seed = 123

Двоични данни
Целия файл


+ 2
- 1
src/dt_pathtrace.cpp Целия файл

@@ -2,7 +2,8 @@
#include <cstdio>
#include <cmath>

#define INFO(...) printf("INFO: " __VA_ARGS__);
// #define INFO(...) printf("INFO: " __VA_ARGS__);
#define INFO(...)

#ifndef pi
# define pi 3.1415926535897932384626433832795


+ 163
- 47
src/main.cpp Целия файл

@@ -1,5 +1,6 @@
#include <cstdio>
#include <cmath>
#include <cstring>

#include "vector.hpp"
#include "texture3d.hpp"
@@ -7,28 +8,24 @@
#include "defer.hpp"
#include "dt_pathtrace.hpp"
#include "ray_pack.hpp"
#include "scene.hpp"


void WriteDomainAndRayPackToOBJFile(texture3D Grid, ray_pack* RayPack,
const char* OBJFileName)
{
FILE* out = fopen(OBJFileName, "w");
void WriteDomainToOBJFile(texture3D Grid) {
FILE* out = fopen("output/Domain.obj", "w");
if (!out) {
fprintf(stderr, "ERROR: file %s could not be opened\n", OBJFileName);
fprintf(stderr, "ERROR: file %s could not be opened\n", "output/Domain.obj");
return;
}
defer {
fclose(out);
};

for (float3 v : RayPack->vertices) {
fprintf(out, "v %f %f %f\n", v.x, v.y, v.z);
}

// Domain Box
float3 maxim;
float3 minim;
GetGridBox(Grid, minim, maxim);
fprintf(out, "o Domain\n");

fprintf(out, "v %f %f %f\n", maxim.x, maxim.y, maxim.z);
fprintf(out, "v %f %f %f\n", maxim.x, maxim.y, -maxim.z);
fprintf(out, "v %f %f %f\n", maxim.x, -maxim.y, maxim.z);
@@ -38,16 +35,55 @@ void WriteDomainAndRayPackToOBJFile(texture3D Grid, ray_pack* RayPack,
fprintf(out, "v %f %f %f\n", -maxim.x, -maxim.y, maxim.z);
fprintf(out, "v %f %f %f\n", -maxim.x, -maxim.y, -maxim.z);


fprintf(out, "l %u %u\n", 1, 2);
fprintf(out, "l %u %u\n", 3, 4);
fprintf(out, "l %u %u\n", 5, 6);
fprintf(out, "l %u %u\n", 7, 8);

fprintf(out, "l %u %u\n", 1, 3);
fprintf(out, "l %u %u\n", 2, 4);
fprintf(out, "l %u %u\n", 5, 7);
fprintf(out, "l %u %u\n", 6, 8);

fprintf(out, "l %u %u\n", 1, 5);
fprintf(out, "l %u %u\n", 2, 6);
fprintf(out, "l %u %u\n", 3, 7);
fprintf(out, "l %u %u\n", 4, 8);
}

void WriteRayPackToOBJFile(int x, int y, ray_pack* RayPack) {
if (RayPack->ray_starts.count == 0) {
return;
}

char OBJFileName[1024];
sprintf(OBJFileName, "output/Ray_Pack_%d_%d.obj", x, y);

FILE* out = fopen(OBJFileName, "w");
// FILE* out = stdout;
if (!out) {
fprintf(stderr, "ERROR: file %s could not be opened\n", OBJFileName);
return;
}
defer {
fclose(out);
};

for (float3 v : RayPack->vertices) {
fprintf(out, "v %f %f %f\n", v.x, v.y, v.z);
}

fprintf(out, "g Rays\n");
uint32_t start = 0;
uint32_t end;
int start = 0;
int end;
// all but the last sample:
uint32_t i = 0;
for (; i < RayPack->ray_starts.count-1; ++i) {
int i = 0;
for (; i < (int)(RayPack->ray_starts.count)-1; ++i) {
end = RayPack->ray_starts[i+1];
fprintf(out, "o Ray_%u\n", i);

for (uint32_t j = start; j < end-1; ++j) {
for (int j = start; j < end-1; ++j) {
// NOTE(Felix): +1 because obj vertex ids start counting at 1
fprintf(out, "l %u %u\n", j+1, j+2);
}
@@ -57,56 +93,136 @@ void WriteDomainAndRayPackToOBJFile(texture3D Grid, ray_pack* RayPack,
// NOTE(Felix): the last sample;
end = RayPack->vertices.count;
fprintf(out, "o Ray_%u\n", i);
printf("start %u end %u\n", start, end);
for (uint32_t j = start; j < end-1; ++j) {
for (int j = start; j < end-1; ++j) {
// NOTE(Felix): +1 because obj vertex ids start counting at 1
fprintf(out, "l %u %u\n", j+1, j+2);
}
}

end++;
fprintf(out, "g Domain\n");
fprintf(out, "o Domain\n");
fprintf(out, "l %u %u\n", end+0, end+1);
fprintf(out, "l %u %u\n", end+2, end+3);
fprintf(out, "l %u %u\n", end+4, end+5);
fprintf(out, "l %u %u\n", end+6, end+7);
void WritePixelGridToOBJFile(float GridWidth, float GridHeight, int ResX, int ResY,
float D, float3 P0, float3 X, float3 Y)
{
FILE* out = fopen("output/Camera.obj", "w");
if (!out) {
fprintf(stderr, "ERROR: file %s could not be opened\n", "output/Domain.obj");
return;
}
defer {
fclose(out);
};

float PixelLength = GridWidth / ResX;

P0 = P0 -
PixelLength / 2 * X -
PixelLength / 2 * Y;
GridWidth += PixelLength;
GridHeight += PixelLength;

fprintf(out, "o Camera\n");

int VertIndex = 1;

// horizontal lines
for (int i = 0; i <= ResY; ++i) {
float3 left = P0 + (1.0*i/ResY) * Y * GridHeight;
float3 right= left + X * GridWidth;

fprintf(out, "v %f %f %f\n", left.x, left.y, left.z);
fprintf(out, "v %f %f %f\n", right.x, right.y, right.z);
fprintf(out, "l %d %d\n", VertIndex, VertIndex+1);

VertIndex += 2;

}

// Vertical lines
for (int i = 0; i <= ResX; ++i) {
float3 top = P0 + (1.0*i/ResX) * X * GridWidth;
float3 bottom = top + Y * GridWidth;

fprintf(out, "l %u %u\n", end+0, end+2);
fprintf(out, "l %u %u\n", end+1, end+3);
fprintf(out, "l %u %u\n", end+4, end+6);
fprintf(out, "l %u %u\n", end+5, end+7);
fprintf(out, "v %f %f %f\n", top.x, top.y, top.z);
fprintf(out, "v %f %f %f\n", bottom.x, bottom.y, bottom.z);
fprintf(out, "l %d %d\n", VertIndex, VertIndex+1);

fprintf(out, "l %u %u\n", end+0, end+4);
fprintf(out, "l %u %u\n", end+1, end+5);
fprintf(out, "l %u %u\n", end+2, end+6);
fprintf(out, "l %u %u\n", end+3, end+7);
VertIndex += 2;

}

}

int main() {
void RunSimulationAndOutputScene(scene S) {
ray_pack RayPack;
RayPack.alloc();
defer {
RayPack.dealloc();
};

Random::InitRNG(S.Seed);

float3 CameraDirection = Normalize(S.CameraLookAt - S.CameraPos);

float3 Y = { 0, 0, -1 };
float3 X = Cross(CameraDirection, Y);
Y = Cross(X, CameraDirection);

// printf("X: %f %f %f\n", X.x, X.y, X.z);
// printf("Y: %f %f %f\n", Y.x, Y.y, Y.z);

float D = 0.5f; // how far away from the camera the grid will be
float GridWidth = tan(S.CameraFOV / 2) * 2 * D;
float GridHeight = S.ResY * 1.0 / S.ResX * GridWidth;

float3 P0 =
S.CameraPos +
CameraDirection * D -
0.5f * Y * GridHeight -
0.5f * X * GridWidth;

// printf("P0: %f %f %f\n", P0.x, P0.y,P0.z);

path_info PI = { };
PI.x = {-2, -2, -2};
PI.w = Normalize(float3{0.4,0.4,0} - PI.x);
PI.PassNumber = 0;

volume_info VI = { };
VI.Grid = ReadXYZFile("cloud-049.xyz");
VI.Extinction = {20, 20, 20};
VI.G = {0.3, 0.3, 0.3};
VI.ScatteringAlbedo = {0.9, 0.9, 0.9};

Random::InitRNG(1);
for (int i = 0; i < 30; ++i) {
DTPathtrace(PI, VI, &RayPack);
PI.x = S.CameraPos;

// Pixel loop
for (int y = 0; y < S.ResY; ++y) {
for (int x = 0; x < S.ResX; ++x) {
// printf("INFO: %d %d\n", x, y);
float3 P =
P0 +
X * (x*1.0/(S.ResX-1)) * GridWidth +
Y * (y*1.0/(S.ResY-1)) * GridHeight;
// printf("P: %f %f %f\n", P.x, P.y, P.z);

P = Normalize(P - S.CameraPos);
// printf("dir: %f %f %f\n", P.x, P.y, P.z);

PI.w = P;
// Sample loop
for (int i = 0; i < S.SamplesPerPixel; ++i) {
PI.PassNumber = i;
DTPathtrace(PI, S.VolInfo, &RayPack);
}

WriteRayPackToOBJFile(x, y, &RayPack);
RayPack.reset();
}
}

WriteDomainToOBJFile(S.VolInfo.Grid);
WritePixelGridToOBJFile(GridWidth, GridHeight, S.ResX, S.ResY,
D, P0, X, Y);
}

int main(int ArgCount, char** Args) {
if (ArgCount != 2) {
fprintf(stderr, "Usage: cloud_tracer <scene_file>\n");
return 1;
}

WriteDomainAndRayPackToOBJFile(VI.Grid, &RayPack, "RayPack.obj");
char* SceneFile = Args[1];
scene Scene = LoadSceneFromFile(SceneFile);
RunSimulationAndOutputScene(Scene);

return 0;
}

+ 5
- 0
src/ray_pack.hpp Целия файл

@@ -16,6 +16,11 @@ struct ray_pack {
ray_starts.dealloc();
}

void reset() {
vertices.clear();
ray_starts.clear();
}

void add_vertex(float3 vert) {
vertices.append(vert);
}


+ 225
- 0
src/scene.cpp Целия файл

@@ -0,0 +1,225 @@
#include <cstdio>
#include <cstring>
#include <cmath>
#include "scene.hpp"
#include "defer.hpp"


void FillOutDefaultValues(scene* s) {
*s = { 0 };

s->CameraFOV = 90;
s->CameraPos = {-2, -2, -2};
s->ResX = 32;
s->ResY = 32;
s->SamplesPerPixel = 1;
}

inline bool IsWhitespace(char c) {
return (c == ' ' || c == '\n' || c == '\r' || c == '\t');
}

void EatUntilWord(char* Str, uint32_t* ParsePos) {
while (IsWhitespace(Str[*ParsePos]))
++(*ParsePos);
}

char* ReadEntireFile(const char* filename) {
char* ret = nullptr;
size_t str_len;
FILE *fp = fopen(filename, "rb");
if (fp) {
defer {
fclose(fp);
};

/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
str_len = ftell(fp) + 1;
if (str_len == 0) {
fprintf(stderr, "Empty file");
ret = (char*)malloc(1);
ret[0] = '\0';
return ret;
}

/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) {
fprintf(stderr, "Error reading file");
return nullptr;
}

/* Allocate our buffer to that size. */
ret = (char*)calloc(str_len, sizeof(char));

/* Read the entire file into memory. */
str_len = fread(ret, sizeof(char), str_len, fp);

ret[str_len] = '\0';
if (ferror(fp) != 0) {
fprintf(stderr, "Error reading file");
return nullptr;
}
}
} else {
fprintf(stderr, "Cannot read file: %s", filename);
return nullptr;
}

return ret;
/* Don't forget to call free() later! */
}

float3 ParseFloat3(char* Str, uint32_t* ParsePos) {
float3 Result = { 0 };
int CharsRead = 0;
sscanf(Str+(*ParsePos), "%f, %f, %f%n",
&Result.x, &Result.y, &Result.z, &CharsRead);

*ParsePos += CharsRead;
return Result;
}

float ParseFloat(char* Str, uint32_t* ParsePos) {
float Result = 0;
int CharsRead = 0;
sscanf(Str+(*ParsePos), "%f%n", &Result, &CharsRead);
*ParsePos += CharsRead;
return Result;
}

int ParseInt(char* Str, uint32_t* ParsePos) {
int Result = 0;
int CharsRead = 0;
sscanf(Str+(*ParsePos), "%d%n", &Result, &CharsRead);
*ParsePos += CharsRead;
return Result;
}

char* ParseFileName(char* Str, uint32_t* ParsePos) {
uint32_t EndOfNameIdx = *ParsePos;
while (!IsWhitespace(Str[EndOfNameIdx]))
++EndOfNameIdx;


uint32_t Length = EndOfNameIdx - *ParsePos;
char* Name = Str + *ParsePos;
*ParsePos = EndOfNameIdx;

char* Result = (char*)malloc(Length+1);
memcpy(Result, Name, Length);
Result[Length] = '\0';

return Result;
}

void ParseSetting(char* Str, uint32_t* ParsePos, scene* Scene) {
uint32_t EndOfNameIdx = *ParsePos;
while ((Str[EndOfNameIdx] >= 'a' && Str[EndOfNameIdx] <= 'z') ||
(Str[EndOfNameIdx] >= 'A' && Str[EndOfNameIdx] <= 'Z'))
++EndOfNameIdx;

uint32_t Length = EndOfNameIdx - *ParsePos;
char* Name = Str + *ParsePos;
*ParsePos = EndOfNameIdx;

EatUntilWord(Str, ParsePos);
if (Str[*ParsePos] != '=') {
fprintf(stderr, "ERROR: Syntax error, expected = after setting name (%.*s) Instead: '%s'\n", Length, Name, Str+(*ParsePos));
return;
}
++(*ParsePos);
EatUntilWord(Str, ParsePos);

if (Str[*ParsePos] == '\0') {
fprintf(stderr, "ERROR: EOF while parsing setting %s\n", Name);
return;
}

#define IsSetting(SettingName) ((sizeof(SettingName)-1 == Length) && \
(strncmp(SettingName, Name, Length) == 0))

if (IsSetting("GridFile")) {
Scene->VolInfo.Grid = ReadXYZFile(ParseFileName(Str, ParsePos));
} else if (IsSetting("Extinction")) {
Scene->VolInfo.Extinction = ParseFloat3(Str, ParsePos);
} else if (IsSetting("ScatteringAlbedo")) {
Scene->VolInfo.ScatteringAlbedo = ParseFloat3(Str, ParsePos);
} else if (IsSetting("G")) {
Scene->VolInfo.G = ParseFloat3(Str, ParsePos);
} else if (IsSetting("CameraPos")) {
Scene->CameraPos = ParseFloat3(Str, ParsePos);
} else if (IsSetting("CameraLookAt")) {
Scene->CameraLookAt = Normalize(ParseFloat3(Str, ParsePos));
} else if (IsSetting("SamplesPerPixel")) {
Scene->SamplesPerPixel = ParseInt(Str, ParsePos);
} else if (IsSetting("Seed")) {
Scene->Seed = ParseInt(Str, ParsePos);
} else if (IsSetting("CameraFOV")) {
Scene->CameraFOV = ParseFloat(Str, ParsePos) / 180 * M_PI;
} else if (IsSetting("ResX")) {
Scene->ResX = ParseInt(Str, ParsePos);
} else if (IsSetting("ResY")) {
Scene->ResY = ParseInt(Str, ParsePos);
} else {
fprintf(stderr, "ERROR: Unknown Setting [%.*s] (length %u)", Length, Name, Length);
}

#undef IsSetting
}

scene LoadSceneFromFile(const char* FilePath) {
scene Result;
FillOutDefaultValues(&Result);
Result.SceneFile = FilePath;

char* SceneConfStr = ReadEntireFile(FilePath);
if (!SceneConfStr) {
fprintf(stderr, "ERROR: scene file %s could not be read\n", FilePath);
return {};
}

uint32_t ParsePos = 0;

EatUntilWord(SceneConfStr, &ParsePos);
while (SceneConfStr[ParsePos] != '\0') {
uint32_t OldParsePos = ParsePos;
ParseSetting(SceneConfStr, &ParsePos, &Result);
EatUntilWord(SceneConfStr, &ParsePos);

if (OldParsePos == ParsePos) {
fprintf(stderr, "ERROR: No parsing progress could be made\n");
return {};
}
}

printf("INFO: SceneFile: %s\n", Result.SceneFile);

printf("INFO: Extinction: %f %f %f\n",
Result.VolInfo.Extinction.x,
Result.VolInfo.Extinction.y,
Result.VolInfo.Extinction.z);
printf("INFO: ScatteringAlbedo: %f %f %f\n",
Result.VolInfo.ScatteringAlbedo.x,
Result.VolInfo.ScatteringAlbedo.y,
Result.VolInfo.ScatteringAlbedo.z);
printf("INFO: G: %f %f %f\n",
Result.VolInfo.G.x,
Result.VolInfo.G.y,
Result.VolInfo.G.z);

printf("INFO: CameraPos: %f %f %f\n",
Result.CameraPos.x,
Result.CameraPos.y,
Result.CameraPos.z);
printf("INFO: CameraLookAt: %f %f %f\n",
Result.CameraLookAt.x,
Result.CameraLookAt.y,
Result.CameraLookAt.z);
printf("INFO: CameraFOV: %f\n", Result.CameraFOV);
printf("INFO: ResX: %d\n", Result.ResX);
printf("INFO: ResY: %d\n", Result.ResY);

return Result;
}

+ 2
- 0
src/scene.hpp Целия файл

@@ -6,12 +6,14 @@ struct scene {
const char* SceneFile;

volume_info VolInfo;
uint32_t Seed;

float3 CameraPos;
float3 CameraLookAt;
float CameraFOV;
uint32_t ResX;
uint32_t ResY;
uint32_t SamplesPerPixel;
};

scene LoadSceneFromFile(const char* FilePath);

Зареждане…
Отказ
Запис