Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Courses
Scotty3D
Commits
c2535f0f
Commit
c2535f0f
authored
Sep 26, 2020
by
TheNumbat
Browse files
upstream changes
parent
8b8ee1f1
Changes
93
Hide whitespace changes
Inline
Side-by-side
src/platform/platform.cpp
View file @
c2535f0f
#include "../lib/log.h"
#include "font.dat"
#include "gl.h"
#include "platform.h"
#include "font.dat"
#include <glad/glad.h>
#include <imgui/imgui.h>
#include <imgui/imgui_impl_sdl.h>
#include <imgui/imgui_impl_opengl3.h>
#include <imgui/imgui_impl_sdl.h>
#ifdef _WIN32
#include <ShellScalingApi.h>
#include <ConsoleApi.h>
#include <ShellScalingApi.h>
extern
"C"
{
__declspec
(
dllexport
)
bool
NvOptimusEnablement
=
true
;
__declspec
(
dllexport
)
bool
AmdPowerXpressRequestHighPerformance
=
true
;
__declspec
(
dllexport
)
bool
NvOptimusEnablement
=
true
;
__declspec
(
dllexport
)
bool
AmdPowerXpressRequestHighPerformance
=
true
;
}
#else
#else
#include <sys/ioctl.h>
#endif
int
Platform
::
console_width
()
{
int
cols
=
0
;
int
cols
=
0
;
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO
csbi
;
GetConsoleScreenBufferInfo
(
GetStdHandle
(
STD_OUTPUT_HANDLE
),
&
csbi
);
cols
=
csbi
.
srWindow
.
Right
-
csbi
.
srWindow
.
Left
+
1
;
CONSOLE_SCREEN_BUFFER_INFO
csbi
;
GetConsoleScreenBufferInfo
(
GetStdHandle
(
STD_OUTPUT_HANDLE
),
&
csbi
);
cols
=
csbi
.
srWindow
.
Right
-
csbi
.
srWindow
.
Left
+
1
;
#else
struct
winsize
w
;
ioctl
(
0
,
TIOCGWINSZ
,
&
w
);
cols
=
w
.
ws_col
;
struct
winsize
w
;
ioctl
(
0
,
TIOCGWINSZ
,
&
w
);
cols
=
w
.
ws_col
;
#endif
return
cols
;
return
cols
;
}
void
Platform
::
remove_console
()
{
#ifdef _WIN32
FreeConsole
();
FreeConsole
();
#endif
}
Platform
::
Platform
()
{
platform_init
();
}
Platform
::
Platform
()
{
platform_init
();
}
Platform
::~
Platform
()
{
platform_shutdown
();
}
Platform
::~
Platform
()
{
platform_shutdown
();
}
void
Platform
::
platform_init
()
{
#ifdef _WIN32
if
(
SetProcessDpiAwareness
(
PROCESS_PER_MONITOR_DPI_AWARE
)
!=
S_OK
)
warn
(
"Failed to set process DPI aware."
);
if
(
SetProcessDpiAwareness
(
PROCESS_PER_MONITOR_DPI_AWARE
)
!=
S_OK
)
warn
(
"Failed to set process DPI aware."
);
#endif
if
(
SDL_Init
(
SDL_INIT_EVERYTHING
)
!=
0
)
{
die
(
"Failed to initialize SDL: %s"
,
SDL_GetError
());
}
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_FLAGS
,
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_PROFILE_MASK
,
SDL_GL_CONTEXT_PROFILE_CORE
);
SDL_GL_SetAttribute
(
SDL_GL_DOUBLEBUFFER
,
1
);
Vec2
wsize
=
Vec2
(
1280
,
720
);
window
=
SDL_CreateWindow
(
"Scotty3D"
,
SDL_WINDOWPOS_UNDEFINED
,
SDL_WINDOWPOS_UNDEFINED
,
(
int
)
wsize
.
x
,
(
int
)
wsize
.
y
,
SDL_WINDOW_OPENGL
|
SDL_WINDOW_RESIZABLE
|
SDL_WINDOW_ALLOW_HIGHDPI
);
if
(
!
window
)
{
die
(
"Failed to create window: %s"
,
SDL_GetError
());
}
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
4
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
5
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
info
(
"Failed to create OpenGL 4.5 context, trying 4.1 (%s)"
,
SDL_GetError
());
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
4
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
1
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
warn
(
"Failed to create OpenGL 4.1 context, trying 3.3 (%s)"
,
SDL_GetError
());
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
3
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
3
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
die
(
"Failed to create Opengl 3.3 context: %s"
,
SDL_GetError
());
}
}
}
SDL_GL_MakeCurrent
(
window
,
gl_context
);
if
(
SDL_GL_SetSwapInterval
(
-
1
))
SDL_GL_SetSwapInterval
(
1
);
if
(
!
gladLoadGL
())
{
die
(
"Failed to load OpenGL functions."
);
}
keybuf
=
SDL_GetKeyboardState
(
nullptr
);
GL
::
setup
();
ImGui
::
CreateContext
();
ImGui_ImplSDL2_InitForOpenGL
(
window
,
gl_context
);
ImGui_ImplOpenGL3_Init
();
if
(
SDL_Init
(
SDL_INIT_EVERYTHING
)
!=
0
)
{
die
(
"Failed to initialize SDL: %s"
,
SDL_GetError
());
}
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_FLAGS
,
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_PROFILE_MASK
,
SDL_GL_CONTEXT_PROFILE_CORE
);
SDL_GL_SetAttribute
(
SDL_GL_DOUBLEBUFFER
,
1
);
Vec2
wsize
=
Vec2
(
1280
,
720
);
window
=
SDL_CreateWindow
(
"Scotty3D"
,
SDL_WINDOWPOS_UNDEFINED
,
SDL_WINDOWPOS_UNDEFINED
,
(
int
)
wsize
.
x
,
(
int
)
wsize
.
y
,
SDL_WINDOW_OPENGL
|
SDL_WINDOW_RESIZABLE
|
SDL_WINDOW_ALLOW_HIGHDPI
);
if
(
!
window
)
{
die
(
"Failed to create window: %s"
,
SDL_GetError
());
}
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
4
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
5
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
info
(
"Failed to create OpenGL 4.5 context, trying 4.1 (%s)"
,
SDL_GetError
());
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
4
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
1
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
warn
(
"Failed to create OpenGL 4.1 context, trying 3.3 (%s)"
,
SDL_GetError
());
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MAJOR_VERSION
,
3
);
SDL_GL_SetAttribute
(
SDL_GL_CONTEXT_MINOR_VERSION
,
3
);
gl_context
=
SDL_GL_CreateContext
(
window
);
if
(
!
gl_context
)
{
die
(
"Failed to create Opengl 3.3 context: %s"
,
SDL_GetError
());
}
}
}
SDL_GL_MakeCurrent
(
window
,
gl_context
);
if
(
SDL_GL_SetSwapInterval
(
-
1
))
SDL_GL_SetSwapInterval
(
1
);
if
(
!
gladLoadGL
())
{
die
(
"Failed to load OpenGL functions."
);
}
keybuf
=
SDL_GetKeyboardState
(
nullptr
);
GL
::
setup
();
ImGui
::
CreateContext
();
ImGui_ImplSDL2_InitForOpenGL
(
window
,
gl_context
);
ImGui_ImplOpenGL3_Init
();
}
void
Platform
::
set_dpi
()
{
float
dpi
;
int
index
=
SDL_GetWindowDisplayIndex
(
window
);
if
(
index
<
0
)
{
return
;
}
if
(
SDL_GetDisplayDPI
(
index
,
nullptr
,
&
dpi
,
nullptr
))
{
return
;
}
float
scale
=
window_draw
().
x
/
window_size
().
x
;
if
(
prev_dpi
==
dpi
&&
prev_scale
==
scale
)
return
;
ImGuiStyle
style
;
ImGui
::
StyleColorsDark
(
&
style
);
style
.
WindowRounding
=
0.0
f
;
float
dpi
;
int
index
=
SDL_GetWindowDisplayIndex
(
window
);
if
(
index
<
0
)
{
return
;
}
if
(
SDL_GetDisplayDPI
(
index
,
nullptr
,
&
dpi
,
nullptr
))
{
return
;
}
float
scale
=
window_draw
().
x
/
window_size
().
x
;
if
(
prev_dpi
==
dpi
&&
prev_scale
==
scale
)
return
;
ImGuiStyle
style
;
ImGui
::
StyleColorsDark
(
&
style
);
style
.
WindowRounding
=
0.0
f
;
#ifndef __APPLE__
style
.
ScaleAllSizes
(
0.8
f
*
dpi
/
96.0
f
);
#else
style
.
ScaleAllSizes
(
0.8
f
);
style
.
ScaleAllSizes
(
0.8
f
*
dpi
/
96.0
f
);
#else
style
.
ScaleAllSizes
(
0.8
f
);
#endif
ImGui
::
GetStyle
()
=
style
;
ImGui
::
GetStyle
()
=
style
;
ImGuiIO
&
IO
=
ImGui
::
GetIO
();
ImFontConfig
config
;
config
.
FontDataOwnedByAtlas
=
false
;
IO
.
IniFilename
=
nullptr
;
IO
.
Fonts
->
Clear
();
ImGuiIO
&
IO
=
ImGui
::
GetIO
();
ImFontConfig
config
;
config
.
FontDataOwnedByAtlas
=
false
;
IO
.
IniFilename
=
nullptr
;
IO
.
Fonts
->
Clear
();
#ifdef __APPLE__
IO
.
Fonts
->
AddFontFromMemoryTTF
(
font_ttf
,
font_ttf_len
,
14.0
f
*
scale
,
&
config
);
IO
.
FontGlobalScale
=
1.0
f
/
scale
;
#else
IO
.
Fonts
->
AddFontFromMemoryTTF
(
font_ttf
,
font_ttf_len
,
14.0
f
/
96.0
f
*
dpi
,
&
config
);
IO
.
Fonts
->
AddFontFromMemoryTTF
(
font_ttf
,
font_ttf_len
,
14.0
f
*
scale
,
&
config
);
IO
.
FontGlobalScale
=
1.0
f
/
scale
;
#else
IO
.
Fonts
->
AddFontFromMemoryTTF
(
font_ttf
,
font_ttf_len
,
14.0
f
/
96.0
f
*
dpi
,
&
config
);
#endif
IO
.
Fonts
->
Build
();
ImGui_ImplOpenGL3_DestroyDeviceObjects
();
prev_dpi
=
dpi
;
prev_scale
=
scale
;
}
IO
.
Fonts
->
Build
();
ImGui_ImplOpenGL3_DestroyDeviceObjects
();
bool
Platform
::
is_down
(
SDL_Scancode
key
)
{
return
keybuf
[
key
]
;
prev_dpi
=
dpi
;
prev_scale
=
scale
;
}
bool
Platform
::
is_down
(
SDL_Scancode
key
)
{
return
keybuf
[
key
];
}
void
Platform
::
platform_shutdown
()
{
ImGui_ImplOpenGL3_Shutdown
();
ImGui_ImplSDL2_Shutdown
();
ImGui
::
DestroyContext
();
ImGui_ImplOpenGL3_Shutdown
();
ImGui_ImplSDL2_Shutdown
();
ImGui
::
DestroyContext
();
GL
::
shutdown
();
SDL_GL_DeleteContext
(
gl_context
);
SDL_DestroyWindow
(
window
);
window
=
nullptr
;
gl_context
=
nullptr
;
SDL_Quit
();
GL
::
shutdown
();
SDL_GL_DeleteContext
(
gl_context
);
SDL_DestroyWindow
(
window
);
window
=
nullptr
;
gl_context
=
nullptr
;
SDL_Quit
();
}
void
Platform
::
complete_frame
()
{
GL
::
Framebuffer
::
bind_screen
();
ImGui
::
Render
();
ImGui_ImplOpenGL3_RenderDrawData
(
ImGui
::
GetDrawData
());
SDL_GL_SwapWindow
(
window
);
GL
::
Framebuffer
::
bind_screen
();
ImGui
::
Render
();
ImGui_ImplOpenGL3_RenderDrawData
(
ImGui
::
GetDrawData
());
SDL_GL_SwapWindow
(
window
);
}
void
Platform
::
begin_frame
()
{
ImGui_ImplOpenGL3_NewFrame
();
ImGui_ImplSDL2_NewFrame
(
window
);
ImGui
::
NewFrame
();
ImGui_ImplOpenGL3_NewFrame
();
ImGui_ImplSDL2_NewFrame
(
window
);
ImGui
::
NewFrame
();
}
void
Platform
::
strcpy
(
char
*
dst
,
const
char
*
src
,
size_t
limit
)
{
void
Platform
::
strcpy
(
char
*
dst
,
const
char
*
src
,
size_t
limit
)
{
#ifdef _WIN32
strncpy_s
(
dst
,
limit
,
src
,
limit
-
1
);
#else
strncpy
(
dst
,
src
,
limit
-
1
);
dst
[
limit
-
1
]
=
'\0'
;
strncpy_s
(
dst
,
limit
,
src
,
limit
-
1
);
#else
strncpy
(
dst
,
src
,
limit
-
1
);
dst
[
limit
-
1
]
=
'\0'
;
#endif
}
void
Platform
::
loop
(
App
&
app
)
{
void
Platform
::
loop
(
App
&
app
)
{
bool
running
=
true
;
while
(
running
)
{
bool
running
=
true
;
while
(
running
)
{
set_dpi
();
SDL_Event
e
;
while
(
SDL_PollEvent
(
&
e
))
{
set_dpi
();
SDL_Event
e
;
while
(
SDL_PollEvent
(
&
e
))
{
ImGui_ImplSDL2_ProcessEvent
(
&
e
);
ImGui_ImplSDL2_ProcessEvent
(
&
e
);
switch
(
e
.
type
)
{
case
SDL_QUIT
:
{
running
=
false
;
}
break
;
}
switch
(
e
.
type
)
{
case
SDL_QUIT
:
{
running
=
false
;
}
break
;
}
app
.
event
(
e
);
}
app
.
event
(
e
);
}
begin_frame
();
app
.
render
();
complete_frame
();
}
begin_frame
();
app
.
render
();
complete_frame
();
}
}
Vec2
Platform
::
scale
(
Vec2
pt
)
{
return
pt
*
window_draw
()
/
window_size
();
}
Vec2
Platform
::
scale
(
Vec2
pt
)
{
return
pt
*
window_draw
()
/
window_size
();
}
Vec2
Platform
::
window_size
()
{
int
w
,
h
;
SDL_GetWindowSize
(
window
,
&
w
,
&
h
);
return
Vec2
((
float
)
w
,
(
float
)
h
);
int
w
,
h
;
SDL_GetWindowSize
(
window
,
&
w
,
&
h
);
return
Vec2
((
float
)
w
,
(
float
)
h
);
}
Vec2
Platform
::
window_draw
()
{
int
w
,
h
;
SDL_GL_GetDrawableSize
(
window
,
&
w
,
&
h
);
return
Vec2
((
float
)
w
,
(
float
)
h
);
int
w
,
h
;
SDL_GL_GetDrawableSize
(
window
,
&
w
,
&
h
);
return
Vec2
((
float
)
w
,
(
float
)
h
);
}
void
Platform
::
grab_mouse
()
{
SDL_SetWindowGrab
(
window
,
SDL_TRUE
);
}
void
Platform
::
grab_mouse
()
{
SDL_SetWindowGrab
(
window
,
SDL_TRUE
);
}
void
Platform
::
ungrab_mouse
()
{
SDL_SetWindowGrab
(
window
,
SDL_FALSE
);
}
void
Platform
::
ungrab_mouse
()
{
SDL_SetWindowGrab
(
window
,
SDL_FALSE
);
}
Vec2
Platform
::
get_mouse
()
{
int
x
,
y
;
SDL_GetMouseState
(
&
x
,
&
y
);
return
Vec2
(
x
,
y
);
int
x
,
y
;
SDL_GetMouseState
(
&
x
,
&
y
);
return
Vec2
(
x
,
y
);
}
void
Platform
::
capture_mouse
()
{
SDL_CaptureMouse
(
SDL_TRUE
);
SDL_SetRelativeMouseMode
(
SDL_TRUE
);
SDL_CaptureMouse
(
SDL_TRUE
);
SDL_SetRelativeMouseMode
(
SDL_TRUE
);
}
void
Platform
::
release_mouse
()
{
SDL_CaptureMouse
(
SDL_FALSE
);
SDL_SetRelativeMouseMode
(
SDL_FALSE
);
SDL_CaptureMouse
(
SDL_FALSE
);
SDL_SetRelativeMouseMode
(
SDL_FALSE
);
}
void
Platform
::
set_mouse
(
Vec2
pos
)
{
SDL_WarpMouseInWindow
(
window
,
(
int
)
pos
.
x
,
(
int
)
pos
.
y
);
}
void
Platform
::
set_mouse
(
Vec2
pos
)
{
SDL_WarpMouseInWindow
(
window
,
(
int
)
pos
.
x
,
(
int
)
pos
.
y
);
}
src/platform/platform.h
View file @
c2535f0f
...
...
@@ -3,43 +3,43 @@
#include <SDL2/SDL.h>
#include "../lib/mathlib.h"
#include "../app.h"
#include "../lib/mathlib.h"
class
Platform
{
public:
Platform
();
~
Platform
();
Platform
();
~
Platform
();
void
loop
(
App
&
app
);
void
loop
(
App
&
app
);
Vec2
window_draw
();
Vec2
window_size
();
Vec2
scale
(
Vec2
pt
);
Vec2
window_draw
();
Vec2
window_size
();
Vec2
scale
(
Vec2
pt
);
void
capture_mouse
();
void
release_mouse
();
void
set_mouse
(
Vec2
pos
);
Vec2
get_mouse
();
void
grab_mouse
();
void
ungrab_mouse
();
bool
is_down
(
SDL_Scancode
key
);
void
capture_mouse
();
void
release_mouse
();
void
set_mouse
(
Vec2
pos
);
Vec2
get_mouse
();
void
grab_mouse
();
void
ungrab_mouse
();
bool
is_down
(
SDL_Scancode
key
);
static
void
remove_console
();
static
int
console_width
();
static
void
strcpy
(
char
*
dest
,
const
char
*
src
,
size_t
limit
);
static
void
remove_console
();
static
int
console_width
();
static
void
strcpy
(
char
*
dest
,
const
char
*
src
,
size_t
limit
);
private:
float
prev_dpi
=
0.0
f
;
float
prev_scale
=
0.0
f
;
void
set_dpi
();
void
platform_init
();
void
platform_shutdown
();
void
begin_frame
();
void
complete_frame
();
SDL_Window
*
window
=
nullptr
;
SDL_GLContext
gl_context
=
nullptr
;
const
Uint8
*
keybuf
=
nullptr
;
float
prev_dpi
=
0.0
f
;
float
prev_scale
=
0.0
f
;
void
set_dpi
();
void
platform_init
();
void
platform_shutdown
();
void
begin_frame
();
void
complete_frame
();
SDL_Window
*
window
=
nullptr
;
SDL_GLContext
gl_context
=
nullptr
;
const
Uint8
*
keybuf
=
nullptr
;
};
src/rays/bsdf.h
View file @
c2535f0f
...
...
@@ -13,128 +13,109 @@ namespace PT {
struct
BSDF_Sample
{
Spectrum
emissive
;
Spectrum
attenuation
;
Vec3
direction
;
float
pdf
;
void
transform
(
const
Mat4
&
T
)
{
direction
=
T
.
rotate
(
direction
);
}
Spectrum
emissive
;
Spectrum
attenuation
;
Vec3
direction
;
float
pdf
;
void
transform
(
const
Mat4
&
T
)
{
direction
=
T
.
rotate
(
direction
);
}
};
struct
BSDF_Lambertian
{
BSDF_Lambertian
(
Spectrum
albedo
)
:
albedo
(
albedo
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
BSDF_Lambertian
(
Spectrum
albedo
)
:
albedo
(
albedo
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
Spectrum
albedo
;
Samplers
::
Hemisphere
::
Uniform
sampler
;
Samplers
::
Hemisphere
::
Uniform
sampler
;
};
struct
BSDF_Mirror
{
BSDF_Mirror
(
Spectrum
reflectance
)
:
reflectance
(
reflectance
)
{}
BSDF_Mirror
(
Spectrum
reflectance
)
:
reflectance
(
reflectance
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
Spectrum
reflectance
;
Spectrum
reflectance
;
};
struct
BSDF_Refract
{
BSDF_Refract
(
Spectrum
transmittance
,
float
ior
)
:
transmittance
(
transmittance
),
index_of_refraction
(
ior
)
{}
BSDF_Refract
(
Spectrum
transmittance
,
float
ior
)
:
transmittance
(
transmittance
),
index_of_refraction
(
ior
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
Spectrum
transmittance
;
float
index_of_refraction
;
Spectrum
transmittance
;
float
index_of_refraction
;
};
struct
BSDF_Glass
{
BSDF_Glass
(
Spectrum
transmittance
,
Spectrum
reflectance
,
float
ior
)
:
transmittance
(
transmittance
),
reflectance
(
reflectance
),
index_of_refraction
(
ior
)
{}
BSDF_Glass
(
Spectrum
transmittance
,
Spectrum
reflectance
,
float
ior
)
:
transmittance
(
transmittance
),
reflectance
(
reflectance
),
index_of_refraction
(
ior
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
Spectrum
transmittance
;
Spectrum
reflectance
;
float
index_of_refraction
;
Spectrum
reflectance
;
float
index_of_refraction
;
};
struct
BSDF_Diffuse
{
BSDF_Diffuse
(
Spectrum
radiance
)
:
radiance
(
radiance
)
{}
BSDF_Diffuse
(
Spectrum
radiance
)
:
radiance
(
radiance
)
{}
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
BSDF_Sample
sample
(
Vec3
out_dir
)
const
;
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
;
Spectrum
radiance
;
Samplers
::
Hemisphere
::
Uniform
sampler
;
Samplers
::
Hemisphere
::
Uniform
sampler
;
};
class
BSDF
{
public:
BSDF
(
BSDF_Lambertian
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Mirror
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Glass
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Diffuse
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Refract
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Lambertian
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Mirror
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Glass
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Diffuse
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
BSDF_Refract
&&
b
)
:
underlying
(
std
::
move
(
b
))
{}
BSDF
(
const
BSDF
&
src
)
=
delete
;
BSDF
&
operator
=
(
const
BSDF
&
src
)
=
delete
;
BSDF
&
operator
=
(
BSDF
&&
src
)
=
default
;
BSDF
(
BSDF
&&
src
)
=
default
;
BSDF
(
const
BSDF
&
src
)
=
delete
;
BSDF
&
operator
=
(
const
BSDF
&
src
)
=
delete
;
BSDF
&
operator
=
(
BSDF
&&
src
)
=
default
;
BSDF
(
BSDF
&&
src
)
=
default
;
BSDF_Sample
sample
(
Vec3
out_dir
)
const
{
return
std
::
visit
(
overloaded
{
[
&
out_dir
](
const
auto
&
b
)
{
return
b
.
sample
(
out_dir
);
}
},
underlying
);
return
std
::
visit
(
overloaded
{[
&
out_dir
](
const
auto
&
b
)
{
return
b
.
sample
(
out_dir
);
}},
underlying
);
}
Spectrum
evaluate
(
Vec3
out_dir
,
Vec3
in_dir
)
const
{
return
std
::
visit
(
overloaded
{
[
&
out_dir
,
&
in_dir
](
const
auto
&
b
)
{
return
b
.
evaluate
(
out_dir
,
in_dir
);
}
},
underlying
);
return
std
::
visit
(
overloaded
{[
&
out_dir
,
&
in_dir
](
const
auto
&
b
)
{
return
b
.
evaluate
(
out_dir
,
in_dir
);
}},
underlying
);
}
bool
is_discrete
()
const
{
return
std
::
visit
(
overloaded
{
[](
const
BSDF_Lambertian
&
)
{
return
false
;
},
[](
const
BSDF_Mirror
&
)
{
return
true
;
},
[](
const
BSDF_Glass
&
)
{
return
true
;
},
[](
const
BSDF_Diffuse
&
)
{
return
false
;
},
[](
const
BSDF_Refract
&
)
{
return
true
;
}
},
underlying
);
}
bool
is_discrete
()
const
{
return
std
::
visit
(
overloaded
{[](
const
BSDF_Lambertian
&
)
{
return
false
;
},
[](
const
BSDF_Mirror
&
)
{
return
true
;
},
[](
const
BSDF_Glass
&
)
{
return
true
;
},
[](
const
BSDF_Diffuse
&
)
{
return
false
;
},
[](
const
BSDF_Refract
&
)
{
return
true
;
}},
underlying
);
}
private:
std
::
variant
<
BSDF_Lambertian
,
BSDF_Mirror
,
BSDF_Glass
,
BSDF_Diffuse
,
BSDF_Refract
>
underlying
;
std
::
variant
<
BSDF_Lambertian
,
BSDF_Mirror
,
BSDF_Glass
,
BSDF_Diffuse
,
BSDF_Refract
>
underlying
;
};
Vec3
reflect
(
Vec3
dir
);
Vec3
refract
(
Vec3
out_dir
,
float
index_of_refraction
,
bool
&
was_internal
);
Vec3
refract
(
Vec3
out_dir
,
float
index_of_refraction
,
bool
&
was_internal
);
}
\ No newline at end of file
}
// namespace PT
src/rays/bvh.h
View file @
c2535f0f
...
...
@@ -8,17 +8,16 @@
namespace
PT
{
template
<
typename
Primitive
>
class
BVH
{
template
<
typename
Primitive
>
class
BVH
{
public:
BVH
()
=
default
;
BVH
(
std
::
vector
<
Primitive
>&&
primitives
,
size_t
max_leaf_size
=
1
);
void
build
(
std
::
vector
<
Primitive
>&&
primitives
,
size_t
max_leaf_size
=
1
);
BVH
(
std
::
vector
<
Primitive
>
&&
primitives
,
size_t
max_leaf_size
=
1
);
void
build
(
std
::
vector
<
Primitive
>
&&
primitives
,
size_t
max_leaf_size
=
1
);
BBox
bbox
()
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
trans
)
const
;
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
trans
)
const
;
std
::
vector
<
Primitive
>
destructure
();
void
clear
();
...
...
@@ -37,11 +36,10 @@ private:
std
::
vector
<
Primitive
>
primitives
;
};
}
}
// namespace PT
#ifdef SCOTTY3D_BUILD_REF
#include "../reference/bvh.cpp"
#else
#include "../student/bvh.cpp"
#endif
src/rays/env_light.h
View file @
c2535f0f
...
...
@@ -13,30 +13,30 @@
namespace
PT
{
struct
Env_Hemisphere
{
Env_Hemisphere
(
Spectrum
r
)
:
radiance
(
r
)
{}
Env_Hemisphere
(
Spectrum
r
)
:
radiance
(
r
)
{}
Light_Sample
sample
()
const
;
Spectrum
sample_direction
(
Vec3
dir
)
const
;
Spectrum
radiance
;
Spectrum
radiance
;
Samplers
::
Hemisphere
::
Uniform
sampler
;
};
struct
Env_Sphere
{
Env_Sphere
(
Spectrum
r
)
:
radiance
(
r
)
{}
Env_Sphere
(
Spectrum
r
)
:
radiance
(
r
)
{}
Light_Sample
sample
()
const
;
Spectrum
sample_direction
(
Vec3
dir
)
const
;
Spectrum
radiance
;
Spectrum
radiance
;
Samplers
::
Sphere
::
Uniform
sampler
;
};
struct
Env_Map
{
Env_Map
(
HDR_Image
&&
img
)
:
image
(
std
::
move
(
img
)),
sampler
(
image
)
{}
Env_Map
(
HDR_Image
&&
img
)
:
image
(
std
::
move
(
img
)),
sampler
(
image
)
{}
Light_Sample
sample
()
const
;
Spectrum
sample_direction
(
Vec3
dir
)
const
;
...
...
@@ -47,49 +47,34 @@ struct Env_Map {
class
Env_Light
{
public:
Env_Light
(
Env_Hemisphere
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
Env_Sphere
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
Env_Map
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
Env_Hemisphere
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
Env_Sphere
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
Env_Map
&&
l
)
:
underlying
(
std
::
move
(
l
))
{}
Env_Light
(
const
Env_Light
&
src
)
=
delete
;
Env_Light
&
operator
=
(
const
Env_Light
&
src
)
=
delete
;
Env_Light
&
operator
=
(
Env_Light
&&
src
)
=
default
;
Env_Light
(
Env_Light
&&
src
)
=
default
;
Env_Light
(
const
Env_Light
&
src
)
=
delete
;
Env_Light
&
operator
=
(
const
Env_Light
&
src
)
=
delete
;
Env_Light
&
operator
=
(
Env_Light
&&
src
)
=
default
;
Env_Light
(
Env_Light
&&
src
)
=
default
;
Light_Sample
sample
(
Vec3
)
const
{
return
std
::
visit
(
overloaded
{
[](
const
Env_Hemisphere
&
h
)
{
return
h
.
sample
();
},
[](
const
Env_Sphere
&
h
)
{
return
h
.
sample
();
},
[](
const
Env_Map
&
h
)
{
return
h
.
sample
();
}
},
underlying
);
return
std
::
visit
(
overloaded
{[](
const
Env_Hemisphere
&
h
)
{
return
h
.
sample
();
},
[](
const
Env_Sphere
&
h
)
{
return
h
.
sample
();
},
[](
const
Env_Map
&
h
)
{
return
h
.
sample
();
}},
underlying
);
}
Spectrum
sample_direction
(
Vec3
dir
)
const
{
return
std
::
visit
(
overloaded
{
[
&
dir
](
const
Env_Hemisphere
&
h
)
{
return
h
.
sample_direction
(
dir
);
},
[
&
dir
](
const
Env_Sphere
&
h
)
{
return
h
.
sample_direction
(
dir
);
},
[
&
dir
](
const
Env_Map
&
h
)
{
return
h
.
sample_direction
(
dir
);
}
},
underlying
);
return
std
::
visit
(
overloaded
{[
&
dir
](
const
Env_Hemisphere
&
h
)
{
return
h
.
sample_direction
(
dir
);
},
[
&
dir
](
const
Env_Sphere
&
h
)
{
return
h
.
sample_direction
(
dir
);
},
[
&
dir
](
const
Env_Map
&
h
)
{
return
h
.
sample_direction
(
dir
);
}},
underlying
);
}
bool
is_discrete
()
const
{
return
false
;
}
bool
is_discrete
()
const
{
return
false
;
}
private:
std
::
variant
<
Env_Hemisphere
,
Env_Sphere
,
Env_Map
>
underlying
;
std
::
variant
<
Env_Hemisphere
,
Env_Sphere
,
Env_Map
>
underlying
;
};
}
\ No newline at end of file
}
// namespace PT
\ No newline at end of file
src/rays/light.cpp
View file @
c2535f0f
...
...
@@ -23,18 +23,19 @@ Light_Sample Point_Light::sample(Vec3 from) const {
Light_Sample
Spot_Light
::
sample
(
Vec3
from
)
const
{
Light_Sample
ret
;
float
angle
=
std
::
atan2
(
Vec2
(
from
.
x
,
from
.
z
).
norm
(),
from
.
y
);
float
angle
=
std
::
atan2
(
Vec2
(
from
.
x
,
from
.
z
).
norm
(),
from
.
y
);
angle
=
std
::
abs
(
Degrees
(
angle
));
ret
.
direction
=
-
from
.
unit
();
ret
.
distance
=
from
.
norm
();
ret
.
pdf
=
1.0
f
;
ret
.
radiance
=
(
1.0
f
-
smoothstep
(
angle_bounds
.
x
/
2.0
f
,
angle_bounds
.
y
/
2.0
f
,
angle
))
*
radiance
;
ret
.
radiance
=
(
1.0
f
-
smoothstep
(
angle_bounds
.
x
/
2.0
f
,
angle_bounds
.
y
/
2.0
f
,
angle
))
*
radiance
;
return
ret
;
}
Light_Sample
Rect_Light
::
sample
(
Vec3
from
)
const
{
Light_Sample
ret
;
Vec2
sample
=
sampler
.
sample
(
ret
.
pdf
);
Vec3
point
(
sample
.
x
-
size
.
x
/
2.0
f
,
0.0
f
,
sample
.
y
-
size
.
y
/
2.0
f
);
Vec3
dir
=
point
-
from
;
...
...
@@ -50,4 +51,4 @@ Light_Sample Rect_Light::sample(Vec3 from) const {
return
ret
;
}
}
}
// namespace PT
src/rays/light.h
View file @
c2535f0f
...
...
@@ -5,8 +5,8 @@
#include "../lib/mathlib.h"
#include "../lib/spectrum.h"
#include "../util/hdr_image.h"
#include "../scene/object.h"
#include "../util/hdr_image.h"
#include "samplers.h"
...
...
@@ -14,122 +14,110 @@ namespace PT {
struct
Light_Sample
{
Spectrum
radiance
;
Vec3
direction
;
float
distance
;
float
pdf
;
Spectrum
radiance
;
Vec3
direction
;
float
distance
;
float
pdf
;
void
transform
(
const
Mat4
&
T
)
{
direction
=
T
.
rotate
(
direction
);
}
void
transform
(
const
Mat4
&
T
)
{
direction
=
T
.
rotate
(
direction
);
}
};
struct
Directional_Light
{
Directional_Light
(
Spectrum
r
)
:
radiance
(
r
),
sampler
(
Vec3
(
0.0
f
,
1.0
f
,
0.0
f
))
{}
Light_Sample
sample
(
Vec3
from
)
const
;
Directional_Light
(
Spectrum
r
)
:
radiance
(
r
),
sampler
(
Vec3
(
0.0
f
,
1.0
f
,
0.0
f
))
{}
Light_Sample
sample
(
Vec3
from
)
const
;
Spectrum
radiance
;
Samplers
::
Direction
sampler
;
Samplers
::
Direction
sampler
;
};
struct
Point_Light
{
Point_Light
(
Spectrum
r
)
:
radiance
(
r
),
sampler
(
Vec3
(
0.0
f
))
{}
Point_Light
(
Spectrum
r
)
:
radiance
(
r
),
sampler
(
Vec3
(
0.0
f
))
{}
Light_Sample
sample
(
Vec3
from
)
const
;
Light_Sample
sample
(
Vec3
from
)
const
;
Spectrum
radiance
;
Samplers
::
Point
sampler
;
Samplers
::
Point
sampler
;
};
struct
Spot_Light
{
Spot_Light
(
Spectrum
r
,
Vec2
a
)
:
radiance
(
r
),
angle_bounds
(
a
),
sampler
(
Vec3
(
0.0
f
))
{}
Spot_Light
(
Spectrum
r
,
Vec2
a
)
:
radiance
(
r
),
angle_bounds
(
a
),
sampler
(
Vec3
(
0.0
f
))
{}
Light_Sample
sample
(
Vec3
from
)
const
;
Light_Sample
sample
(
Vec3
from
)
const
;
Spectrum
radiance
;
Vec2
angle_bounds
;
Samplers
::
Point
sampler
;
Samplers
::
Point
sampler
;
};
struct
Rect_Light
{
Rect_Light
(
Spectrum
r
,
Vec2
s
)
:
radiance
(
r
),
size
(
s
),
sampler
(
size
)
{}
Rect_Light
(
Spectrum
r
,
Vec2
s
)
:
radiance
(
r
),
size
(
s
),
sampler
(
size
)
{}
Light_Sample
sample
(
Vec3
from
)
const
;
Light_Sample
sample
(
Vec3
from
)
const
;
Spectrum
radiance
;
Vec2
size
;
Samplers
::
Rect
::
Uniform
sampler
;
Samplers
::
Rect
::
Uniform
sampler
;
};
class
Light
{
public:
Light
(
Directional_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Point_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Spot_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Rect_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
const
Light
&
src
)
=
delete
;
Light
&
operator
=
(
const
Light
&
src
)
=
delete
;
Light
&
operator
=
(
Light
&&
src
)
=
default
;
Light
(
Light
&&
src
)
=
default
;
Light
(
Directional_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Point_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Spot_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
Rect_Light
&&
l
,
Scene_ID
id
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
underlying
(
std
::
move
(
l
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Light
(
const
Light
&
src
)
=
delete
;
Light
&
operator
=
(
const
Light
&
src
)
=
delete
;
Light
&
operator
=
(
Light
&&
src
)
=
default
;
Light
(
Light
&&
src
)
=
default
;
Light_Sample
sample
(
Vec3
from
)
const
{
if
(
has_trans
)
from
=
itrans
*
from
;
Light_Sample
ret
=
std
::
visit
(
overloaded
{
[
&
from
](
const
auto
&
l
)
{
return
l
.
sample
(
from
);
}
},
underlying
);
if
(
has_trans
)
ret
.
transform
(
trans
);
return
ret
;
if
(
has_trans
)
from
=
itrans
*
from
;
Light_Sample
ret
=
std
::
visit
(
overloaded
{[
&
from
](
const
auto
&
l
)
{
return
l
.
sample
(
from
);
}},
underlying
);
if
(
has_trans
)
ret
.
transform
(
trans
);
return
ret
;
}
bool
is_discrete
()
const
{
return
std
::
visit
(
overloaded
{
[](
const
Directional_Light
&
)
{
return
true
;
},
[](
const
Point_Light
&
)
{
return
true
;
},
[](
const
Spot_Light
&
)
{
return
true
;
},
[](
const
Rect_Light
&
)
{
return
false
;
}
},
underlying
);
}
Scene_ID
id
()
const
{
return
_id
;
}
void
set_trans
(
const
Mat4
&
T
)
{
trans
=
T
;
itrans
=
T
.
inverse
();
has_trans
=
trans
!=
Mat4
::
I
;
}
bool
is_discrete
()
const
{
return
std
::
visit
(
overloaded
{[](
const
Directional_Light
&
)
{
return
true
;
},
[](
const
Point_Light
&
)
{
return
true
;
},
[](
const
Spot_Light
&
)
{
return
true
;
},
[](
const
Rect_Light
&
)
{
return
false
;
}},
underlying
);
}
Scene_ID
id
()
const
{
return
_id
;
}
void
set_trans
(
const
Mat4
&
T
)
{
trans
=
T
;
itrans
=
T
.
inverse
();
has_trans
=
trans
!=
Mat4
::
I
;
}
private:
bool
has_trans
;
Mat4
trans
,
itrans
;
Scene_ID
_id
;
std
::
variant
<
Directional_Light
,
Point_Light
,
Spot_Light
,
Rect_Light
>
underlying
;
bool
has_trans
;
Mat4
trans
,
itrans
;
Scene_ID
_id
;
std
::
variant
<
Directional_Light
,
Point_Light
,
Spot_Light
,
Rect_Light
>
underlying
;
};
}
\ No newline at end of file
}
// namespace PT
src/rays/list.h
View file @
c2535f0f
...
...
@@ -6,36 +6,32 @@
namespace
PT
{
template
<
typename
Primitive
>
class
List
{
template
<
typename
Primitive
>
class
List
{
public:
List
()
{}
List
(
std
::
vector
<
Primitive
>&&
primitives
)
:
prims
(
primitives
)
{}
List
(
std
::
vector
<
Primitive
>
&&
primitives
)
:
prims
(
primitives
)
{}
BBox
bbox
()
const
{
BBox
ret
;
for
(
const
auto
&
p
:
prims
)
{
for
(
const
auto
&
p
:
prims
)
{
ret
.
enclose
(
p
.
bbox
());
}
return
ret
;
}
Trace
hit
(
const
Ray
&
ray
)
const
{
Trace
hit
(
const
Ray
&
ray
)
const
{
Trace
ret
;
for
(
const
auto
&
p
:
prims
)
{
for
(
const
auto
&
p
:
prims
)
{
Trace
test
=
p
.
hit
(
ray
);
ret
=
Trace
::
min
(
ret
,
test
);
}
return
ret
;
}
void
append
(
Primitive
&&
prim
)
{
prims
.
push_back
(
std
::
move
(
prim
));
}
void
append
(
Primitive
&&
prim
)
{
prims
.
push_back
(
std
::
move
(
prim
));
}
private:
std
::
vector
<
Primitive
>
prims
;
};
}
}
// namespace PT
src/rays/object.h
View file @
c2535f0f
#pragma once
#include <variant>
#include "../lib/mathlib.h"
#include "../scene/object.h"
#include <variant>
#include "trace.h"
#include "bvh.h"
#include "list.h"
#include "shapes.h"
#include "trace.h"
#include "tri_mesh.h"
namespace
PT
{
class
Object
{
public:
Object
(
Shape
&&
shape
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
shape
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
Tri_Mesh
&&
tri_mesh
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
tri_mesh
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
List
<
Object
>&&
list
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
list
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
BVH
<
Object
>&&
bvh
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
bvh
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
Shape
&&
shape
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
shape
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
Tri_Mesh
&&
tri_mesh
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
tri_mesh
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
List
<
Object
>
&&
list
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
list
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
BVH
<
Object
>
&&
bvh
,
Scene_ID
id
,
unsigned
int
m
=
0
,
const
Mat4
&
T
=
Mat4
::
I
)
:
trans
(
T
),
itrans
(
T
.
inverse
()),
_id
(
id
),
material
(
m
),
underlying
(
std
::
move
(
bvh
))
{
has_trans
=
trans
!=
Mat4
::
I
;
}
Object
(
const
Object
&
src
)
=
delete
;
Object
&
operator
=
(
const
Object
&
src
)
=
delete
;
Object
&
operator
=
(
Object
&&
src
)
=
default
;
Object
(
Object
&&
src
)
=
default
;
Object
(
const
Object
&
src
)
=
delete
;
Object
&
operator
=
(
const
Object
&
src
)
=
delete
;
Object
&
operator
=
(
Object
&&
src
)
=
default
;
Object
(
Object
&&
src
)
=
default
;
BBox
bbox
()
const
{
BBox
box
=
std
::
visit
(
overloaded
{
[](
const
auto
&
o
)
{
return
o
.
bbox
();
}
},
underlying
);
if
(
has_trans
)
box
.
transform
(
trans
);
return
box
;
}
BBox
bbox
()
const
{
BBox
box
=
std
::
visit
(
overloaded
{[](
const
auto
&
o
)
{
return
o
.
bbox
();
}},
underlying
);
if
(
has_trans
)
box
.
transform
(
trans
);
return
box
;
}
Trace
hit
(
Ray
ray
)
const
{
if
(
has_trans
)
ray
.
transform
(
itrans
);
Trace
ret
=
std
::
visit
(
overloaded
{
[
&
ray
](
const
auto
&
o
)
{
return
o
.
hit
(
ray
);
}
},
underlying
);
if
(
ret
.
hit
)
{
ret
.
material
=
material
;
if
(
has_trans
)
ret
.
transform
(
trans
,
itrans
.
T
());
}
return
ret
;
}
Trace
hit
(
Ray
ray
)
const
{
if
(
has_trans
)
ray
.
transform
(
itrans
);
Trace
ret
=
std
::
visit
(
overloaded
{[
&
ray
](
const
auto
&
o
)
{
return
o
.
hit
(
ray
);
}},
underlying
);
if
(
ret
.
hit
)
{
ret
.
material
=
material
;
if
(
has_trans
)
ret
.
transform
(
trans
,
itrans
.
T
());
}
return
ret
;
}
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
vtrans
)
const
{
Mat4
next
=
has_trans
?
vtrans
*
trans
:
vtrans
;
return
std
::
visit
(
overloaded
{
[
&
](
const
BVH
<
Object
>&
bvh
)
{
return
bvh
.
visualize
(
lines
,
active
,
level
,
next
);
},
[
&
](
const
Tri_Mesh
&
mesh
)
{
return
mesh
.
visualize
(
lines
,
active
,
level
,
next
);
},
[](
const
auto
&
)
{
return
size_t
(
0
);
}
},
underlying
);
}
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
vtrans
)
const
{
Mat4
next
=
has_trans
?
vtrans
*
trans
:
vtrans
;
return
std
::
visit
(
overloaded
{
[
&
](
const
BVH
<
Object
>
&
bvh
)
{
return
bvh
.
visualize
(
lines
,
active
,
level
,
next
);
},
[
&
](
const
Tri_Mesh
&
mesh
)
{
return
mesh
.
visualize
(
lines
,
active
,
level
,
next
);
},
[](
const
auto
&
)
{
return
size_t
(
0
);
}},
underlying
);
}
Scene_ID
id
()
const
{
return
_id
;
}
void
set_trans
(
const
Mat4
&
T
)
{
trans
=
T
;
itrans
=
T
.
inverse
();
has_trans
=
trans
!=
Mat4
::
I
;
}
Scene_ID
id
()
const
{
return
_id
;
}
void
set_trans
(
const
Mat4
&
T
)
{
trans
=
T
;
itrans
=
T
.
inverse
();
has_trans
=
trans
!=
Mat4
::
I
;
}
private:
bool
has_trans
;
Mat4
trans
,
itrans
;
unsigned
int
material
;
Scene_ID
_id
;
std
::
variant
<
Tri_Mesh
,
Shape
,
BVH
<
Object
>
,
List
<
Object
>>
underlying
;
bool
has_trans
;
Mat4
trans
,
itrans
;
unsigned
int
material
;
Scene_ID
_id
;
std
::
variant
<
Tri_Mesh
,
Shape
,
BVH
<
Object
>
,
List
<
Object
>>
underlying
;
};
}
\ No newline at end of file
}
// namespace PT
\ No newline at end of file
src/rays/pathtracer.cpp
View file @
c2535f0f
#include "pathtracer.h"
#include "../gui/render.h"
#include "../geometry/util.h"
#include "../gui/render.h"
#include <SDL2/SDL.h>
#include <thread>
namespace
PT
{
Pathtracer
::
Pathtracer
(
Gui
::
Widget_Render
&
gui
,
Vec2
screen_dim
)
:
thread_pool
(
std
::
thread
::
hardware_concurrency
()),
gui
(
gui
),
camera
(
screen_dim
)
{
Pathtracer
::
Pathtracer
(
Gui
::
Widget_Render
&
gui
,
Vec2
screen_dim
)
:
thread_pool
(
std
::
thread
::
hardware_concurrency
()),
gui
(
gui
),
camera
(
screen_dim
)
{
accumulator_samples
=
0
;
total_epochs
=
0
;
completed_epochs
=
0
;
...
...
@@ -20,73 +18,76 @@ Pathtracer::Pathtracer(Gui::Widget_Render& gui, Vec2 screen_dim) :
n_area_samples
=
0
;
}
Pathtracer
::~
Pathtracer
()
{
thread_pool
.
stop
();
}
Pathtracer
::~
Pathtracer
()
{
thread_pool
.
stop
();
}
void
Pathtracer
::
refit_scene
(
Scene
&
layout_scene
)
{
void
Pathtracer
::
refit_scene
(
Scene
&
layout_scene
)
{
std
::
unordered_map
<
Scene_ID
,
Object
>
obj_map
;
std
::
vector
<
Object
>
objs
=
scene
.
destructure
();
for
(
auto
&
o
:
objs
)
obj_map
.
insert
({
o
.
id
(),
std
::
move
(
o
)});
for
(
auto
&
o
:
objs
)
obj_map
.
insert
({
o
.
id
(),
std
::
move
(
o
)});
std
::
set
<
Scene_ID
>
light_ids
;
for
(
auto
&
l
:
lights
)
light_ids
.
insert
(
l
.
id
());
for
(
auto
&
l
:
lights
)
light_ids
.
insert
(
l
.
id
());
layout_scene
.
for_items
([
&
](
const
Scene_Item
&
item
)
{
layout_scene
.
for_items
([
&
](
const
Scene_Item
&
item
)
{
auto
entry
=
obj_map
.
find
(
item
.
id
());
if
(
entry
!=
obj_map
.
end
())
{
if
(
entry
!=
obj_map
.
end
())
{
entry
->
second
.
set_trans
(
item
.
pose
().
transform
());
if
(
light_ids
.
count
(
entry
->
first
))
{
if
(
light_ids
.
count
(
entry
->
first
))
{
obj_map
.
erase
(
entry
);
}
}
});
objs
.
clear
();
for
(
auto
&
o
:
obj_map
)
objs
.
push_back
(
std
::
move
(
o
.
second
));
for
(
auto
&
o
:
obj_map
)
objs
.
push_back
(
std
::
move
(
o
.
second
));
build_lights
(
layout_scene
,
objs
);
scene
.
build
(
std
::
move
(
objs
));
}
void
Pathtracer
::
build_lights
(
Scene
&
layout_scene
,
std
::
vector
<
Object
>
&
objs
)
{
void
Pathtracer
::
build_lights
(
Scene
&
layout_scene
,
std
::
vector
<
Object
>
&
objs
)
{
lights
.
clear
();
env_light
.
reset
();
layout_scene
.
for_items
([
&
,
this
](
const
Scene_Item
&
item
)
{
if
(
item
.
is
<
Scene_Light
>
())
{
const
Scene_Light
&
light
=
item
.
get
<
Scene_Light
>
();
layout_scene
.
for_items
([
&
,
this
](
const
Scene_Item
&
item
)
{
if
(
item
.
is
<
Scene_Light
>
())
{
const
Scene_Light
&
light
=
item
.
get
<
Scene_Light
>
();
Spectrum
r
=
light
.
radiance
();
switch
(
light
.
opt
.
type
)
{
case
Light_Type
::
directional
:
{
switch
(
light
.
opt
.
type
)
{
case
Light_Type
::
directional
:
{
lights
.
push_back
(
Light
(
Directional_Light
(
r
),
light
.
id
(),
light
.
pose
.
transform
()));
}
break
;
case
Light_Type
::
sphere
:
{
if
(
light
.
opt
.
has_emissive_map
)
{
case
Light_Type
::
sphere
:
{
if
(
light
.
opt
.
has_emissive_map
)
{
env_light
=
Env_Light
(
Env_Map
(
light
.
emissive_copy
()));
}
else
{
env_light
=
Env_Light
(
Env_Sphere
(
r
));
}
}
break
;
case
Light_Type
::
hemisphere
:
{
case
Light_Type
::
hemisphere
:
{
env_light
=
Env_Light
(
Env_Hemisphere
(
r
));
}
break
;
case
Light_Type
::
point
:
{
case
Light_Type
::
point
:
{
lights
.
push_back
(
Light
(
Point_Light
(
r
),
light
.
id
(),
light
.
pose
.
transform
()));
}
break
;
case
Light_Type
::
spot
:
{
lights
.
push_back
(
Light
(
Spot_Light
(
r
,
light
.
opt
.
angle_bounds
),
light
.
id
(),
light
.
pose
.
transform
()));
case
Light_Type
::
spot
:
{
lights
.
push_back
(
Light
(
Spot_Light
(
r
,
light
.
opt
.
angle_bounds
),
light
.
id
(),
light
.
pose
.
transform
()));
}
break
;
case
Light_Type
::
rectangle
:
{
lights
.
push_back
(
Light
(
Rect_Light
(
r
,
light
.
opt
.
size
),
light
.
id
(),
light
.
pose
.
transform
()));
case
Light_Type
::
rectangle
:
{
lights
.
push_back
(
Light
(
Rect_Light
(
r
,
light
.
opt
.
size
),
light
.
id
(),
light
.
pose
.
transform
()));
unsigned
int
idx
=
0
;
auto
entry
=
mat_cache
.
find
(
light
.
id
());
if
(
entry
!=
mat_cache
.
end
())
{
if
(
entry
!=
mat_cache
.
end
())
{
idx
=
(
unsigned
int
)
entry
->
second
;
materials
[
entry
->
second
]
=
BSDF
(
BSDF_Diffuse
(
r
));
}
else
{
...
...
@@ -94,43 +95,45 @@ void Pathtracer::build_lights(Scene& layout_scene, std::vector<Object>& objs) {
mat_cache
[
light
.
id
()]
=
materials
.
size
();
materials
.
push_back
(
BSDF
(
BSDF_Diffuse
(
r
)));
}
objs
.
push_back
(
Object
(
std
::
move
(
Util
::
quad_mesh
(
light
.
opt
.
size
.
x
,
light
.
opt
.
size
.
y
)),
light
.
id
(),
idx
,
light
.
pose
.
transform
()));
objs
.
push_back
(
Object
(
std
::
move
(
Util
::
quad_mesh
(
light
.
opt
.
size
.
x
,
light
.
opt
.
size
.
y
)),
light
.
id
(),
idx
,
light
.
pose
.
transform
()));
}
break
;
default:
return
;
default:
return
;
}
}
});
}
void
Pathtracer
::
build_scene
(
Scene
&
layout_scene
)
{
void
Pathtracer
::
build_scene
(
Scene
&
layout_scene
)
{
// It would be nice to let the interface be usable here (as with
// the path-tracing part), but this would cause too much hassle with
// editing the scene while building BVHs from it.
// This could be worked around by first copying all the mesh data
// and then building the BVHs, but I don't think it's that big
// and then building the BVHs, but I don't think it's that big
// of a deal, as BVH building should take at most a few seconds
// even with many big meshes.
// We could also do instancing instead of duplicating the bvh
// for big meshes, but that's something to add in the future
// Yeah this could just be a list of futures but future wanted a
// Yeah this could just be a list of futures but future wanted a
// default constructor for Object so whatever
std
::
mutex
obj_mut
;
std
::
vector
<
Object
>
obj_list
;
materials
.
clear
();
mat_cache
.
clear
();
layout_scene
.
for_items
([
&
,
this
](
Scene_Item
&
item
)
{
if
(
item
.
is
<
Scene_Object
>
())
{
Scene_Object
&
obj
=
item
.
get
<
Scene_Object
>
();
layout_scene
.
for_items
([
&
,
this
](
Scene_Item
&
item
)
{
if
(
item
.
is
<
Scene_Object
>
())
{
Scene_Object
&
obj
=
item
.
get
<
Scene_Object
>
();
unsigned
int
idx
=
(
unsigned
int
)
materials
.
size
();
const
Material
::
Options
&
opt
=
obj
.
material
.
opt
;
const
Material
::
Options
&
opt
=
obj
.
material
.
opt
;
switch
(
opt
.
type
)
{
switch
(
opt
.
type
)
{
case
Material_Type
::
lambertian
:
{
materials
.
push_back
(
BSDF
(
BSDF_Lambertian
(
opt
.
albedo
)));
}
break
;
...
...
@@ -146,19 +149,21 @@ void Pathtracer::build_scene(Scene& layout_scene) {
case
Material_Type
::
diffuse_light
:
{
materials
.
push_back
(
BSDF
(
BSDF_Diffuse
(
obj
.
material
.
emissive
())));
}
break
;
default:
return
;
default:
return
;
}
thread_pool
.
enqueue
([
&
,
idx
]()
{
if
(
obj
.
is_shape
())
{
if
(
obj
.
is_shape
())
{
Shape
shape
(
obj
.
opt
.
shape
);
std
::
lock_guard
<
std
::
mutex
>
lock
(
obj_mut
);
obj_list
.
push_back
(
Object
(
std
::
move
(
shape
),
obj
.
id
(),
idx
,
obj
.
pose
.
transform
()));
obj_list
.
push_back
(
Object
(
std
::
move
(
shape
),
obj
.
id
(),
idx
,
obj
.
pose
.
transform
()));
}
else
{
Tri_Mesh
mesh
(
obj
.
posed_mesh
());
std
::
lock_guard
<
std
::
mutex
>
lock
(
obj_mut
);
obj_list
.
push_back
(
Object
(
std
::
move
(
mesh
),
obj
.
id
(),
idx
,
obj
.
pose
.
transform
()));
obj_list
.
push_back
(
Object
(
std
::
move
(
mesh
),
obj
.
id
(),
idx
,
obj
.
pose
.
transform
()));
}
});
}
...
...
@@ -179,19 +184,18 @@ void Pathtracer::set_sizes(size_t w, size_t h, size_t samples, size_t area_sampl
accumulator
.
resize
(
out_w
,
out_h
);
}
void
Pathtracer
::
log_ray
(
const
Ray
&
ray
,
float
t
,
Spectrum
color
)
{
gui
.
log_ray
(
ray
,
t
,
color
);
}
void
Pathtracer
::
log_ray
(
const
Ray
&
ray
,
float
t
,
Spectrum
color
)
{
gui
.
log_ray
(
ray
,
t
,
color
);
}
void
Pathtracer
::
accumulate
(
const
HDR_Image
&
sample
)
{
void
Pathtracer
::
accumulate
(
const
HDR_Image
&
sample
)
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
accumulator_mut
);
accumulator_samples
++
;
for
(
size_t
j
=
0
;
j
<
out_h
;
j
++
)
{
for
(
size_t
i
=
0
;
i
<
out_w
;
i
++
)
{
Spectrum
&
s
=
accumulator
.
at
(
i
,
j
);
s
+=
(
sample
.
at
(
i
,
j
)
-
s
)
*
(
1.0
f
/
accumulator_samples
);
for
(
size_t
j
=
0
;
j
<
out_h
;
j
++
)
{
for
(
size_t
i
=
0
;
i
<
out_w
;
i
++
)
{
Spectrum
&
s
=
accumulator
.
at
(
i
,
j
);
const
Spectrum
&
n
=
sample
.
at
(
i
,
j
);
s
+=
(
n
-
s
)
*
(
1.0
f
/
accumulator_samples
);
}
}
}
...
...
@@ -199,12 +203,14 @@ void Pathtracer::accumulate(const HDR_Image& sample) {
void
Pathtracer
::
do_trace
(
size_t
samples
)
{
HDR_Image
sample
(
out_w
,
out_h
);
for
(
size_t
j
=
0
;
j
<
out_h
;
j
++
)
{
for
(
size_t
i
=
0
;
i
<
out_w
;
i
++
)
{
for
(
size_t
j
=
0
;
j
<
out_h
;
j
++
)
{
for
(
size_t
i
=
0
;
i
<
out_w
;
i
++
)
{
size_t
sampled
=
0
;
for
(
size_t
s
=
0
;
s
<
samples
;
s
++
)
{
for
(
size_t
s
=
0
;
s
<
samples
;
s
++
)
{
Spectrum
p
=
trace_pixel
(
i
,
j
);
if
(
p
.
valid
())
{
if
(
p
.
valid
())
{
sample
.
at
(
i
,
j
)
+=
p
;
sampled
++
;
}
...
...
@@ -215,11 +221,9 @@ void Pathtracer::do_trace(size_t samples) {
accumulate
(
sample
);
}
bool
Pathtracer
::
in_progress
()
const
{
return
completed_epochs
.
load
()
<
total_epochs
.
load
();
}
bool
Pathtracer
::
in_progress
()
const
{
return
completed_epochs
.
load
()
<
total_epochs
.
load
();
}
std
::
pair
<
float
,
float
>
Pathtracer
::
completion_time
()
const
{
std
::
pair
<
float
,
float
>
Pathtracer
::
completion_time
()
const
{
double
freq
=
(
double
)
SDL_GetPerformanceFrequency
();
return
{(
float
)(
build_time
/
freq
),
(
float
)(
render_time
/
freq
)};
}
...
...
@@ -228,11 +232,11 @@ float Pathtracer::progress() const {
return
(
float
)
completed_epochs
.
load
()
/
(
float
)
total_epochs
.
load
();
}
size_t
Pathtracer
::
visualize_bvh
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
depth
)
{
size_t
Pathtracer
::
visualize_bvh
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
depth
)
{
return
scene
.
visualize
(
lines
,
active
,
depth
,
Mat4
::
I
);
}
void
Pathtracer
::
begin_render
(
Scene
&
layout_scene
,
const
Camera
&
cam
,
bool
refit
)
{
void
Pathtracer
::
begin_render
(
Scene
&
layout_scene
,
const
Camera
&
cam
,
bool
refit
)
{
size_t
n_threads
=
std
::
thread
::
hardware_concurrency
();
size_t
samples_per_epoch
=
std
::
max
(
size_t
(
1
),
n_samples
/
(
n_threads
*
10
));
...
...
@@ -243,19 +247,21 @@ void Pathtracer::begin_render(Scene& layout_scene, const Camera& cam, bool refit
total_epochs
=
n_samples
/
samples_per_epoch
+
!!
(
n_samples
%
samples_per_epoch
);
build_time
=
SDL_GetPerformanceCounter
();
if
(
refit
)
refit_scene
(
layout_scene
);
else
build_scene
(
layout_scene
);
if
(
refit
)
refit_scene
(
layout_scene
);
else
build_scene
(
layout_scene
);
render_time
=
SDL_GetPerformanceCounter
();
build_time
=
render_time
-
build_time
;
camera
=
cam
;
for
(
size_t
s
=
0
;
s
<
n_samples
;
s
+=
samples_per_epoch
)
{
for
(
size_t
s
=
0
;
s
<
n_samples
;
s
+=
samples_per_epoch
)
{
size_t
samples
=
(
s
+
samples_per_epoch
)
>
n_samples
?
n_samples
-
s
:
samples_per_epoch
;
thread_pool
.
enqueue
([
samples
,
this
]()
{
do_trace
(
samples
);
completed_epochs
++
;
if
(
completed_epochs
.
load
()
==
total_epochs
.
load
())
{
if
(
completed_epochs
.
load
()
==
total_epochs
.
load
())
{
Uint64
done
=
SDL_GetPerformanceCounter
();
render_time
=
done
-
render_time
;
}
...
...
@@ -272,13 +278,11 @@ void Pathtracer::cancel() {
total_epochs
=
0
;
}
const
HDR_Image
&
Pathtracer
::
get_output
()
{
return
accumulator
;
}
const
HDR_Image
&
Pathtracer
::
get_output
()
{
return
accumulator
;
}
const
GL
::
Tex2D
&
Pathtracer
::
get_output_texture
(
float
exposure
)
{
const
GL
::
Tex2D
&
Pathtracer
::
get_output_texture
(
float
exposure
)
{
std
::
lock_guard
<
std
::
mutex
>
lock
(
accumulator_mut
);
return
accumulator
.
get_texture
(
exposure
);
}
}
}
// namespace PT
src/rays/pathtracer.h
View file @
c2535f0f
#pragma once
#pragma once
#include <mutex>
#include <atomic>
#include <mutex>
#include <unordered_map>
#include "../lib/mathlib.h"
#include "../scene/scene.h"
#include "../util/hdr_image.h"
#include "../util/thread_pool.h"
#include "../scene/scene.h"
#include "bsdf.h"
#include "env_light.h"
#include "light.h"
#include "object.h"
#include "bsdf.h"
namespace
Gui
{
class
Widget_Render
;
}
namespace
Gui
{
class
Widget_Render
;
}
namespace
PT
{
class
Pathtracer
{
public:
Pathtracer
(
Gui
::
Widget_Render
&
gui
,
Vec2
screen_dim
);
Pathtracer
(
Gui
::
Widget_Render
&
gui
,
Vec2
screen_dim
);
~
Pathtracer
();
void
set_sizes
(
size_t
w
,
size_t
h
,
size_t
pixel_samples
,
size_t
area_samples
,
size_t
depth
);
const
HDR_Image
&
get_output
();
const
GL
::
Tex2D
&
get_output_texture
(
float
exposure
);
size_t
visualize_bvh
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
);
const
HDR_Image
&
get_output
();
const
GL
::
Tex2D
&
get_output_texture
(
float
exposure
);
size_t
visualize_bvh
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
);
void
begin_render
(
Scene
&
scene
,
const
Camera
&
camera
,
bool
refit
=
false
);
void
begin_render
(
Scene
&
scene
,
const
Camera
&
camera
,
bool
refit
=
false
);
void
cancel
();
bool
in_progress
()
const
;
float
progress
()
const
;
std
::
pair
<
float
,
float
>
completion_time
()
const
;
bool
in_progress
()
const
;
float
progress
()
const
;
std
::
pair
<
float
,
float
>
completion_time
()
const
;
private:
// Internal
void
build_scene
(
Scene
&
scene
);
void
refit_scene
(
Scene
&
scene
);
void
build_lights
(
Scene
&
scene
,
std
::
vector
<
Object
>
&
objs
);
void
build_scene
(
Scene
&
scene
);
void
refit_scene
(
Scene
&
scene
);
void
build_lights
(
Scene
&
scene
,
std
::
vector
<
Object
>
&
objs
);
void
do_trace
(
size_t
samples
);
void
accumulate
(
const
HDR_Image
&
sample
);
void
accumulate
(
const
HDR_Image
&
sample
);
bool
tonemap
();
Gui
::
Widget_Render
&
gui
;
Gui
::
Widget_Render
&
gui
;
unsigned
long
long
render_time
,
build_time
;
Thread_Pool
thread_pool
;
HDR_Image
accumulator
;
std
::
mutex
accumulator_mut
;
std
::
atomic
<
size_t
>
accumulator_samples
,
total_epochs
,
completed_epochs
;
/// Relevant to student
Spectrum
trace_pixel
(
size_t
x
,
size_t
y
);
Spectrum
trace_ray
(
const
Ray
&
ray
);
void
log_ray
(
const
Ray
&
ray
,
float
t
,
Spectrum
color
=
Spectrum
{
1.0
f
});
Spectrum
trace_ray
(
const
Ray
&
ray
);
void
log_ray
(
const
Ray
&
ray
,
float
t
,
Spectrum
color
=
Spectrum
{
1.0
f
});
BVH
<
Object
>
scene
;
std
::
vector
<
Light
>
lights
;
...
...
@@ -68,4 +70,4 @@ private:
size_t
out_w
,
out_h
,
n_samples
,
n_area_samples
,
max_depth
;
};
}
}
// namespace PT
src/rays/samplers.h
View file @
c2535f0f
...
...
@@ -6,64 +6,66 @@
namespace
Samplers
{
// These samplers are discrete. Note they output a probability _mass_ function
struct
Point
{
Point
(
Vec3
point
)
:
point
(
point
)
{}
Vec3
sample
(
float
&
pmf
)
const
;
Vec3
point
;
};
struct
Two_Points
{
Two_Points
(
Vec3
p1
,
Vec3
p2
,
float
p_p1
)
:
p1
(
p1
),
p2
(
p2
),
prob
(
p_p1
)
{}
Vec3
sample
(
float
&
pmf
)
const
;
Vec3
p1
,
p2
;
float
prob
;
};
using
Direction
=
Point
;
using
Two_Directions
=
Two_Points
;
// These are continuous. Note they output a probabilty _density_ function
namespace
Rect
{
struct
Uniform
{
Uniform
(
Vec2
size
=
Vec2
(
1.0
f
))
:
size
(
size
)
{}
Vec2
sample
(
float
&
pdf
)
const
;
Vec2
size
;
};
}
namespace
Hemisphere
{
struct
Uniform
{
Uniform
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
};
struct
Cosine
{
Cosine
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
};
}
namespace
Sphere
{
struct
Uniform
{
Uniform
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
Hemisphere
::
Uniform
hemi
;
};
struct
Image
{
Image
(
const
HDR_Image
&
image
);
Vec3
sample
(
float
&
pdf
)
const
;
size_t
w
=
0
,
h
=
0
;
std
::
vector
<
float
>
pdf
,
cdf
;
float
total
=
0.0
f
;
};
};
}
// These samplers are discrete. Note they output a probability _mass_ function
struct
Point
{
Point
(
Vec3
point
)
:
point
(
point
)
{}
Vec3
sample
(
float
&
pmf
)
const
;
Vec3
point
;
};
struct
Two_Points
{
Two_Points
(
Vec3
p1
,
Vec3
p2
,
float
p_p1
)
:
p1
(
p1
),
p2
(
p2
),
prob
(
p_p1
)
{}
Vec3
sample
(
float
&
pmf
)
const
;
Vec3
p1
,
p2
;
float
prob
;
};
using
Direction
=
Point
;
using
Two_Directions
=
Two_Points
;
// These are continuous. Note they output a probabilty _density_ function
namespace
Rect
{
struct
Uniform
{
Uniform
(
Vec2
size
=
Vec2
(
1.0
f
))
:
size
(
size
)
{}
Vec2
sample
(
float
&
pdf
)
const
;
Vec2
size
;
};
}
// namespace Rect
namespace
Hemisphere
{
struct
Uniform
{
Uniform
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
};
struct
Cosine
{
Cosine
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
};
}
// namespace Hemisphere
namespace
Sphere
{
struct
Uniform
{
Uniform
()
=
default
;
Vec3
sample
(
float
&
pdf
)
const
;
Hemisphere
::
Uniform
hemi
;
};
struct
Image
{
Image
(
const
HDR_Image
&
image
);
Vec3
sample
(
float
&
pdf
)
const
;
size_t
w
=
0
,
h
=
0
;
std
::
vector
<
float
>
pdf
,
cdf
;
float
total
=
0.0
f
;
};
}
// namespace Sphere
}
// namespace Samplers
src/rays/shapes.h
View file @
c2535f0f
#pragma once
#include <variant>
#include "../lib/mathlib.h"
#include "trace.h"
#include <variant>
namespace
PT
{
enum
class
Shape_Type
:
int
{
none
,
sphere
,
count
};
extern
const
char
*
Shape_Type_Names
[(
int
)
Shape_Type
::
count
];
enum
class
Shape_Type
:
int
{
none
,
sphere
,
count
};
extern
const
char
*
Shape_Type_Names
[(
int
)
Shape_Type
::
count
];
class
Sphere
{
public:
Sphere
()
=
default
;
Sphere
()
=
default
;
Sphere
(
float
radius
)
:
radius
(
radius
)
{}
BBox
bbox
()
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
float
radius
=
1.0
f
;
bool
operator
!=
(
const
Sphere
&
s
)
const
{
return
radius
!=
s
.
radius
;
}
bool
operator
!=
(
const
Sphere
&
s
)
const
{
return
radius
!=
s
.
radius
;
}
};
class
Shape
{
public:
Shape
()
=
default
;
Shape
(
Sphere
&&
sphere
)
:
underlying
(
std
::
move
(
sphere
))
{}
Shape
(
const
Shape
&
src
)
=
default
;
Shape
&
operator
=
(
const
Shape
&
src
)
=
default
;
Shape
&
operator
=
(
Shape
&&
src
)
=
default
;
Shape
(
Shape
&&
src
)
=
default
;
BBox
bbox
()
const
{
return
std
::
visit
(
overloaded
{
[](
const
auto
&
o
)
{
return
o
.
bbox
();
}
},
underlying
);
}
Trace
hit
(
Ray
ray
)
const
{
return
std
::
visit
(
overloaded
{
[
&
ray
](
const
auto
&
o
)
{
return
o
.
hit
(
ray
);
}
},
underlying
);
}
template
<
typename
T
>
T
&
get
()
{
return
std
::
get
<
T
>
(
underlying
);
Shape
(
Sphere
&&
sphere
)
:
underlying
(
std
::
move
(
sphere
))
{}
Shape
(
const
Shape
&
src
)
=
default
;
Shape
&
operator
=
(
const
Shape
&
src
)
=
default
;
Shape
&
operator
=
(
Shape
&&
src
)
=
default
;
Shape
(
Shape
&&
src
)
=
default
;
BBox
bbox
()
const
{
return
std
::
visit
(
overloaded
{[](
const
auto
&
o
)
{
return
o
.
bbox
();
}},
underlying
);
}
template
<
typename
T
>
const
T
&
get
()
const
{
return
std
::
get
<
T
>
(
underlying
);
Trace
hit
(
Ray
ray
)
const
{
return
std
::
visit
(
overloaded
{[
&
ray
](
const
auto
&
o
)
{
return
o
.
hit
(
ray
);
}},
underlying
);
}
bool
operator
!=
(
const
Shape
&
c
)
const
{
return
underlying
!=
c
.
underlying
;
}
template
<
typename
T
>
T
&
get
()
{
return
std
::
get
<
T
>
(
underlying
);
}
template
<
typename
T
>
const
T
&
get
()
const
{
return
std
::
get
<
T
>
(
underlying
);
}
bool
operator
!=
(
const
Shape
&
c
)
const
{
return
underlying
!=
c
.
underlying
;
}
private:
std
::
variant
<
Sphere
>
underlying
;
std
::
variant
<
Sphere
>
underlying
;
};
}
}
// namespace PT
src/rays/trace.h
View file @
c2535f0f
...
...
@@ -6,26 +6,29 @@
namespace
PT
{
struct
Trace
{
bool
hit
=
false
;
float
time
=
0.0
f
;
Vec3
position
,
normal
;
int
material
=
0
;
static
Trace
min
(
const
Trace
&
l
,
const
Trace
&
r
)
{
if
(
l
.
hit
&&
r
.
hit
)
{
if
(
l
.
time
<
r
.
time
)
return
l
;
bool
hit
=
false
;
float
time
=
0.0
f
;
Vec3
position
,
normal
;
int
material
=
0
;
static
Trace
min
(
const
Trace
&
l
,
const
Trace
&
r
)
{
if
(
l
.
hit
&&
r
.
hit
)
{
if
(
l
.
time
<
r
.
time
)
return
l
;
return
r
;
}
if
(
l
.
hit
)
return
l
;
if
(
r
.
hit
)
return
r
;
if
(
l
.
hit
)
return
l
;
if
(
r
.
hit
)
return
r
;
return
{};
}
void
transform
(
const
Mat4
&
transform
,
const
Mat4
&
norm
)
{
void
transform
(
const
Mat4
&
transform
,
const
Mat4
&
norm
)
{
position
=
transform
*
position
;
normal
=
norm
.
rotate
(
normal
);
}
};
}
}
// namespace PT
src/rays/tri_mesh.h
View file @
c2535f0f
...
...
@@ -4,8 +4,8 @@
#include "../lib/mathlib.h"
#include "../platform/gl.h"
#include "trace.h"
#include "bvh.h"
#include "trace.h"
namespace
PT
{
...
...
@@ -17,33 +17,33 @@ struct Tri_Mesh_Vert {
class
Triangle
{
public:
BBox
bbox
()
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
size_t
visualize
(
GL
::
Lines
&
,
GL
::
Lines
&
,
size_t
,
const
Mat4
&
)
const
{
return
size_t
(
0
);
}
Trace
hit
(
const
Ray
&
ray
)
const
;
size_t
visualize
(
GL
::
Lines
&
,
GL
::
Lines
&
,
size_t
,
const
Mat4
&
)
const
{
return
size_t
(
0
);
}
private:
Triangle
(
Tri_Mesh_Vert
*
verts
,
unsigned
int
v0
,
unsigned
int
v1
,
unsigned
int
v2
);
Triangle
(
Tri_Mesh_Vert
*
verts
,
unsigned
int
v0
,
unsigned
int
v1
,
unsigned
int
v2
);
unsigned
int
v0
,
v1
,
v2
;
Tri_Mesh_Vert
*
vertex_list
;
Tri_Mesh_Vert
*
vertex_list
;
friend
class
Tri_Mesh
;
};
class
Tri_Mesh
{
public:
Tri_Mesh
()
=
default
;
Tri_Mesh
(
const
GL
::
Mesh
&
mesh
);
Tri_Mesh
(
const
GL
::
Mesh
&
mesh
);
BBox
bbox
()
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
Trace
hit
(
const
Ray
&
ray
)
const
;
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
trans
)
const
;
size_t
visualize
(
GL
::
Lines
&
lines
,
GL
::
Lines
&
active
,
size_t
level
,
const
Mat4
&
trans
)
const
;
void
build
(
const
GL
::
Mesh
&
mesh
);
void
build
(
const
GL
::
Mesh
&
mesh
);
private:
std
::
vector
<
Tri_Mesh_Vert
>
verts
;
BVH
<
Triangle
>
triangles
;
};
}
}
// namespace PT
src/scene/light.cpp
View file @
c2535f0f
...
...
@@ -6,149 +6,133 @@
#include <sstream>
const
char
*
Light_Type_Names
[(
int
)
Light_Type
::
count
]
=
{
"Directional"
,
"Sphere"
,
"Hemisphere"
,
"Point"
,
"Spot"
,
"Rectangle"
};
Scene_Light
::
Scene_Light
(
Light_Type
type
,
Scene_ID
id
,
Pose
p
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
_lines
(
1.0
f
)
{
opt
.
type
=
type
;
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s Light %d"
,
Light_Type_Names
[(
int
)
type
],
id
);
}
const
char
*
Light_Type_Names
[(
int
)
Light_Type
::
count
]
=
{
"Directional"
,
"Sphere"
,
"Hemisphere"
,
"Point"
,
"Spot"
,
"Rectangle"
};
Scene_Light
::
Scene_Light
(
Light_Type
type
,
Scene_ID
id
,
Pose
p
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
_lines
(
1.0
f
)
{
opt
.
type
=
type
;
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s Light %d"
,
Light_Type_Names
[(
int
)
type
],
id
);
}
}
bool
Scene_Light
::
is_env
()
const
{
return
opt
.
type
==
Light_Type
::
sphere
||
opt
.
type
==
Light_Type
::
hemisphere
;
return
opt
.
type
==
Light_Type
::
sphere
||
opt
.
type
==
Light_Type
::
hemisphere
;
}
void
Scene_Light
::
set_time
(
float
time
)
{
if
(
lanim
.
splines
.
any
())
{
lanim
.
at
(
time
,
opt
);
}
dirty
();
if
(
lanim
.
splines
.
any
())
{
lanim
.
at
(
time
,
opt
);
}
dirty
();
}
void
Scene_Light
::
emissive_clear
()
{
opt
.
has_emissive_map
=
false
;
}
void
Scene_Light
::
emissive_clear
()
{
opt
.
has_emissive_map
=
false
;
}
HDR_Image
Scene_Light
::
emissive_copy
()
const
{
return
_emissive
.
copy
();
}
HDR_Image
Scene_Light
::
emissive_copy
()
const
{
return
_emissive
.
copy
();
}
std
::
string
Scene_Light
::
emissive_load
(
std
::
string
file
)
{
std
::
string
err
=
_emissive
.
load_from
(
file
);
if
(
err
.
empty
())
{
opt
.
has_emissive_map
=
true
;
}
return
err
;
std
::
string
err
=
_emissive
.
load_from
(
file
);
if
(
err
.
empty
())
{
opt
.
has_emissive_map
=
true
;
}
return
err
;
}
std
::
string
Scene_Light
::
emissive_loaded
()
const
{
return
_emissive
.
loaded_from
();
}
std
::
string
Scene_Light
::
emissive_loaded
()
const
{
return
_emissive
.
loaded_from
();
}
const
GL
::
Tex2D
&
Scene_Light
::
emissive_texture
()
const
{
return
_emissive
.
get_texture
();
}
const
GL
::
Tex2D
&
Scene_Light
::
emissive_texture
()
const
{
return
_emissive
.
get_texture
();
}
BBox
Scene_Light
::
bbox
()
const
{
BBox
box
=
_mesh
.
bbox
();
box
.
transform
(
pose
.
transform
());
return
box
;
BBox
box
=
_mesh
.
bbox
();
box
.
transform
(
pose
.
transform
());
return
box
;
}
Scene_Light
::
Scene_Light
(
Scene_Light
&&
src
)
:
_lines
(
1.0
f
)
{
*
this
=
std
::
move
(
src
);
}
Scene_Light
::
Scene_Light
(
Scene_Light
&&
src
)
:
_lines
(
1.0
f
)
{
*
this
=
std
::
move
(
src
);
}
void
Scene_Light
::
regen_mesh
()
{
switch
(
opt
.
type
)
{
case
Light_Type
::
spot
:
{
Vec3
col
(
opt
.
spectrum
.
r
,
opt
.
spectrum
.
g
,
opt
.
spectrum
.
b
);
_lines
=
Util
::
spotlight_mesh
(
col
,
opt
.
angle_bounds
.
x
,
opt
.
angle_bounds
.
y
);
_mesh
=
Util
::
sphere_mesh
(
0.15
f
,
2
);
}
break
;
case
Light_Type
::
directional
:
{
_mesh
=
Util
::
arrow_mesh
(
0.03
f
,
0.075
f
,
1.0
f
);
}
break
;
case
Light_Type
::
point
:
{
_mesh
=
Util
::
sphere_mesh
(
0.15
f
,
2
);
}
break
;
case
Light_Type
::
rectangle
:
{
_mesh
=
Util
::
quad_mesh
(
opt
.
size
.
x
,
opt
.
size
.
y
);
}
break
;
default:
break
;
}
_dirty
=
false
;
}
void
Scene_Light
::
dirty
()
{
_dirty
=
true
;
}
Spectrum
Scene_Light
::
radiance
()
const
{
return
opt
.
spectrum
*
opt
.
intensity
;
}
void
Scene_Light
::
render
(
const
Mat4
&
view
,
bool
depth_only
,
bool
posed
)
{
if
(
_dirty
)
regen_mesh
();
Renderer
&
renderer
=
Renderer
::
get
();
Spectrum
s
=
opt
.
spectrum
;
s
.
make_srgb
();
Vec3
col
(
s
.
r
,
s
.
g
,
s
.
b
);
Mat4
rot
=
view
;
rot
.
cols
[
3
]
=
Vec4
(
0.0
f
,
0.0
f
,
0.0
f
,
1.0
f
);
Mat4
T
=
posed
?
pose
.
transform
()
:
Mat4
::
I
;
if
(
opt
.
type
==
Light_Type
::
spot
&&
!
depth_only
)
renderer
.
lines
(
_lines
,
view
,
T
);
if
(
opt
.
type
==
Light_Type
::
hemisphere
)
{
renderer
.
skydome
(
rot
,
col
,
0.0
f
);
}
else
if
(
opt
.
type
==
Light_Type
::
sphere
)
{
if
(
opt
.
has_emissive_map
)
renderer
.
skydome
(
rot
,
col
,
-
1.1
f
,
_emissive
.
get_texture
());
else
renderer
.
skydome
(
rot
,
col
,
-
1.1
f
);
}
else
{
Renderer
::
MeshOpt
opts
;
opts
.
modelview
=
view
*
T
;
opts
.
id
=
_id
;
opts
.
solid_color
=
true
;
opts
.
depth_only
=
depth_only
;
opts
.
color
=
col
;
renderer
.
mesh
(
_mesh
,
opts
);
}
}
bool
operator
!=
(
const
Scene_Light
::
Options
&
l
,
const
Scene_Light
::
Options
&
r
)
{
return
l
.
type
!=
r
.
type
||
std
::
string
(
l
.
name
)
!=
std
::
string
(
r
.
name
)
||
l
.
spectrum
!=
r
.
spectrum
||
l
.
intensity
!=
r
.
intensity
||
l
.
angle_bounds
!=
r
.
angle_bounds
||
l
.
size
!=
r
.
size
||
l
.
has_emissive_map
!=
r
.
has_emissive_map
;
}
void
Scene_Light
::
Anim_Light
::
at
(
float
t
,
Options
&
o
)
const
{
auto
[
s
,
i
,
a
,
sz
]
=
splines
.
at
(
t
);
o
.
spectrum
=
s
;
o
.
intensity
=
i
;
o
.
angle_bounds
=
a
;
o
.
size
=
sz
;
switch
(
opt
.
type
)
{
case
Light_Type
::
spot
:
{
Vec3
col
(
opt
.
spectrum
.
r
,
opt
.
spectrum
.
g
,
opt
.
spectrum
.
b
);
_lines
=
Util
::
spotlight_mesh
(
col
,
opt
.
angle_bounds
.
x
,
opt
.
angle_bounds
.
y
);
_mesh
=
Util
::
sphere_mesh
(
0.15
f
,
2
);
}
break
;
case
Light_Type
::
directional
:
{
_mesh
=
Util
::
arrow_mesh
(
0.03
f
,
0.075
f
,
1.0
f
);
}
break
;
case
Light_Type
::
point
:
{
_mesh
=
Util
::
sphere_mesh
(
0.15
f
,
2
);
}
break
;
case
Light_Type
::
rectangle
:
{
_mesh
=
Util
::
quad_mesh
(
opt
.
size
.
x
,
opt
.
size
.
y
);
}
break
;
default:
break
;
}
_dirty
=
false
;
}
void
Scene_Light
::
dirty
()
{
_dirty
=
true
;
}
Spectrum
Scene_Light
::
radiance
()
const
{
return
opt
.
spectrum
*
opt
.
intensity
;
}
void
Scene_Light
::
render
(
const
Mat4
&
view
,
bool
depth_only
,
bool
posed
)
{
if
(
_dirty
)
regen_mesh
();
Renderer
&
renderer
=
Renderer
::
get
();
Spectrum
s
=
opt
.
spectrum
;
s
.
make_srgb
();
Vec3
col
(
s
.
r
,
s
.
g
,
s
.
b
);
Mat4
rot
=
view
;
rot
.
cols
[
3
]
=
Vec4
(
0.0
f
,
0.0
f
,
0.0
f
,
1.0
f
);
Mat4
T
=
posed
?
pose
.
transform
()
:
Mat4
::
I
;
if
(
opt
.
type
==
Light_Type
::
spot
&&
!
depth_only
)
renderer
.
lines
(
_lines
,
view
,
T
);
if
(
opt
.
type
==
Light_Type
::
hemisphere
)
{
renderer
.
skydome
(
rot
,
col
,
0.0
f
);
}
else
if
(
opt
.
type
==
Light_Type
::
sphere
)
{
if
(
opt
.
has_emissive_map
)
renderer
.
skydome
(
rot
,
col
,
-
1.1
f
,
_emissive
.
get_texture
());
else
renderer
.
skydome
(
rot
,
col
,
-
1.1
f
);
}
else
{
Renderer
::
MeshOpt
opts
;
opts
.
modelview
=
view
*
T
;
opts
.
id
=
_id
;
opts
.
solid_color
=
true
;
opts
.
depth_only
=
depth_only
;
opts
.
color
=
col
;
renderer
.
mesh
(
_mesh
,
opts
);
}
}
bool
operator
!=
(
const
Scene_Light
::
Options
&
l
,
const
Scene_Light
::
Options
&
r
)
{
return
l
.
type
!=
r
.
type
||
std
::
string
(
l
.
name
)
!=
std
::
string
(
r
.
name
)
||
l
.
spectrum
!=
r
.
spectrum
||
l
.
intensity
!=
r
.
intensity
||
l
.
angle_bounds
!=
r
.
angle_bounds
||
l
.
size
!=
r
.
size
||
l
.
has_emissive_map
!=
r
.
has_emissive_map
;
}
void
Scene_Light
::
Anim_Light
::
at
(
float
t
,
Options
&
o
)
const
{
auto
[
s
,
i
,
a
,
sz
]
=
splines
.
at
(
t
);
o
.
spectrum
=
s
;
o
.
intensity
=
i
;
o
.
angle_bounds
=
a
;
o
.
size
=
sz
;
}
void
Scene_Light
::
Anim_Light
::
set
(
float
t
,
Options
o
)
{
splines
.
set
(
t
,
o
.
spectrum
,
o
.
intensity
,
o
.
angle_bounds
,
o
.
size
);
splines
.
set
(
t
,
o
.
spectrum
,
o
.
intensity
,
o
.
angle_bounds
,
o
.
size
);
}
src/scene/light.h
View file @
c2535f0f
...
...
@@ -8,77 +8,69 @@
#include "../rays/samplers.h"
#include "../util/hdr_image.h"
#include "pose.h"
#include "object.h"
#include "pose.h"
enum
class
Light_Type
:
int
{
directional
,
sphere
,
hemisphere
,
point
,
spot
,
rectangle
,
count
};
extern
const
char
*
Light_Type_Names
[(
int
)
Light_Type
::
count
];
enum
class
Light_Type
:
int
{
directional
,
sphere
,
hemisphere
,
point
,
spot
,
rectangle
,
count
};
extern
const
char
*
Light_Type_Names
[(
int
)
Light_Type
::
count
];
class
Scene_Light
{
public:
Scene_Light
(
Light_Type
type
,
Scene_ID
id
,
Pose
p
,
std
::
string
n
=
{});
Scene_Light
(
const
Scene_Light
&
src
)
=
delete
;
Scene_Light
(
Scene_Light
&&
src
);
~
Scene_Light
()
=
default
;
void
operator
=
(
const
Scene_Light
&
src
)
=
delete
;
Scene_Light
&
operator
=
(
Scene_Light
&&
src
)
=
default
;
Scene_ID
id
()
const
{
return
_id
;}
BBox
bbox
()
const
;
void
render
(
const
Mat4
&
view
,
bool
depth_only
=
false
,
bool
posed
=
true
);
void
dirty
();
Spectrum
radiance
()
const
;
void
set_time
(
float
time
);
std
::
string
emissive_load
(
std
::
string
file
);
std
::
string
emissive_loaded
()
const
;
HDR_Image
emissive_copy
()
const
;
const
GL
::
Tex2D
&
emissive_texture
()
const
;
void
emissive_clear
();
bool
is_env
()
const
;
static
const
inline
int
max_name_len
=
256
;
struct
Options
{
Light_Type
type
=
Light_Type
::
point
;
char
name
[
max_name_len
]
=
{};
Spectrum
spectrum
=
Spectrum
(
1.0
f
);
float
intensity
=
1.0
f
;
bool
has_emissive_map
=
false
;
Vec2
angle_bounds
=
Vec2
(
30.0
f
,
35.0
f
);
Vec2
size
=
Vec2
(
1.0
f
);
};
struct
Anim_Light
{
void
at
(
float
t
,
Options
&
o
)
const
;
void
set
(
float
t
,
Options
o
);
Splines
<
Spectrum
,
float
,
Vec2
,
Vec2
>
splines
;
};
Options
opt
;
Pose
pose
;
Anim_Pose
anim
;
Anim_Light
lanim
;
Scene_Light
(
Light_Type
type
,
Scene_ID
id
,
Pose
p
,
std
::
string
n
=
{});
Scene_Light
(
const
Scene_Light
&
src
)
=
delete
;
Scene_Light
(
Scene_Light
&&
src
);
~
Scene_Light
()
=
default
;
void
operator
=
(
const
Scene_Light
&
src
)
=
delete
;
Scene_Light
&
operator
=
(
Scene_Light
&&
src
)
=
default
;
Scene_ID
id
()
const
{
return
_id
;
}
BBox
bbox
()
const
;
void
render
(
const
Mat4
&
view
,
bool
depth_only
=
false
,
bool
posed
=
true
);
void
dirty
();
Spectrum
radiance
()
const
;
void
set_time
(
float
time
);
std
::
string
emissive_load
(
std
::
string
file
);
std
::
string
emissive_loaded
()
const
;
HDR_Image
emissive_copy
()
const
;
const
GL
::
Tex2D
&
emissive_texture
()
const
;
void
emissive_clear
();
bool
is_env
()
const
;
static
const
inline
int
max_name_len
=
256
;
struct
Options
{
Light_Type
type
=
Light_Type
::
point
;
char
name
[
max_name_len
]
=
{};
Spectrum
spectrum
=
Spectrum
(
1.0
f
);
float
intensity
=
1.0
f
;
bool
has_emissive_map
=
false
;
Vec2
angle_bounds
=
Vec2
(
30.0
f
,
35.0
f
);
Vec2
size
=
Vec2
(
1.0
f
);
};
struct
Anim_Light
{
void
at
(
float
t
,
Options
&
o
)
const
;
void
set
(
float
t
,
Options
o
);
Splines
<
Spectrum
,
float
,
Vec2
,
Vec2
>
splines
;
};
Options
opt
;
Pose
pose
;
Anim_Pose
anim
;
Anim_Light
lanim
;
private:
void
regen_mesh
();
void
regen_mesh
();
bool
_dirty
=
true
;
Scene_ID
_id
=
0
;
GL
::
Mesh
_mesh
;
GL
::
Lines
_lines
;
HDR_Image
_emissive
;
bool
_dirty
=
true
;
Scene_ID
_id
=
0
;
GL
::
Mesh
_mesh
;
GL
::
Lines
_lines
;
HDR_Image
_emissive
;
};
bool
operator
!=
(
const
Scene_Light
::
Options
&
l
,
const
Scene_Light
::
Options
&
r
);
bool
operator
!=
(
const
Scene_Light
::
Options
&
l
,
const
Scene_Light
::
Options
&
r
);
src/scene/material.cpp
View file @
c2535f0f
#include "material.h"
const
char
*
Material_Type_Names
[(
int
)
Material_Type
::
count
]
=
{
"Lambertian"
,
"Mirror"
,
"Refract"
,
"Glass"
,
"Diffuse Light"
};
const
char
*
Material_Type_Names
[(
int
)
Material_Type
::
count
]
=
{
"Lambertian"
,
"Mirror"
,
"Refract"
,
"Glass"
,
"Diffuse Light"
};
bool
operator
!=
(
const
Material
::
Options
&
l
,
const
Material
::
Options
&
r
)
{
return
l
.
albedo
!=
r
.
albedo
||
l
.
emissive
!=
r
.
emissive
||
l
.
ior
!=
r
.
ior
||
l
.
reflectance
!=
r
.
reflectance
||
l
.
transmittance
!=
r
.
transmittance
||
l
.
type
!=
r
.
type
||
l
.
intensity
!=
r
.
intensity
;
bool
operator
!=
(
const
Material
::
Options
&
l
,
const
Material
::
Options
&
r
)
{
return
l
.
albedo
!=
r
.
albedo
||
l
.
emissive
!=
r
.
emissive
||
l
.
ior
!=
r
.
ior
||
l
.
reflectance
!=
r
.
reflectance
||
l
.
transmittance
!=
r
.
transmittance
||
l
.
type
!=
r
.
type
||
l
.
intensity
!=
r
.
intensity
;
}
Vec3
Material
::
layout_color
()
const
{
Vec3
color
;
switch
(
opt
.
type
)
{
case
Material_Type
::
lambertian
:
{
color
=
opt
.
albedo
.
to_vec
();
}
break
;
case
Material_Type
::
mirror
:
{
color
=
opt
.
reflectance
.
to_vec
();
}
break
;
case
Material_Type
::
refract
:
case
Material_Type
::
glass
:
{
color
=
opt
.
transmittance
.
to_vec
();
}
break
;
case
Material_Type
::
diffuse_light
:
{
color
=
opt
.
emissive
.
to_vec
();
}
break
;
default:
break
;
}
return
color
;
Vec3
color
;
switch
(
opt
.
type
)
{
case
Material_Type
::
lambertian
:
{
color
=
opt
.
albedo
.
to_vec
();
}
break
;
case
Material_Type
::
mirror
:
{
color
=
opt
.
reflectance
.
to_vec
();
}
break
;
case
Material_Type
::
refract
:
case
Material_Type
::
glass
:
{
color
=
opt
.
transmittance
.
to_vec
();
}
break
;
case
Material_Type
::
diffuse_light
:
{
color
=
opt
.
emissive
.
to_vec
();
}
break
;
default:
break
;
}
return
color
;
}
Spectrum
Material
::
emissive
()
const
{
return
opt
.
emissive
*
opt
.
intensity
;
}
Spectrum
Material
::
emissive
()
const
{
return
opt
.
emissive
*
opt
.
intensity
;
}
Material
Material
::
copy
()
const
{
Material
ret
;
...
...
src/scene/material.h
View file @
c2535f0f
...
...
@@ -3,46 +3,38 @@
#include "../lib/spectrum.h"
enum
class
Material_Type
:
int
{
lambertian
,
mirror
,
refract
,
glass
,
diffuse_light
,
count
};
extern
const
char
*
Material_Type_Names
[(
int
)
Material_Type
::
count
];
enum
class
Material_Type
:
int
{
lambertian
,
mirror
,
refract
,
glass
,
diffuse_light
,
count
};
extern
const
char
*
Material_Type_Names
[(
int
)
Material_Type
::
count
];
class
Material
{
public:
Material
()
=
default
;
Material
(
Material_Type
type
)
{
opt
.
type
=
type
;
}
Material
(
const
Material
&
src
)
=
delete
;
Material
(
Material
&&
src
)
=
default
;
~
Material
()
=
default
;
void
operator
=
(
const
Material
&
src
)
=
delete
;
Material
&
operator
=
(
Material
&&
src
)
=
default
;
// TODO: decide how to handle texture resources. should probably use a texture repository
// and also integrate that into the envmaps
Material
(
Material_Type
type
)
{
opt
.
type
=
type
;
}
Material
(
const
Material
&
src
)
=
delete
;
Material
(
Material
&&
src
)
=
default
;
~
Material
()
=
default
;
void
operator
=
(
const
Material
&
src
)
=
delete
;
Material
&
operator
=
(
Material
&&
src
)
=
default
;
// TODO: decide how to handle texture resources. should probably use a texture repository
// and also integrate that into the envmaps
Material
copy
()
const
;
Spectrum
emissive
()
const
;
Vec3
layout_color
()
const
;
Spectrum
emissive
()
const
;
Vec3
layout_color
()
const
;
struct
Options
{
Material_Type
type
=
Material_Type
::
lambertian
;
Spectrum
albedo
=
Spectrum
(
1.0
f
);
struct
Options
{
Material_Type
type
=
Material_Type
::
lambertian
;
Spectrum
albedo
=
Spectrum
(
1.0
f
);
Spectrum
reflectance
=
Spectrum
(
1.0
f
);
Spectrum
transmittance
=
Spectrum
(
1.0
f
);
Spectrum
emissive
=
Spectrum
(
1.0
f
);
float
intensity
=
1.0
f
;
float
intensity
=
1.0
f
;
float
ior
=
1.2
f
;
};
};
Options
opt
;
Options
opt
;
};
bool
operator
!=
(
const
Material
::
Options
&
l
,
const
Material
::
Options
&
r
);
bool
operator
!=
(
const
Material
::
Options
&
l
,
const
Material
::
Options
&
r
);
src/scene/object.cpp
View file @
c2535f0f
...
...
@@ -3,212 +3,201 @@
#include <sstream>
#include "../gui/render.h"
#include "../geometry/util.h"
#include "../gui/render.h"
#include "renderer.h"
Scene_Object
::
Scene_Object
(
Scene_ID
id
,
Pose
p
,
GL
::
Mesh
&&
m
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
armature
(
id
),
_mesh
(
std
::
move
(
m
))
{
set_skel_dirty
();
editable
=
false
;
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"Object %d"
,
id
);
}
}
Scene_Object
::
Scene_Object
(
Scene_ID
id
,
Pose
p
,
Halfedge_Mesh
&&
m
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
armature
(
id
),
halfedge
(
std
::
move
(
m
)),
_mesh
()
{
set_mesh_dirty
();
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"Object %d"
,
id
);
}
}
const
GL
::
Mesh
&
Scene_Object
::
posed_mesh
()
{
sync_anim_mesh
();
if
(
armature
.
has_bones
())
{
return
_anim_mesh
;
}
return
_mesh
;
Scene_Object
::
Scene_Object
(
Scene_ID
id
,
Pose
p
,
GL
::
Mesh
&&
m
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
armature
(
id
),
_mesh
(
std
::
move
(
m
))
{
set_skel_dirty
();
editable
=
false
;
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"Object %d"
,
id
);
}
}
void
Scene_Object
::
try_make_editable
(
PT
::
Shape_Type
prev
)
{
Scene_Object
::
Scene_Object
(
Scene_ID
id
,
Pose
p
,
Halfedge_Mesh
&&
m
,
std
::
string
n
)
:
pose
(
p
),
_id
(
id
),
armature
(
id
),
halfedge
(
std
::
move
(
m
)),
_mesh
()
{
switch
(
prev
)
{
case
PT
::
Shape_Type
::
sphere
:
{
_mesh
=
Util
::
sphere_mesh
(
opt
.
shape
.
get
<
PT
::
Sphere
>
().
radius
,
2
);
}
break
;
case
PT
::
Shape_Type
::
none
:
case
PT
::
Shape_Type
::
count
:
break
;
}
set_mesh_dirty
();
std
::
string
err
=
halfedge
.
from_mesh
(
_mesh
);
if
(
err
.
empty
())
editable
=
true
;
mesh_dirty
=
true
;
skel_dirty
=
true
;
if
(
n
.
size
())
{
snprintf
(
opt
.
name
,
max_name_len
,
"%s"
,
n
.
c_str
());
}
else
{
snprintf
(
opt
.
name
,
max_name_len
,
"Object %d"
,
id
);
}
}
bool
Scene_Object
::
is_shape
()
const
{
return
opt
.
shape_type
!=
PT
::
Shape_Type
::
none
;
const
GL
::
Mesh
&
Scene_Object
::
posed_mesh
()
{
sync_anim_mesh
();
if
(
armature
.
has_bones
())
{
return
_anim_mesh
;
}
return
_mesh
;
}
void
Scene_Object
::
try_make_editable
(
PT
::
Shape_Type
prev
)
{
switch
(
prev
)
{
case
PT
::
Shape_Type
::
sphere
:
{
_mesh
=
Util
::
sphere_mesh
(
opt
.
shape
.
get
<
PT
::
Sphere
>
().
radius
,
2
);
}
break
;
case
PT
::
Shape_Type
::
none
:
case
PT
::
Shape_Type
::
count
:
break
;
}
std
::
string
err
=
halfedge
.
from_mesh
(
_mesh
);
if
(
err
.
empty
())
editable
=
true
;
mesh_dirty
=
true
;
skel_dirty
=
true
;
}
bool
Scene_Object
::
is_shape
()
const
{
return
opt
.
shape_type
!=
PT
::
Shape_Type
::
none
;
}
void
Scene_Object
::
set_time
(
float
time
)
{
if
(
anim
.
splines
.
any
())
pose
=
anim
.
at
(
time
);
if
(
armature
.
set_time
(
time
))
set_pose_dirty
();
if
(
anim
.
splines
.
any
())
pose
=
anim
.
at
(
time
);
if
(
armature
.
set_time
(
time
))
set_pose_dirty
();
}
bool
Scene_Object
::
is_editable
()
const
{
return
editable
&&
opt
.
shape_type
==
PT
::
Shape_Type
::
none
;
return
editable
&&
opt
.
shape_type
==
PT
::
Shape_Type
::
none
;
}
void
Scene_Object
::
copy_mesh
(
Halfedge_Mesh
&
out
)
{
halfedge
.
copy_to
(
out
);
}
void
Scene_Object
::
copy_mesh
(
Halfedge_Mesh
&
out
)
{
halfedge
.
copy_to
(
out
);
}
void
Scene_Object
::
set_mesh
(
Halfedge_Mesh
&
in
)
{
in
.
copy_to
(
halfedge
);
set_mesh_dirty
();
void
Scene_Object
::
set_mesh
(
Halfedge_Mesh
&
in
)
{
in
.
copy_to
(
halfedge
);
set_mesh_dirty
();
}
Halfedge_Mesh
::
ElementRef
Scene_Object
::
set_mesh
(
Halfedge_Mesh
&
in
,
unsigned
int
eid
)
{
auto
e
=
in
.
copy_to
(
halfedge
,
eid
);
set_mesh_dirty
();
return
e
;
Halfedge_Mesh
::
ElementRef
Scene_Object
::
set_mesh
(
Halfedge_Mesh
&
in
,
unsigned
int
eid
)
{
auto
e
=
in
.
copy_to
(
halfedge
,
eid
);
set_mesh_dirty
();
return
e
;
}
void
Scene_Object
::
take_mesh
(
Halfedge_Mesh
&&
in
)
{
halfedge
=
std
::
move
(
in
);
set_mesh_dirty
();
void
Scene_Object
::
take_mesh
(
Halfedge_Mesh
&&
in
)
{
halfedge
=
std
::
move
(
in
);
set_mesh_dirty
();
}
Halfedge_Mesh
&
Scene_Object
::
get_mesh
()
{
return
halfedge
;
}
Halfedge_Mesh
&
Scene_Object
::
get_mesh
()
{
return
halfedge
;
}
const
Halfedge_Mesh
&
Scene_Object
::
get_mesh
()
const
{
return
halfedge
;
}
const
Halfedge_Mesh
&
Scene_Object
::
get_mesh
()
const
{
return
halfedge
;
}
void
Scene_Object
::
sync_anim_mesh
()
{
sync_mesh
();
if
(
skel_dirty
&&
armature
.
has_bones
())
{
vertex_joints
.
clear
();
armature
.
find_joints
(
_mesh
,
vertex_joints
);
}
if
(
pose_dirty
&&
armature
.
has_bones
())
{
armature
.
skin
(
_mesh
,
_anim_mesh
,
vertex_joints
);
if
(
!
opt
.
smooth_normals
)
{
auto
&
verts
=
_anim_mesh
.
edit_verts
();
auto
&
idxs
=
_anim_mesh
.
edit_indices
();
for
(
size_t
i
=
0
;
i
<
idxs
.
size
();
i
+=
3
)
{
Vec3
v0
=
verts
[
idxs
[
i
]].
pos
;
Vec3
v1
=
verts
[
idxs
[
i
+
1
]].
pos
;
Vec3
v2
=
verts
[
idxs
[
i
+
2
]].
pos
;
Vec3
n
=
cross
(
v1
-
v0
,
v2
-
v0
).
unit
();
verts
[
idxs
[
i
]].
norm
=
n
;
verts
[
idxs
[
i
+
1
]].
norm
=
n
;
verts
[
idxs
[
i
+
2
]].
norm
=
n
;
}
}
}
skel_dirty
=
pose_dirty
=
false
;
sync_mesh
();
if
(
skel_dirty
&&
armature
.
has_bones
())
{
vertex_joints
.
clear
();
armature
.
find_joints
(
_mesh
,
vertex_joints
);
}
if
(
pose_dirty
&&
armature
.
has_bones
())
{
armature
.
skin
(
_mesh
,
_anim_mesh
,
vertex_joints
);
if
(
!
opt
.
smooth_normals
)
{
auto
&
verts
=
_anim_mesh
.
edit_verts
();
auto
&
idxs
=
_anim_mesh
.
edit_indices
();
for
(
size_t
i
=
0
;
i
<
idxs
.
size
();
i
+=
3
)
{
Vec3
v0
=
verts
[
idxs
[
i
]].
pos
;
Vec3
v1
=
verts
[
idxs
[
i
+
1
]].
pos
;
Vec3
v2
=
verts
[
idxs
[
i
+
2
]].
pos
;
Vec3
n
=
cross
(
v1
-
v0
,
v2
-
v0
).
unit
();
verts
[
idxs
[
i
]].
norm
=
n
;
verts
[
idxs
[
i
+
1
]].
norm
=
n
;
verts
[
idxs
[
i
+
2
]].
norm
=
n
;
}
}
}
skel_dirty
=
pose_dirty
=
false
;
}
void
Scene_Object
::
sync_mesh
()
{
if
(
editable
&&
mesh_dirty
)
{
halfedge
.
to_mesh
(
_mesh
,
!
opt
.
smooth_normals
);
mesh_dirty
=
false
;
}
else
if
(
mesh_dirty
&&
is_shape
())
{
mesh_dirty
=
false
;
}
}
void
Scene_Object
::
set_pose_dirty
()
{
pose_dirty
=
true
;
if
(
editable
&&
mesh_dirty
)
{
halfedge
.
to_mesh
(
_mesh
,
!
opt
.
smooth_normals
);
mesh_dirty
=
false
;
}
else
if
(
mesh_dirty
&&
is_shape
())
{
mesh_dirty
=
false
;
}
}
void
Scene_Object
::
set_pose_dirty
()
{
pose_dirty
=
true
;
}
void
Scene_Object
::
set_skel_dirty
()
{
skel_dirty
=
true
;
pose_dirty
=
true
;
skel_dirty
=
true
;
pose_dirty
=
true
;
}
void
Scene_Object
::
set_mesh_dirty
()
{
rig_dirty
=
true
;
mesh_dirty
=
true
;
skel_dirty
=
true
;
pose_dirty
=
true
;
rig_dirty
=
true
;
mesh_dirty
=
true
;
skel_dirty
=
true
;
pose_dirty
=
true
;
}
BBox
Scene_Object
::
bbox
()
{
sync_anim_mesh
();
BBox
box
;
if
(
opt
.
shape_type
==
PT
::
Shape_Type
::
none
)
{
if
(
armature
.
has_bones
())
box
=
_anim_mesh
.
bbox
();
else
box
=
_mesh
.
bbox
();
}
else
{
box
=
opt
.
shape
.
bbox
();
}
box
.
transform
(
pose
.
transform
());
return
box
;
}
void
Scene_Object
::
render
(
const
Mat4
&
view
,
bool
solid
,
bool
depth_only
,
bool
posed
,
bool
do_anim
)
{
if
(
do_anim
)
sync_anim_mesh
();
else
sync_mesh
();
Renderer
::
MeshOpt
opts
;
opts
.
id
=
_id
;
opts
.
solid_color
=
solid
;
opts
.
depth_only
=
depth_only
;
opts
.
color
=
material
.
layout_color
();
opts
.
sel_color
=
material
.
layout_color
();
opts
.
modelview
=
posed
?
view
*
pose
.
transform
()
:
view
;
switch
(
opt
.
shape_type
)
{
case
PT
::
Shape_Type
::
sphere
:
{
opts
.
wireframe
=
false
;
opts
.
modelview
=
opts
.
modelview
*
Mat4
::
scale
(
Vec3
{
opt
.
shape
.
get
<
PT
::
Sphere
>
().
radius
});
Renderer
::
get
().
sphere
(
opts
);
}
break
;
case
PT
::
Shape_Type
::
none
:
{
opts
.
wireframe
=
opt
.
wireframe
;
if
(
do_anim
&&
armature
.
has_bones
())
{
Renderer
::
get
().
mesh
(
_anim_mesh
,
opts
);
}
else
{
Renderer
::
get
().
mesh
(
_mesh
,
opts
);
}
}
break
;
case
PT
::
Shape_Type
::
count
:
break
;
}
}
bool
operator
!=
(
const
Scene_Object
::
Options
&
l
,
const
Scene_Object
::
Options
&
r
)
{
return
std
::
string
(
l
.
name
)
!=
std
::
string
(
r
.
name
)
||
l
.
shape_type
!=
r
.
shape_type
||
l
.
smooth_normals
!=
r
.
smooth_normals
||
l
.
wireframe
!=
r
.
wireframe
||
l
.
shape
!=
r
.
shape
;
sync_anim_mesh
();
BBox
box
;
if
(
opt
.
shape_type
==
PT
::
Shape_Type
::
none
)
{
if
(
armature
.
has_bones
())
box
=
_anim_mesh
.
bbox
();
else
box
=
_mesh
.
bbox
();
}
else
{
box
=
opt
.
shape
.
bbox
();
}
box
.
transform
(
pose
.
transform
());
return
box
;
}
void
Scene_Object
::
render
(
const
Mat4
&
view
,
bool
solid
,
bool
depth_only
,
bool
posed
,
bool
do_anim
)
{
if
(
do_anim
)
sync_anim_mesh
();
else
sync_mesh
();
Renderer
::
MeshOpt
opts
;
opts
.
id
=
_id
;
opts
.
solid_color
=
solid
;
opts
.
depth_only
=
depth_only
;
opts
.
color
=
material
.
layout_color
();
opts
.
sel_color
=
material
.
layout_color
();
opts
.
modelview
=
posed
?
view
*
pose
.
transform
()
:
view
;
switch
(
opt
.
shape_type
)
{
case
PT
::
Shape_Type
::
sphere
:
{
opts
.
wireframe
=
false
;
opts
.
modelview
=
opts
.
modelview
*
Mat4
::
scale
(
Vec3
{
opt
.
shape
.
get
<
PT
::
Sphere
>
().
radius
});
Renderer
::
get
().
sphere
(
opts
);
}
break
;
case
PT
::
Shape_Type
::
none
:
{
opts
.
wireframe
=
opt
.
wireframe
;
if
(
do_anim
&&
armature
.
has_bones
())
{
Renderer
::
get
().
mesh
(
_anim_mesh
,
opts
);
}
else
{
Renderer
::
get
().
mesh
(
_mesh
,
opts
);
}
}
break
;
case
PT
::
Shape_Type
::
count
:
break
;
}
}
bool
operator
!=
(
const
Scene_Object
::
Options
&
l
,
const
Scene_Object
::
Options
&
r
)
{
return
std
::
string
(
l
.
name
)
!=
std
::
string
(
r
.
name
)
||
l
.
shape_type
!=
r
.
shape_type
||
l
.
smooth_normals
!=
r
.
smooth_normals
||
l
.
wireframe
!=
r
.
wireframe
||
l
.
shape
!=
r
.
shape
;
}
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment