Render Scene and Rays to Obj

This commit is contained in:
2021-06-05 01:22:06 +02:00
parent 38b22379a4
commit 49569f7f9b
8 changed files with 416 additions and 52 deletions
+1
View File
@@ -3,3 +3,4 @@
/dist/* /dist/*
!/dist/*.xyz !/dist/*.xyz
!/dist/*.txt !/dist/*.txt
!/dist/*.blend
+14
View File
@@ -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
BIN
View File
Binary file not shown.
+2 -1
View File
@@ -2,7 +2,8 @@
#include <cstdio> #include <cstdio>
#include <cmath> #include <cmath>
#define INFO(...) printf("INFO: " __VA_ARGS__); // #define INFO(...) printf("INFO: " __VA_ARGS__);
#define INFO(...)
#ifndef pi #ifndef pi
# define pi 3.1415926535897932384626433832795 # define pi 3.1415926535897932384626433832795
+167 -51
View File
@@ -1,5 +1,6 @@
#include <cstdio> #include <cstdio>
#include <cmath> #include <cmath>
#include <cstring>
#include "vector.hpp" #include "vector.hpp"
#include "texture3d.hpp" #include "texture3d.hpp"
@@ -7,12 +8,60 @@
#include "defer.hpp" #include "defer.hpp"
#include "dt_pathtrace.hpp" #include "dt_pathtrace.hpp"
#include "ray_pack.hpp" #include "ray_pack.hpp"
#include "scene.hpp"
void WriteDomainToOBJFile(texture3D Grid) {
FILE* out = fopen("output/Domain.obj", "w");
if (!out) {
fprintf(stderr, "ERROR: file %s could not be opened\n", "output/Domain.obj");
return;
}
defer {
fclose(out);
};
// 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);
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);
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);
void WriteDomainAndRayPackToOBJFile(texture3D Grid, ray_pack* RayPack, fprintf(out, "l %u %u\n", 1, 2);
const char* OBJFileName) 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 = fopen(OBJFileName, "w");
// FILE* out = stdout;
if (!out) { if (!out) {
fprintf(stderr, "ERROR: file %s could not be opened\n", OBJFileName); fprintf(stderr, "ERROR: file %s could not be opened\n", OBJFileName);
return; return;
@@ -25,29 +74,16 @@ void WriteDomainAndRayPackToOBJFile(texture3D Grid, ray_pack* RayPack,
fprintf(out, "v %f %f %f\n", v.x, v.y, v.z); 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, "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);
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);
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, "g Rays\n"); fprintf(out, "g Rays\n");
uint32_t start = 0; int start = 0;
uint32_t end; int end;
// all but the last sample: // all but the last sample:
uint32_t i = 0; int i = 0;
for (; i < RayPack->ray_starts.count-1; ++i) { for (; i < (int)(RayPack->ray_starts.count)-1; ++i) {
end = RayPack->ray_starts[i+1]; end = RayPack->ray_starts[i+1];
fprintf(out, "o Ray_%u\n", i); 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 // NOTE(Felix): +1 because obj vertex ids start counting at 1
fprintf(out, "l %u %u\n", j+1, j+2); 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; // NOTE(Felix): the last sample;
end = RayPack->vertices.count; end = RayPack->vertices.count;
fprintf(out, "o Ray_%u\n", i); fprintf(out, "o Ray_%u\n", i);
printf("start %u end %u\n", start, end); for (int j = start; j < end-1; ++j) {
for (uint32_t j = start; j < end-1; ++j) {
// NOTE(Felix): +1 because obj vertex ids start counting at 1 // NOTE(Felix): +1 because obj vertex ids start counting at 1
fprintf(out, "l %u %u\n", j+1, j+2); fprintf(out, "l %u %u\n", j+1, j+2);
} }
}
end++; void WritePixelGridToOBJFile(float GridWidth, float GridHeight, int ResX, int ResY,
fprintf(out, "g Domain\n"); float D, float3 P0, float3 X, float3 Y)
fprintf(out, "o Domain\n"); {
fprintf(out, "l %u %u\n", end+0, end+1); FILE* out = fopen("output/Camera.obj", "w");
fprintf(out, "l %u %u\n", end+2, end+3); if (!out) {
fprintf(out, "l %u %u\n", end+4, end+5); fprintf(stderr, "ERROR: file %s could not be opened\n", "output/Domain.obj");
fprintf(out, "l %u %u\n", end+6, end+7); return;
}
defer {
fclose(out);
};
fprintf(out, "l %u %u\n", end+0, end+2); float PixelLength = GridWidth / ResX;
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, "l %u %u\n", end+0, end+4); P0 = P0 -
fprintf(out, "l %u %u\n", end+1, end+5); PixelLength / 2 * X -
fprintf(out, "l %u %u\n", end+2, end+6); PixelLength / 2 * Y;
fprintf(out, "l %u %u\n", end+3, end+7); 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;
} }
int main() { // 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, "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);
VertIndex += 2;
}
}
void RunSimulationAndOutputScene(scene S) {
ray_pack RayPack; ray_pack RayPack;
RayPack.alloc(); RayPack.alloc();
defer { defer {
RayPack.dealloc(); 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 = { }; path_info PI = { };
PI.x = {-2, -2, -2}; PI.x = S.CameraPos;
PI.w = Normalize(float3{0.4,0.4,0} - PI.x);
PI.PassNumber = 0;
volume_info VI = { }; // Pixel loop
VI.Grid = ReadXYZFile("cloud-049.xyz"); for (int y = 0; y < S.ResY; ++y) {
VI.Extinction = {20, 20, 20}; for (int x = 0; x < S.ResX; ++x) {
VI.G = {0.3, 0.3, 0.3}; // printf("INFO: %d %d\n", x, y);
VI.ScatteringAlbedo = {0.9, 0.9, 0.9}; 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);
Random::InitRNG(1); P = Normalize(P - S.CameraPos);
for (int i = 0; i < 30; ++i) { // printf("dir: %f %f %f\n", P.x, P.y, P.z);
DTPathtrace(PI, VI, &RayPack);
PI.w = P;
// Sample loop
for (int i = 0; i < S.SamplesPerPixel; ++i) {
PI.PassNumber = i;
DTPathtrace(PI, S.VolInfo, &RayPack);
} }
WriteDomainAndRayPackToOBJFile(VI.Grid, &RayPack, "RayPack.obj"); 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;
}
char* SceneFile = Args[1];
scene Scene = LoadSceneFromFile(SceneFile);
RunSimulationAndOutputScene(Scene);
return 0; return 0;
} }
+5
View File
@@ -16,6 +16,11 @@ struct ray_pack {
ray_starts.dealloc(); ray_starts.dealloc();
} }
void reset() {
vertices.clear();
ray_starts.clear();
}
void add_vertex(float3 vert) { void add_vertex(float3 vert) {
vertices.append(vert); vertices.append(vert);
} }
+225
View File
@@ -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
View File
@@ -6,12 +6,14 @@ struct scene {
const char* SceneFile; const char* SceneFile;
volume_info VolInfo; volume_info VolInfo;
uint32_t Seed;
float3 CameraPos; float3 CameraPos;
float3 CameraLookAt; float3 CameraLookAt;
float CameraFOV; float CameraFOV;
uint32_t ResX; uint32_t ResX;
uint32_t ResY; uint32_t ResY;
uint32_t SamplesPerPixel;
}; };
scene LoadSceneFromFile(const char* FilePath); scene LoadSceneFromFile(const char* FilePath);