Compare commits
235 Commits
devirtuali
...
lineart-ob
Author | SHA1 | Date | |
---|---|---|---|
5ba3e6001f | |||
0ebc062604 | |||
a3b38c979a | |||
77afe859a0 | |||
ce689964a4 | |||
516ec45d10 | |||
58511c4175 | |||
f49948bf48 | |||
50840bb2a3 | |||
3a055e8f41 | |||
0d5d554287 | |||
fe2df4c771 | |||
0385e2f1f9 | |||
5b8a3ccd37 | |||
97dbcf9746 | |||
8adc7cad00 | |||
31a2feceb8 | |||
f5191b8760 | |||
65a1fcdaf7 | |||
67a4908bfc | |||
3adef61942 | |||
41b8e0316a | |||
28e068b55c | |||
8898251584 | |||
11dd7941af | |||
67516d0dae | |||
8ed8fa80f4 | |||
08dbd3bc7f | |||
38d8b088e7 | |||
c2cdbe1e88 | |||
df3316cbe9 | |||
972a697f82 | |||
feea852b10 | |||
9364e17936 | |||
f438344cf2 | |||
6d9268c2c7 | |||
16afff2ddc | |||
42717596d0 | |||
f8f8edbe1a | |||
![]() |
75ccfa63d0 | ||
6a3c3c77b3 | |||
9ec94c3882 | |||
d813ee55fd | |||
5a06996722 | |||
67962824e9 | |||
37d298391e | |||
2890c11cd7 | |||
56cfd60d43 | |||
![]() |
721a9bc35c | ||
![]() |
3e98331a09 | ||
47de3659f0 | |||
6f56bd4083 | |||
767939231d | |||
058ce64be0 | |||
14a2706886 | |||
fa3bd17ae8 | |||
1e3f4c70ab | |||
c2c17cc076 | |||
6296cb5129 | |||
eccc9d8eba | |||
3035235def | |||
58d86527ae | |||
8c25889bb6 | |||
775f0d76d5 | |||
7e045094c1 | |||
f401741544 | |||
76acc5e999 | |||
adcce654e3 | |||
![]() |
549f68149d | ||
b90e892a17 | |||
5da02548e9 | |||
a0c2d6bf85 | |||
bec057a453 | |||
03d39a04a3 | |||
314b27850c | |||
95cce6f6b0 | |||
98fc998c70 | |||
fc58368263 | |||
2cb76a6c8d | |||
029b0df81a | |||
41b3feea85 | |||
![]() |
ccd2e89d37 | ||
ef2b8c1c3a | |||
933fed2a17 | |||
bf80dc2bd4 | |||
213cd39b6d | |||
a3eb4027c2 | |||
b32cb0266c | |||
e88807e71c | |||
b9f1b64801 | |||
98eb111568 | |||
2b191cd2b4 | |||
8eb40d2063 | |||
dc5ae10692 | |||
cb3c233ed3 | |||
65194f47b0 | |||
ad324316ce | |||
089e701191 | |||
4e6c0669e3 | |||
0f9057390d | |||
7484f274dc | |||
cc6db8921b | |||
47d961a4b1 | |||
![]() |
e96a809a68 | ||
25196f8a36 | |||
2839fe9a4d | |||
![]() |
db6287873c | ||
48ff456a4b | |||
48d2f536e1 | |||
05715eaea1 | |||
80859a6cb2 | |||
66dc4d4efb | |||
45f30543db | |||
ad245a25e2 | |||
c71013082d | |||
a9b94e5f81 | |||
31b2b84b3c | |||
1440074cac | |||
c9574412c7 | |||
![]() |
8f0e06a0ca | ||
![]() |
e28f07b5c8 | ||
3acbe2d1e9 | |||
![]() |
b0dc3aff2c | ||
![]() |
d62f443f2d | ||
![]() |
f1ae6952a8 | ||
![]() |
d6e7241237 | ||
4fa3eadce9 | |||
b1908f2e0b | |||
678b76d99a | |||
405bff7fd8 | |||
bc8dcf6db7 | |||
180163c4e4 | |||
f31c3f8114 | |||
f84f9eb8ed | |||
3e25561d51 | |||
927cb5bfac | |||
f076493dbb | |||
3f305b9ab3 | |||
8826db8f03 | |||
8e4c3c6a24 | |||
0ba061c3bc | |||
232b388455 | |||
ad3378215c | |||
abd02da4bd | |||
5a98e38275 | |||
078aa677b6 | |||
a8ee279aa9 | |||
94495049a8 | |||
95236d8a75 | |||
6da5ee8368 | |||
![]() |
7dc4ac71e8 | ||
9c09e5ba24 | |||
e22fd7247a | |||
fb84408aa5 | |||
0a57d6d076 | |||
24fea2bdc4 | |||
babd027fae | |||
cf5d582b77 | |||
c31b89e76e | |||
3a88f151c4 | |||
402845744f | |||
25c357124d | |||
da66c0519f | |||
a63982a65b | |||
4a70561bbd | |||
e0c8d0913b | |||
d1418dd151 | |||
567aad9dcd | |||
9a659f2573 | |||
02de1bff1e | |||
7d3db7a3ae | |||
4b5195a9d7 | |||
21ae323dbf | |||
ae43872ad5 | |||
d0a70adf8f | |||
af17676005 | |||
132576ebb1 | |||
8fad71799f | |||
17a19069db | |||
cd4a9c488f | |||
![]() |
9bc678969a | ||
359b6baf32 | |||
b1d915d027 | |||
88ab34488b | |||
![]() |
869a46df29 | ||
2d472b70e5 | |||
a0957ceab2 | |||
48014fbf14 | |||
77db370cb6 | |||
05a1770ab0 | |||
ee9688da99 | |||
d1944dee86 | |||
5cae213750 | |||
b4a2096415 | |||
4fd3d96f46 | |||
fbca6aeb7c | |||
4a3bcfa102 | |||
d683ea4862 | |||
2451d7d57e | |||
6f1ad5f5e7 | |||
3c62e539af | |||
484a914647 | |||
![]() |
b3525c3487 | ||
4aa9888854 | |||
07cacb6d14 | |||
![]() |
c4f7f59c65 | ||
5f2317fa9b | |||
c65b022e62 | |||
a99639792b | |||
7163db99c4 | |||
4aac251b42 | |||
e7a69b438f | |||
0329145712 | |||
0d0a45b89d | |||
883dbfb72f | |||
20846596b5 | |||
043555c78f | |||
![]() |
b6eb7dae59 | ||
cda3334586 | |||
b2143da253 | |||
e03810693c | |||
5e47056e8d | |||
1c264ebdc0 | |||
2e77a8f974 | |||
0b05e0b97e | |||
![]() |
a4f970e86b | ||
![]() |
811371a6bd | ||
![]() |
1db3e26c74 | ||
8315e97754 | |||
881c566032 | |||
749636bdb9 | |||
ceed37fc5c | |||
69a4d113e8 | |||
3f2d5dfc0d | |||
32da64c17e |
@@ -446,7 +446,7 @@ if(NOT APPLE)
|
||||
endif()
|
||||
|
||||
option(WITH_CYCLES_HIP_BINARIES "Build Cycles AMD HIP binaries" OFF)
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx900 gfx906 gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
set(CYCLES_HIP_BINARIES_ARCH gfx1010 gfx1011 gfx1012 gfx1030 gfx1031 gfx1032 gfx1034 CACHE STRING "AMD HIP architectures to build binaries for")
|
||||
mark_as_advanced(WITH_CYCLES_DEVICE_HIP)
|
||||
mark_as_advanced(CYCLES_HIP_BINARIES_ARCH)
|
||||
endif()
|
||||
|
@@ -4004,6 +4004,7 @@ install_DEB() {
|
||||
WEBP_DEV="libwebp-dev"
|
||||
check_package_DEB $WEBP_DEV
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_DEB $WEBP_DEV
|
||||
WEBP_USE=true
|
||||
fi
|
||||
|
||||
@@ -4435,9 +4436,6 @@ install_DEB() {
|
||||
if [ "$VPX_USE" = true ]; then
|
||||
_packages="$_packages $VPX_DEV"
|
||||
fi
|
||||
if [ "$WEBP_USE" = true ]; then
|
||||
_packages="$_packages $WEBP_DEV"
|
||||
fi
|
||||
if [ "$OPUS_USE" = true ]; then
|
||||
_packages="$_packages $OPUS_DEV"
|
||||
fi
|
||||
@@ -4722,6 +4720,7 @@ install_RPM() {
|
||||
WEBP_DEV="libwebp-devel"
|
||||
check_package_RPM $WEBP_DEV
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_RPM $WEBP_DEV
|
||||
WEBP_USE=true
|
||||
fi
|
||||
|
||||
@@ -5124,9 +5123,6 @@ install_RPM() {
|
||||
if [ "$VPX_USE" = true ]; then
|
||||
_packages="$_packages $VPX_DEV"
|
||||
fi
|
||||
if [ "$WEBP_USE" = true ]; then
|
||||
_packages="$_packages $WEBP_DEV"
|
||||
fi
|
||||
if [ "$OPUS_USE" = true ]; then
|
||||
_packages="$_packages $OPUS_DEV"
|
||||
fi
|
||||
@@ -5300,6 +5296,7 @@ install_ARCH() {
|
||||
WEBP_DEV="libwebp"
|
||||
check_package_ARCH $WEBP_DEV
|
||||
if [ $? -eq 0 ]; then
|
||||
install_packages_ARCH $WEBP_DEV
|
||||
WEBP_USE=true
|
||||
fi
|
||||
|
||||
@@ -5704,16 +5701,12 @@ install_ARCH() {
|
||||
if [ "$VPX_USE" = true ]; then
|
||||
_packages="$_packages $VPX_DEV"
|
||||
fi
|
||||
if [ "$WEBP_USE" = true ]; then
|
||||
_packages="$_packages $WEBP_DEV"
|
||||
fi
|
||||
if [ "$OPUS_USE" = true ]; then
|
||||
_packages="$_packages $OPUS_DEV"
|
||||
fi
|
||||
if [ "$MP3LAME_USE" = true ]; then
|
||||
_packages="$_packages $MP3LAME_DEV"
|
||||
fi
|
||||
install_packages_ARCH $_packages
|
||||
|
||||
compile_FFmpeg
|
||||
fi
|
||||
@@ -5961,6 +5954,12 @@ print_info() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$WEBP_USE" = true ]; then
|
||||
_1="-D WITH_IMAGE_WEBP=ON"
|
||||
PRINT " $_1"
|
||||
_buildargs="$_buildargs $_1"
|
||||
fi
|
||||
|
||||
if [ -d $INST/openexr ]; then
|
||||
_1="-D OPENEXR_ROOT_DIR=$INST/openexr"
|
||||
PRINT " $_1"
|
||||
|
@@ -202,9 +202,9 @@ def parm_size(node_child):
|
||||
|
||||
# NOT PERFECT CODE, EXTRACT SIZE FROM TOKENS
|
||||
if len(tokens) >= 3: # foo [ 1 ]
|
||||
if ((tokens[-3].kind == TokenKind.PUNCTUATION and tokens[-3].spelling == "[") and
|
||||
(tokens[-2].kind == TokenKind.LITERAL and tokens[-2].spelling.isdigit()) and
|
||||
(tokens[-1].kind == TokenKind.PUNCTUATION and tokens[-1].spelling == "]")):
|
||||
if ((tokens[-3].kind == TokenKind.PUNCTUATION and tokens[-3].spelling == "[") and
|
||||
(tokens[-2].kind == TokenKind.LITERAL and tokens[-2].spelling.isdigit()) and
|
||||
(tokens[-1].kind == TokenKind.PUNCTUATION and tokens[-1].spelling == "]")):
|
||||
# ---
|
||||
return int(tokens[-2].spelling)
|
||||
return -1
|
||||
|
@@ -214,7 +214,7 @@ if(WITH_SDL)
|
||||
find_package(SDL2)
|
||||
set(SDL_INCLUDE_DIR ${SDL2_INCLUDE_DIRS})
|
||||
set(SDL_LIBRARY ${SDL2_LIBRARIES})
|
||||
string(APPEND PLATFORM_LINKFLAGS " -framework ForceFeedback")
|
||||
string(APPEND PLATFORM_LINKFLAGS " -framework ForceFeedback -framework GameController -framework CoreHaptics")
|
||||
endif()
|
||||
|
||||
set(PNG_ROOT ${LIBDIR}/png)
|
||||
|
@@ -114,12 +114,11 @@ def makefile_log() -> List[str]:
|
||||
print("Can't execute process")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
while process.poll():
|
||||
time.sleep(1)
|
||||
|
||||
# We know this is always true based on the input arguments to `Popen`.
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
|
||||
out = stdout.read()
|
||||
stdout.close()
|
||||
@@ -210,7 +209,7 @@ def build_defines_as_source() -> str:
|
||||
)
|
||||
|
||||
# We know this is always true based on the input arguments to `Popen`.
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
stdout: IO[bytes] = process.stdout # type: ignore
|
||||
|
||||
return cast(str, stdout.read().strip().decode('ascii'))
|
||||
|
||||
@@ -228,7 +227,7 @@ def build_defines_as_args() -> List[str]:
|
||||
def queue_processes(
|
||||
process_funcs: Sequence[Tuple[Callable[..., subprocess.Popen[Any]], Tuple[Any, ...]]],
|
||||
*,
|
||||
job_total: int =-1,
|
||||
job_total: int = -1,
|
||||
sleep: float = 0.1,
|
||||
) -> None:
|
||||
""" Takes a list of function arg pairs, each function must return a process
|
||||
|
@@ -143,8 +143,8 @@ def packages_path(current_directory: Path, cli_args: Any) -> Optional[Path]:
|
||||
|
||||
return Path(relpath)
|
||||
|
||||
|
||||
### Manifest creation
|
||||
# -----------------------------------------------------------------------------
|
||||
# Manifest creation
|
||||
|
||||
|
||||
def create_manifest(
|
||||
@@ -195,7 +195,8 @@ def packages_to_manifest(outfile: TextIO, packages_dir: Path) -> None:
|
||||
print(path, file=outfile)
|
||||
|
||||
|
||||
### Higher-level functions
|
||||
# -----------------------------------------------------------------------------
|
||||
# Higher-level functions
|
||||
|
||||
|
||||
def create_tarball(
|
||||
@@ -249,7 +250,8 @@ def cleanup(manifest: Path) -> None:
|
||||
print("OK")
|
||||
|
||||
|
||||
## Low-level commands
|
||||
# -----------------------------------------------------------------------------
|
||||
# Low-level commands
|
||||
|
||||
|
||||
def git_ls_files(directory: Path = Path(".")) -> Iterable[Path]:
|
||||
@@ -265,7 +267,7 @@ def git_ls_files(directory: Path = Path(".")) -> Iterable[Path]:
|
||||
yield path
|
||||
|
||||
|
||||
def git_command(*cli_args: Union[bytes, str, Path] ) -> Iterable[str]:
|
||||
def git_command(*cli_args: Union[bytes, str, Path]) -> Iterable[str]:
|
||||
"""Generator, yields lines of output from a Git command."""
|
||||
command = ("git", *cli_args)
|
||||
|
||||
|
@@ -129,6 +129,7 @@ def svn_update(args, release_version):
|
||||
call(svn_non_interactive + ["switch", svn_url + dirname, dirpath], exit_on_error=False)
|
||||
call(svn_non_interactive + ["update", dirpath])
|
||||
|
||||
|
||||
# Test if git repo can be updated.
|
||||
def git_update_skip(args, check_remote_exists=True):
|
||||
if make_utils.command_missing(args.git_command):
|
||||
|
@@ -47,8 +47,10 @@ def check_output(cmd, exit_on_error=True):
|
||||
|
||||
|
||||
def git_branch_exists(git_command, branch):
|
||||
return call([git_command, "rev-parse", "--verify", branch], exit_on_error=False, silent=True) == 0 or \
|
||||
call([git_command, "rev-parse", "--verify", "remotes/origin/" + branch], exit_on_error=False, silent=True) == 0
|
||||
return (
|
||||
call([git_command, "rev-parse", "--verify", branch], exit_on_error=False, silent=True) == 0 or
|
||||
call([git_command, "rev-parse", "--verify", "remotes/origin/" + branch], exit_on_error=False, silent=True) == 0
|
||||
)
|
||||
|
||||
|
||||
def git_branch(git_command):
|
||||
|
@@ -378,7 +378,8 @@ def usage():
|
||||
|
||||
def main():
|
||||
|
||||
import os, os.path
|
||||
import os
|
||||
import os.path
|
||||
|
||||
try:
|
||||
bpy = __import__('bpy')
|
||||
|
@@ -103,10 +103,10 @@ blender \- a full-featured 3D application''')
|
||||
.PP
|
||||
.B blender
|
||||
is a full-featured 3D application. It supports the entirety of the 3D pipeline - '''
|
||||
'''modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing.
|
||||
'''modeling, rigging, animation, simulation, rendering, compositing, motion tracking, and video editing.
|
||||
|
||||
Use Blender to create 3D images and animations, films and commercials, content for games, '''
|
||||
r'''architectural and industrial visualizations, and scientific visualizations.
|
||||
r'''architectural and industrial visualizations, and scientific visualizations.
|
||||
|
||||
https://www.blender.org''')
|
||||
|
||||
|
@@ -11,6 +11,7 @@ import queue
|
||||
|
||||
execution_queue = queue.Queue()
|
||||
|
||||
|
||||
# This function can safely be called in another thread.
|
||||
# The function will be executed when the timer runs the next time.
|
||||
def run_in_main_thread(function):
|
||||
|
@@ -9,7 +9,7 @@ operator in the different part of the user interface.
|
||||
The context overrides are passed as a dictionary, with keys matching the context
|
||||
member names in bpy.context.
|
||||
For example to override ``bpy.context.active_object``,
|
||||
you would pass ``{'active_object': object}``.
|
||||
you would pass ``{'active_object': object}`` to :class:`bpy.types.Context.temp_override`.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -17,8 +17,10 @@ you would pass ``{'active_object': object}``.
|
||||
(otherwise, you'll have to find and gather all needed data yourself).
|
||||
"""
|
||||
|
||||
# remove all objects in scene rather than the selected ones
|
||||
# Remove all objects in scene rather than the selected ones.
|
||||
import bpy
|
||||
override = bpy.context.copy()
|
||||
override['selected_objects'] = list(bpy.context.scene.objects)
|
||||
bpy.ops.object.delete(override)
|
||||
from bpy import context
|
||||
override = context.copy()
|
||||
override["selected_objects"] = list(context.scene.objects)
|
||||
with context.temp_override(**override):
|
||||
bpy.ops.object.delete()
|
||||
|
@@ -1,17 +1,16 @@
|
||||
"""
|
||||
It is also possible to run an operator in a particular part of the user
|
||||
interface. For this we need to pass the window, screen, area and sometimes
|
||||
a region.
|
||||
interface. For this we need to pass the window, area and sometimes a region.
|
||||
"""
|
||||
|
||||
# maximize 3d view in all windows
|
||||
# Maximize 3d view in all windows.
|
||||
import bpy
|
||||
from bpy import context
|
||||
|
||||
for window in bpy.context.window_manager.windows:
|
||||
for window in context.window_manager.windows:
|
||||
screen = window.screen
|
||||
|
||||
for area in screen.areas:
|
||||
if area.type == 'VIEW_3D':
|
||||
override = {'window': window, 'screen': screen, 'area': area}
|
||||
bpy.ops.screen.screen_full_area(override)
|
||||
with context.temp_override(window=window, area=area):
|
||||
bpy.ops.screen.screen_full_area()
|
||||
break
|
||||
|
@@ -33,6 +33,11 @@ There are 3 optional positional arguments (documented in detail below).
|
||||
bpy.ops.test.operator(override_context, execution_context, undo)
|
||||
|
||||
- override_context - ``dict`` type.
|
||||
|
||||
.. deprecated:: 3.2
|
||||
|
||||
:class:`bpy.types.Context.temp_override` should be used instead of this argument.
|
||||
|
||||
- execution_context - ``str`` (enum).
|
||||
- undo - ``bool`` type.
|
||||
|
||||
|
@@ -4,6 +4,7 @@ the middle of updating the armature without having to update dependencies
|
||||
after each change, by manually carrying updated matrices in a recursive walk.
|
||||
"""
|
||||
|
||||
|
||||
def set_pose_matrices(obj, matrix_map):
|
||||
"Assign pose space matrices of all bones at once, ignoring constraints."
|
||||
|
||||
@@ -11,7 +12,7 @@ def set_pose_matrices(obj, matrix_map):
|
||||
if pbone.name in matrix_map:
|
||||
matrix = matrix_map[pbone.name]
|
||||
|
||||
## Instead of:
|
||||
# # Instead of:
|
||||
# pbone.matrix = matrix
|
||||
# bpy.context.view_layer.update()
|
||||
|
||||
|
19
doc/python_api/examples/bpy.types.Context.temp_override.1.py
Normal file
19
doc/python_api/examples/bpy.types.Context.temp_override.1.py
Normal file
@@ -0,0 +1,19 @@
|
||||
"""
|
||||
Overriding the context can be used to temporarily activate another ``window`` / ``area`` & ``region``,
|
||||
as well as other members such as the ``active_object`` or ``bone``.
|
||||
|
||||
Notes:
|
||||
|
||||
- When overriding window, area and regions: the arguments must be consistent,
|
||||
so any region argument that's passed in must be contained by the current area or the area passed in.
|
||||
The same goes for the area needing to be contained in the current window.
|
||||
|
||||
- Temporary context overrides may be nested, when this is done, members will be added to the existing overrides.
|
||||
|
||||
- Context members are restored outside the scope of the context.
|
||||
The only exception to this is when the data is no longer available.
|
||||
|
||||
In the event windowing data was removed (for example), the state of the context is left as-is.
|
||||
While this isn't likely to happen, explicit window operation such as closing windows or loading a new file
|
||||
remove the windowing data that was set before the temporary context was created.
|
||||
"""
|
15
doc/python_api/examples/bpy.types.Context.temp_override.2.py
Normal file
15
doc/python_api/examples/bpy.types.Context.temp_override.2.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Overriding the context can be useful to set the context after loading files
|
||||
(which would otherwise by None). For example:
|
||||
"""
|
||||
|
||||
import bpy
|
||||
from bpy import context
|
||||
|
||||
# Reload the current file and select all.
|
||||
bpy.ops.wm.open_mainfile(filepath=bpy.data.filepath)
|
||||
window = context.window_manager.windows[0]
|
||||
with context.temp_override(window=window):
|
||||
bpy.ops.mesh.primitive_uv_sphere_add()
|
||||
# The context override is needed so it's possible to set edit-mode.
|
||||
bpy.ops.object.mode_set(mode='EDIT')
|
16
doc/python_api/examples/bpy.types.Context.temp_override.3.py
Normal file
16
doc/python_api/examples/bpy.types.Context.temp_override.3.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
This example shows how it's possible to add an object to the scene in another window.
|
||||
"""
|
||||
import bpy
|
||||
from bpy import context
|
||||
|
||||
win_active = context.window
|
||||
win_other = None
|
||||
for win_iter in context.window_manager.windows:
|
||||
if win_iter != win_active:
|
||||
win_other = win_iter
|
||||
break
|
||||
|
||||
# Add cube in the other window.
|
||||
with context.temp_override(window=win_other):
|
||||
bpy.ops.mesh.primitive_cube_add()
|
@@ -42,10 +42,12 @@ class SimpleMouseOperator(bpy.types.Operator):
|
||||
self.y = event.mouse_y
|
||||
return self.execute(context)
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(SimpleMouseOperator.bl_idname, text="Simple Mouse Operator")
|
||||
|
||||
|
||||
# Register and add to the view menu (required to also use F3 search "Simple Mouse Operator" for quick access)
|
||||
bpy.utils.register_class(SimpleMouseOperator)
|
||||
bpy.types.VIEW3D_MT_view.append(menu_func)
|
||||
|
@@ -37,7 +37,7 @@ class ExportSomeData(bpy.types.Operator):
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator_context = 'INVOKE_DEFAULT'
|
||||
self.layout.operator(ExportSomeData.bl_idname, text="Text Export Operator")
|
||||
|
@@ -27,7 +27,8 @@ class DialogOperator(bpy.types.Operator):
|
||||
wm = context.window_manager
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(DialogOperator.bl_idname, text="Dialog Operator")
|
||||
|
||||
|
@@ -41,11 +41,13 @@ class CustomDrawOperator(bpy.types.Operator):
|
||||
|
||||
col.prop(self, "my_string")
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(CustomDrawOperator.bl_idname, text="Custom Draw Operator")
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Custom Draw Operator" for quick access)
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Custom Draw Operator" for quick access).
|
||||
bpy.utils.register_class(CustomDrawOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
|
@@ -55,11 +55,13 @@ class ModalOperator(bpy.types.Operator):
|
||||
context.window_manager.modal_handler_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(ModalOperator.bl_idname, text="Modal Operator")
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Modal Operator" for quick access)
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Modal Operator" for quick access).
|
||||
bpy.utils.register_class(ModalOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
||||
|
@@ -31,10 +31,12 @@ class SearchEnumOperator(bpy.types.Operator):
|
||||
context.window_manager.invoke_search_popup(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(SearchEnumOperator.bl_idname, text="Search Enum Operator")
|
||||
|
||||
|
||||
# Register and add to the object menu (required to also use F3 search "Search Enum Operator" for quick access)
|
||||
bpy.utils.register_class(SearchEnumOperator)
|
||||
bpy.types.VIEW3D_MT_object.append(menu_func)
|
||||
|
@@ -22,13 +22,15 @@ class HelloWorldOperator(bpy.types.Operator):
|
||||
print("Hello World")
|
||||
return {'FINISHED'}
|
||||
|
||||
# Only needed if you want to add into a dynamic menu
|
||||
|
||||
# Only needed if you want to add into a dynamic menu.
|
||||
def menu_func(self, context):
|
||||
self.layout.operator(HelloWorldOperator.bl_idname, text="Hello World Operator")
|
||||
|
||||
# Register and add to the view menu (required to also use F3 search "Hello World Operator" for quick access)
|
||||
|
||||
# Register and add to the view menu (required to also use F3 search "Hello World Operator" for quick access).
|
||||
bpy.utils.register_class(HelloWorldOperator)
|
||||
bpy.types.VIEW3D_MT_view.append(menu_func)
|
||||
|
||||
# test call to the newly defined operator
|
||||
# Test call to the newly defined operator.
|
||||
bpy.ops.wm.hello_world()
|
||||
|
@@ -93,7 +93,7 @@ Consider the calculations that might contribute to the object's final transforma
|
||||
- Animation function curves.
|
||||
- Drivers and their Python expressions.
|
||||
- Constraints
|
||||
- Parent objects and all of their F-curves, constraints, etc.
|
||||
- Parent objects and all of their F-Curves, constraints, etc.
|
||||
|
||||
To avoid expensive recalculations every time a property is modified,
|
||||
Blender defers the evaluation until the results are needed.
|
||||
@@ -802,7 +802,7 @@ Removing Data
|
||||
-------------
|
||||
|
||||
**Any** data that you remove shouldn't be modified or accessed afterwards,
|
||||
this includes: F-curves, drivers, render layers, timeline markers, modifiers, constraints
|
||||
this includes: F-Curves, drivers, render layers, timeline markers, modifiers, constraints
|
||||
along with objects, scenes, collections, bones, etc.
|
||||
|
||||
The ``remove()`` API calls will invalidate the data they free to prevent common mistakes.
|
||||
|
@@ -409,7 +409,9 @@ BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 Git hash
|
||||
BLENDER_VERSION_HASH = BLENDER_REVISION
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % (BLENDER_VERSION_HASH, BLENDER_VERSION_HASH)
|
||||
BLENDER_VERSION_HASH_HTML_LINK = "<a href=https://developer.blender.org/rB%s>%s</a>" % (
|
||||
BLENDER_VERSION_HASH, BLENDER_VERSION_HASH,
|
||||
)
|
||||
BLENDER_VERSION_DATE = time.strftime("%d/%m/%Y", time.localtime(BLENDER_REVISION_TIMESTAMP))
|
||||
else:
|
||||
# Fallback: Should not be used
|
||||
@@ -573,7 +575,7 @@ def example_extract_docstring(filepath):
|
||||
line_no += 1
|
||||
|
||||
file.close()
|
||||
return "\n".join(text), line_no, line_no_has_content
|
||||
return "\n".join(text).rstrip("\n"), line_no, line_no_has_content
|
||||
|
||||
|
||||
def title_string(text, heading_char, double=False):
|
||||
@@ -593,9 +595,13 @@ def write_example_ref(ident, fw, example_id, ext="py"):
|
||||
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
|
||||
|
||||
text, line_no, line_no_has_content = example_extract_docstring(filepath_full)
|
||||
if text:
|
||||
# Ensure a blank line, needed since in some cases the indentation doesn't match the previous line.
|
||||
# which causes Sphinx not to warn about bad indentation.
|
||||
fw("\n")
|
||||
for line in text.split("\n"):
|
||||
fw("%s\n" % (ident + line).rstrip())
|
||||
|
||||
for line in text.split("\n"):
|
||||
fw("%s\n" % (ident + line).rstrip())
|
||||
fw("\n")
|
||||
|
||||
# Some files only contain a doc-string.
|
||||
@@ -1147,6 +1153,9 @@ def pycontext2sphinx(basepath):
|
||||
fw("Note that all context values are readonly,\n")
|
||||
fw("but may be modified through the data API or by running operators\n\n")
|
||||
|
||||
# Track all unique properties to properly use `noindex`.
|
||||
unique = set()
|
||||
|
||||
def write_contex_cls():
|
||||
|
||||
fw(title_string("Global Context", "-"))
|
||||
@@ -1164,9 +1173,11 @@ def pycontext2sphinx(basepath):
|
||||
|
||||
# First write RNA
|
||||
for prop in sorted_struct_properties:
|
||||
# support blacklisting props
|
||||
# Support blacklisting props.
|
||||
if prop.identifier in struct_blacklist:
|
||||
continue
|
||||
# No need to check if there are duplicates yet as it's known there wont be.
|
||||
unique.add(prop.identifier)
|
||||
|
||||
type_descr = prop.get_type_description(
|
||||
class_fmt=":class:`bpy.types.%s`", collection_id=_BPY_PROP_COLLECTION_ID)
|
||||
@@ -1204,7 +1215,8 @@ def pycontext2sphinx(basepath):
|
||||
"file_context_dir",
|
||||
)
|
||||
|
||||
unique = set()
|
||||
# Track unique for `context_strings` to validate `context_type_map`.
|
||||
unique_context_strings = set()
|
||||
blend_cdll = ctypes.CDLL("")
|
||||
for ctx_str in context_strings:
|
||||
subsection = "%s Context" % ctx_str.split("_")[0].title()
|
||||
@@ -1216,22 +1228,34 @@ def pycontext2sphinx(basepath):
|
||||
i = 0
|
||||
while char_array[i] is not None:
|
||||
member = ctypes.string_at(char_array[i]).decode(encoding="ascii")
|
||||
fw(".. data:: %s\n\n" % member)
|
||||
unique_all_len = len(unique)
|
||||
unique.add(member)
|
||||
member_visited = unique_all_len == len(unique)
|
||||
|
||||
unique_context_strings.add(member)
|
||||
|
||||
fw(".. data:: %s\n" % member)
|
||||
# Avoid warnings about the member being included multiple times.
|
||||
if member_visited:
|
||||
fw(" :noindex:\n")
|
||||
fw("\n")
|
||||
|
||||
try:
|
||||
member_type, is_seq = context_type_map[member]
|
||||
except KeyError:
|
||||
raise SystemExit("Error: context key %r not found in context_type_map; update %s" % (member, __file__)) from None
|
||||
raise SystemExit(
|
||||
"Error: context key %r not found in context_type_map; update %s" %
|
||||
(member, __file__)) from None
|
||||
fw(" :type: %s :class:`bpy.types.%s`\n\n" % ("sequence of " if is_seq else "", member_type))
|
||||
unique.add(member)
|
||||
i += 1
|
||||
|
||||
# generate typemap...
|
||||
# for member in sorted(unique):
|
||||
# for member in sorted(unique_context_strings):
|
||||
# print(' "%s": ("", False),' % member)
|
||||
if len(context_type_map) > len(unique):
|
||||
if len(context_type_map) > len(unique_context_strings):
|
||||
warnings.warn(
|
||||
"Some types are not used: %s" %
|
||||
str([member for member in context_type_map if member not in unique]))
|
||||
str([member for member in context_type_map if member not in unique_context_strings]))
|
||||
else:
|
||||
pass # will have raised an error above
|
||||
|
||||
|
27
extern/fast_float/LICENSE-MIT
vendored
Normal file
27
extern/fast_float/LICENSE-MIT
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 The fast_float authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
7
extern/fast_float/README.blender
vendored
Normal file
7
extern/fast_float/README.blender
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Project: fast_float
|
||||
URL: https://github.com/fastfloat/fast_float
|
||||
License: MIT
|
||||
Upstream version: 3.4.0 (b7f9d6c)
|
||||
Local modifications:
|
||||
|
||||
- Took only the fast_float.h header and the license/readme files
|
218
extern/fast_float/README.md
vendored
Normal file
218
extern/fast_float/README.md
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
## fast_float number parsing library: 4x faster than strtod
|
||||
|
||||
/badge.svg)
|
||||
/badge.svg)
|
||||

|
||||

|
||||

|
||||
[](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml)
|
||||
|
||||
The fast_float library provides fast header-only implementations for the C++ from_chars
|
||||
functions for `float` and `double` types. These functions convert ASCII strings representing
|
||||
decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including
|
||||
round to even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries.
|
||||
|
||||
Specifically, `fast_float` provides the following two functions with a C++17-like syntax (the library itself only requires C++11):
|
||||
|
||||
```C++
|
||||
from_chars_result from_chars(const char* first, const char* last, float& value, ...);
|
||||
from_chars_result from_chars(const char* first, const char* last, double& value, ...);
|
||||
```
|
||||
|
||||
The return type (`from_chars_result`) is defined as the struct:
|
||||
```C++
|
||||
struct from_chars_result {
|
||||
const char* ptr;
|
||||
std::errc ec;
|
||||
};
|
||||
```
|
||||
|
||||
It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
|
||||
a locale-independent format equivalent to the C++17 from_chars function.
|
||||
The resulting floating-point value is the closest floating-point values (using either float or double),
|
||||
using the "round to even" convention for values that would otherwise fall right in-between two values.
|
||||
That is, we provide exact parsing according to the IEEE standard.
|
||||
|
||||
|
||||
Given a successful parse, the pointer (`ptr`) in the returned value is set to point right after the
|
||||
parsed number, and the `value` referenced is set to the parsed value. In case of error, the returned
|
||||
`ec` contains a representative error, otherwise the default (`std::errc()`) value is stored.
|
||||
|
||||
The implementation does not throw and does not allocate memory (e.g., with `new` or `malloc`).
|
||||
|
||||
It will parse infinity and nan values.
|
||||
|
||||
Example:
|
||||
|
||||
``` C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "3.1416 xyz ";
|
||||
double result;
|
||||
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
|
||||
if(answer.ec != std::errc()) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
|
||||
the type `fast_float::chars_format`. It is a bitset value: we check whether
|
||||
`fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
|
||||
to determine whether we allow the fixed point and scientific notation respectively.
|
||||
The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
|
||||
|
||||
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
|
||||
* The `from_chars` function does not skip leading white-space characters.
|
||||
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden.
|
||||
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
|
||||
|
||||
Furthermore, we have the following restrictions:
|
||||
* We only support `float` and `double` types at this time.
|
||||
* We only support the decimal format: we do not support hexadecimal strings.
|
||||
* For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value.
|
||||
|
||||
We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems.
|
||||
|
||||
|
||||
|
||||
## Using commas as decimal separator
|
||||
|
||||
|
||||
The C++ standard stipulate that `from_chars` has to be locale-independent. In
|
||||
particular, the decimal separator has to be the period (`.`). However,
|
||||
some users still want to use the `fast_float` library with in a locale-dependent
|
||||
manner. Using a separate function called `from_chars_advanced`, we allow the users
|
||||
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
|
||||
the comma). You may use it as follows.
|
||||
|
||||
```C++
|
||||
#include "fast_float/fast_float.h"
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
const std::string input = "3,1416 xyz ";
|
||||
double result;
|
||||
fast_float::parse_options options{fast_float::chars_format::general, ','};
|
||||
auto answer = fast_float::from_chars_advanced(input.data(), input.data()+input.size(), result, options);
|
||||
if((answer.ec != std::errc()) || ((result != 3.1416))) { std::cerr << "parsing failure\n"; return EXIT_FAILURE; }
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Pratice and Experience 51 (8), 2021.
|
||||
|
||||
## Other programming languages
|
||||
|
||||
- [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called `rcppfastfloat`.
|
||||
- [There is a Rust port of the fast_float library](https://github.com/aldanor/fast-float-rust/) called `fast-float-rust`.
|
||||
- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`.
|
||||
- [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`.
|
||||
|
||||
|
||||
## Relation With Other Work
|
||||
|
||||
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
|
||||
|
||||
The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).
|
||||
|
||||
## Users
|
||||
|
||||
The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [Yandex ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet).
|
||||
|
||||
|
||||
## How fast is it?
|
||||
|
||||
It can parse random floating-point numbers at a speed of 1 GB/s on some systems. We find that it is often twice as fast as the best available competitor, and many times faster than many standard-library implementations.
|
||||
|
||||
<img src="http://lemire.me/blog/wp-content/uploads/2020/11/fastfloat_speed.png" width="400">
|
||||
|
||||
```
|
||||
$ ./build/benchmarks/benchmark
|
||||
# parsing random integers in the range [0,1)
|
||||
volume = 2.09808 MB
|
||||
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
|
||||
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
|
||||
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
|
||||
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
|
||||
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
|
||||
```
|
||||
|
||||
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
|
||||
|
||||
|
||||
## Video
|
||||
|
||||
[](http://www.youtube.com/watch?v=AVXgvlMeIm4)<br />
|
||||
|
||||
## Using as a CMake dependency
|
||||
|
||||
This library is header-only by design. The CMake file provides the `fast_float` target
|
||||
which is merely a pointer to the `include` directory.
|
||||
|
||||
If you drop the `fast_float` repository in your CMake project, you should be able to use
|
||||
it in this manner:
|
||||
|
||||
```cmake
|
||||
add_subdirectory(fast_float)
|
||||
target_link_libraries(myprogram PUBLIC fast_float)
|
||||
```
|
||||
|
||||
Or you may want to retrieve the dependency automatically if you have a sufficiently recent version of CMake (3.11 or better at least):
|
||||
|
||||
```cmake
|
||||
FetchContent_Declare(
|
||||
fast_float
|
||||
GIT_REPOSITORY https://github.com/lemire/fast_float.git
|
||||
GIT_TAG tags/v1.1.2
|
||||
GIT_SHALLOW TRUE)
|
||||
|
||||
FetchContent_MakeAvailable(fast_float)
|
||||
target_link_libraries(myprogram PUBLIC fast_float)
|
||||
|
||||
```
|
||||
|
||||
You should change the `GIT_TAG` line so that you recover the version you wish to use.
|
||||
|
||||
## Using as single header
|
||||
|
||||
The script `script/amalgamate.py` may be used to generate a single header
|
||||
version of the library if so desired.
|
||||
Just run the script from the root directory of this repository.
|
||||
You can customize the license type and output file if desired as described in
|
||||
the command line help.
|
||||
|
||||
You may directly download automatically generated single-header files:
|
||||
|
||||
https://github.com/fastfloat/fast_float/releases/download/v1.1.2/fast_float.h
|
||||
|
||||
## Credit
|
||||
|
||||
Though this work is inspired by many different people, this work benefited especially from exchanges with
|
||||
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
|
||||
invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits.
|
||||
|
||||
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
|
||||
under the Apache 2.0 license.
|
||||
|
||||
## License
|
||||
|
||||
<sup>
|
||||
Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
|
||||
2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
|
||||
</sup>
|
||||
|
||||
<br>
|
||||
|
||||
<sub>
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this repository by you, as defined in the Apache-2.0 license,
|
||||
shall be dual licensed as above, without any additional terms or conditions.
|
||||
</sub>
|
2979
extern/fast_float/fast_float.h
vendored
Normal file
2979
extern/fast_float/fast_float.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ import bpy
|
||||
from bpy_extras.io_utils import ExportHelper
|
||||
from bpy.props import PointerProperty, StringProperty
|
||||
|
||||
|
||||
def strip(root):
|
||||
root.text = None
|
||||
root.tail = None
|
||||
@@ -17,6 +18,7 @@ def strip(root):
|
||||
for elem in root:
|
||||
strip(elem)
|
||||
|
||||
|
||||
def write(node, fname):
|
||||
strip(node)
|
||||
|
||||
@@ -26,25 +28,31 @@ def write(node, fname):
|
||||
f = open(fname, "w")
|
||||
f.write(s)
|
||||
|
||||
|
||||
class CyclesXMLSettings(bpy.types.PropertyGroup):
|
||||
@classmethod
|
||||
def register(cls):
|
||||
bpy.types.Scene.cycles_xml = PointerProperty(
|
||||
type=cls,
|
||||
name="Cycles XML export Settings",
|
||||
description="Cycles XML export settings")
|
||||
type=cls,
|
||||
name="Cycles XML export Settings",
|
||||
description="Cycles XML export settings",
|
||||
)
|
||||
cls.filepath = StringProperty(
|
||||
name='Filepath',
|
||||
description='Filepath for the .xml file',
|
||||
maxlen=256,
|
||||
default='',
|
||||
subtype='FILE_PATH')
|
||||
name='Filepath',
|
||||
description='Filepath for the .xml file',
|
||||
maxlen=256,
|
||||
default='',
|
||||
subtype='FILE_PATH',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def unregister(cls):
|
||||
del bpy.types.Scene.cycles_xml
|
||||
|
||||
# User Interface Drawing Code
|
||||
|
||||
# User Interface Drawing Code.
|
||||
|
||||
|
||||
class RenderButtonsPanel():
|
||||
bl_space_type = 'PROPERTIES'
|
||||
bl_region_type = 'WINDOW'
|
||||
@@ -114,22 +122,31 @@ class ExportCyclesXML(bpy.types.Operator, ExportHelper):
|
||||
uvs += str(uvf.uv1[0]) + " " + str(uvf.uv1[1]) + " "
|
||||
uvs += str(uvf.uv2[0]) + " " + str(uvf.uv2[1]) + " "
|
||||
uvs += str(uvf.uv3[0]) + " " + str(uvf.uv3[1]) + " "
|
||||
if vcount==4:
|
||||
if vcount == 4:
|
||||
uvs += " " + str(uvf.uv4[0]) + " " + str(uvf.uv4[1]) + " "
|
||||
|
||||
|
||||
node = etree.Element('mesh', attrib={'nverts': nverts.strip(), 'verts': verts.strip(), 'P': P, 'UV' : uvs.strip()})
|
||||
node = etree.Element(
|
||||
'mesh',
|
||||
attrib={
|
||||
'nverts': nverts.strip(),
|
||||
'verts': verts.strip(),
|
||||
'P': P,
|
||||
'UV': uvs.strip(),
|
||||
})
|
||||
|
||||
# write to file
|
||||
write(node, filepath)
|
||||
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
register()
|
||||
|
@@ -4,11 +4,14 @@
|
||||
# <pep8 compliant>
|
||||
|
||||
# Fit to match default projective camera with focal_length 50 and sensor_width 36.
|
||||
default_fisheye_polynomial = [-1.1735143712967577e-05,
|
||||
-0.019988736953434998,
|
||||
-3.3525322965709175e-06,
|
||||
3.099275275886036e-06,
|
||||
-2.6064646454854524e-08]
|
||||
default_fisheye_polynomial = [
|
||||
-1.1735143712967577e-05,
|
||||
-0.019988736953434998,
|
||||
-3.3525322965709175e-06,
|
||||
3.099275275886036e-06,
|
||||
-2.6064646454854524e-08,
|
||||
]
|
||||
|
||||
|
||||
# Utilities to generate lens polynomials to match built-in camera types, only here
|
||||
# for reference at the moment, not used by the code.
|
||||
@@ -51,7 +54,9 @@ def fisheye_lens_polynomial_from_equidistant(fov=180, sensor_width=36, sensor_he
|
||||
return [0, -np.radians(fov) / sensor_width, 0, 0, 0]
|
||||
|
||||
|
||||
def fisheye_lens_polynomial_from_distorted_projective_polynomial(k1, k2, k3, focal_length=50, sensor_width=36, sensor_height=None):
|
||||
def fisheye_lens_polynomial_from_distorted_projective_polynomial(
|
||||
k1, k2, k3, focal_length=50, sensor_width=36, sensor_height=None,
|
||||
):
|
||||
import numpy as np
|
||||
rr = create_grid(sensor_height, sensor_width)
|
||||
r2 = (rr / focal_length) ** 2
|
||||
@@ -61,7 +66,10 @@ def fisheye_lens_polynomial_from_distorted_projective_polynomial(k1, k2, k3, foc
|
||||
polynomial = np.polyfit(rr.flat, (-np.arctan(rr / focal_length * r_coeff)).flat, 4)
|
||||
return list(reversed(polynomial))
|
||||
|
||||
def fisheye_lens_polynomial_from_distorted_projective_divisions(k1, k2, focal_length=50, sensor_width=36, sensor_height=None):
|
||||
|
||||
def fisheye_lens_polynomial_from_distorted_projective_divisions(
|
||||
k1, k2, focal_length=50, sensor_width=36, sensor_height=None,
|
||||
):
|
||||
import numpy as np
|
||||
rr = create_grid(sensor_height, sensor_width)
|
||||
r2 = (rr / focal_length) ** 2
|
||||
|
@@ -98,6 +98,7 @@ def render_frame_finish(engine):
|
||||
import _cycles
|
||||
_cycles.render_frame_finish(engine.session)
|
||||
|
||||
|
||||
def draw(engine, depsgraph, space_image):
|
||||
if not engine.session:
|
||||
return
|
||||
@@ -168,6 +169,9 @@ def list_render_passes(scene, srl):
|
||||
# Combined pass.
|
||||
yield ("Combined", "RGBA", 'COLOR')
|
||||
|
||||
# Keep alignment for readability.
|
||||
# autopep8: off
|
||||
|
||||
# Data passes.
|
||||
if srl.use_pass_z: yield ("Depth", "Z", 'VALUE')
|
||||
if srl.use_pass_mist: yield ("Mist", "Z", 'VALUE')
|
||||
@@ -195,9 +199,11 @@ def list_render_passes(scene, srl):
|
||||
if srl.use_pass_shadow: yield ("Shadow", "RGB", 'COLOR')
|
||||
if srl.use_pass_ambient_occlusion: yield ("AO", "RGB", 'COLOR')
|
||||
if crl.use_pass_shadow_catcher: yield ("Shadow Catcher", "RGB", 'COLOR')
|
||||
# autopep8: on
|
||||
|
||||
# Debug passes.
|
||||
if crl.pass_debug_sample_count: yield ("Debug Sample Count", "X", 'VALUE')
|
||||
if crl.pass_debug_sample_count:
|
||||
yield ("Debug Sample Count", "X", 'VALUE')
|
||||
|
||||
# Cryptomatte passes.
|
||||
crypto_depth = (srl.pass_cryptomatte_depth + 1) // 2
|
||||
@@ -217,16 +223,16 @@ def list_render_passes(scene, srl):
|
||||
if crl.use_pass_shadow_catcher:
|
||||
yield ("Noisy Shadow Catcher", "RGBA", 'COLOR')
|
||||
if crl.denoising_store_passes:
|
||||
yield ("Denoising Normal", "XYZ", 'VECTOR')
|
||||
yield ("Denoising Albedo", "RGB", 'COLOR')
|
||||
yield ("Denoising Depth", "Z", 'VALUE')
|
||||
yield ("Denoising Normal", "XYZ", 'VECTOR')
|
||||
yield ("Denoising Albedo", "RGB", 'COLOR')
|
||||
yield ("Denoising Depth", "Z", 'VALUE')
|
||||
|
||||
# Custom AOV passes.
|
||||
for aov in srl.aovs:
|
||||
if aov.type == 'VALUE':
|
||||
yield (aov.name, "X", 'VALUE')
|
||||
else:
|
||||
yield (aov.name, "RGB", 'COLOR')
|
||||
yield (aov.name, "RGBA", 'COLOR')
|
||||
|
||||
# Light groups.
|
||||
for lightgroup in srl.lightgroups:
|
||||
|
@@ -34,8 +34,8 @@ class CYCLES_OT_use_shading_nodes(Operator):
|
||||
|
||||
class CYCLES_OT_denoise_animation(Operator):
|
||||
"Denoise rendered animation sequence using current scene and view " \
|
||||
"layer settings. Requires denoising data passes and output to " \
|
||||
"OpenEXR multilayer files"
|
||||
"layer settings. Requires denoising data passes and output to " \
|
||||
"OpenEXR multilayer files"
|
||||
bl_idname = "cycles.denoise_animation"
|
||||
bl_label = "Denoise Animation"
|
||||
|
||||
@@ -117,7 +117,7 @@ class CYCLES_OT_denoise_animation(Operator):
|
||||
|
||||
class CYCLES_OT_merge_images(Operator):
|
||||
"Combine OpenEXR multilayer images rendered with different sample " \
|
||||
"ranges into one image with reduced noise"
|
||||
"ranges into one image with reduced noise"
|
||||
bl_idname = "cycles.merge_images"
|
||||
bl_label = "Merge Images"
|
||||
|
||||
|
@@ -85,6 +85,7 @@ class AddPresetViewportSampling(AddPresetBase, Operator):
|
||||
|
||||
preset_subdir = "cycles/viewport_sampling"
|
||||
|
||||
|
||||
classes = (
|
||||
AddPresetIntegrator,
|
||||
AddPresetSampling,
|
||||
|
@@ -83,7 +83,8 @@ enum_sampling_pattern = (
|
||||
enum_volume_sampling = (
|
||||
('DISTANCE', "Distance", "Use distance sampling, best for dense volumes with lights far away"),
|
||||
('EQUIANGULAR', "Equiangular", "Use equiangular sampling, best for volumes with low density with light inside or near the volume"),
|
||||
('MULTIPLE_IMPORTANCE', "Multiple Importance", "Combine distance and equi-angular sampling for volumes where neither method is ideal"),
|
||||
('MULTIPLE_IMPORTANCE', "Multiple Importance",
|
||||
"Combine distance and equi-angular sampling for volumes where neither method is ideal"),
|
||||
)
|
||||
|
||||
enum_volume_interpolation = (
|
||||
@@ -181,7 +182,12 @@ def enum_preview_denoiser(self, context):
|
||||
oidn_items = enum_openimagedenoise_denoiser(self, context)
|
||||
|
||||
if len(optix_items) or len(oidn_items):
|
||||
items = [('AUTO', "Automatic", "Use the fastest available denoiser for viewport rendering (OptiX if available, OpenImageDenoise otherwise)", 0)]
|
||||
items = [
|
||||
('AUTO',
|
||||
"Automatic",
|
||||
("Use the fastest available denoiser for viewport rendering "
|
||||
"(OptiX if available, OpenImageDenoise otherwise)"),
|
||||
0)]
|
||||
else:
|
||||
items = [('AUTO', "None", "Blender was compiled without a viewport denoiser", 0)]
|
||||
|
||||
@@ -210,11 +216,14 @@ enum_denoising_prefilter = (
|
||||
)
|
||||
|
||||
enum_direct_light_sampling_type = (
|
||||
('MULTIPLE_IMPORTANCE_SAMPLING', "Multiple Importance Sampling", "Multiple importance sampling is used to combine direct light contributions from next-event estimation and forward path tracing", 0),
|
||||
('MULTIPLE_IMPORTANCE_SAMPLING', "Multiple Importance Sampling",
|
||||
"Multiple importance sampling is used to combine direct light contributions from next-event estimation and forward path tracing", 0),
|
||||
('FORWARD_PATH_TRACING', "Forward Path Tracing", "Direct light contributions are only sampled using forward path tracing", 1),
|
||||
('NEXT_EVENT_ESTIMATION', "Next-Event Estimation", "Direct light contributions are only sampled using next-event estimation", 2),
|
||||
('NEXT_EVENT_ESTIMATION', "Next-Event Estimation",
|
||||
"Direct light contributions are only sampled using next-event estimation", 2),
|
||||
)
|
||||
|
||||
|
||||
def update_render_passes(self, context):
|
||||
view_layer = context.view_layer
|
||||
view_layer.update_render_passes()
|
||||
@@ -262,7 +271,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
|
||||
description="Denoise the image with the selected denoiser. "
|
||||
"For denoising the image after rendering",
|
||||
items=enum_denoiser,
|
||||
default=4, # Use integer to avoid error in builds without OpenImageDenoise.
|
||||
default=4, # Use integer to avoid error in builds without OpenImageDenoise.
|
||||
update=update_render_passes,
|
||||
)
|
||||
denoising_prefilter: EnumProperty(
|
||||
@@ -1507,7 +1516,7 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
col.label(text="and NVIDIA driver version 470 or newer", icon='BLANK1')
|
||||
elif device_type == 'HIP':
|
||||
import sys
|
||||
col.label(text="Requires discrete AMD GPU with Vega architecture", icon='BLANK1')
|
||||
col.label(text="Requires discrete AMD GPU with RDNA architecture", icon='BLANK1')
|
||||
if sys.platform[:3] == "win":
|
||||
col.label(text="and AMD Radeon Pro 21.Q4 driver or newer", icon='BLANK1')
|
||||
elif device_type == 'METAL':
|
||||
@@ -1547,7 +1556,6 @@ class CyclesPreferences(bpy.types.AddonPreferences):
|
||||
row.use_property_split = True
|
||||
row.prop(self, "use_metalrt")
|
||||
|
||||
|
||||
def draw(self, context):
|
||||
self.draw_impl(self.layout, context)
|
||||
|
||||
|
@@ -14,6 +14,7 @@ from bl_ui.properties_grease_pencil_common import GreasePencilSimplifyPanel
|
||||
from bl_ui.properties_render import draw_curves_settings
|
||||
from bl_ui.properties_view_layer import ViewLayerCryptomattePanel, ViewLayerAOVPanel, ViewLayerLightgroupsPanel
|
||||
|
||||
|
||||
class CyclesPresetPanel(PresetPanel, Panel):
|
||||
COMPAT_ENGINES = {'CYCLES'}
|
||||
preset_operator = "script.execute_preset"
|
||||
@@ -25,16 +26,19 @@ class CyclesPresetPanel(PresetPanel, Panel):
|
||||
render = context.scene.render
|
||||
render.filter_size = render.filter_size
|
||||
|
||||
|
||||
class CYCLES_PT_sampling_presets(CyclesPresetPanel):
|
||||
bl_label = "Sampling Presets"
|
||||
preset_subdir = "cycles/sampling"
|
||||
preset_add_operator = "render.cycles_sampling_preset_add"
|
||||
|
||||
|
||||
class CYCLES_PT_viewport_sampling_presets(CyclesPresetPanel):
|
||||
bl_label = "Viewport Sampling Presets"
|
||||
preset_subdir = "cycles/viewport_sampling"
|
||||
preset_add_operator = "render.cycles_viewport_sampling_preset_add"
|
||||
|
||||
|
||||
class CYCLES_PT_integrator_presets(CyclesPresetPanel):
|
||||
bl_label = "Integrator Presets"
|
||||
preset_subdir = "cycles/integrator"
|
||||
@@ -90,6 +94,7 @@ def use_metal(context):
|
||||
|
||||
return (get_device_type(context) == 'METAL' and cscene.device == 'GPU')
|
||||
|
||||
|
||||
def use_cuda(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
@@ -101,11 +106,13 @@ def use_hip(context):
|
||||
|
||||
return (get_device_type(context) == 'HIP' and cscene.device == 'GPU')
|
||||
|
||||
|
||||
def use_optix(context):
|
||||
cscene = context.scene.cycles
|
||||
|
||||
return (get_device_type(context) == 'OPTIX' and cscene.device == 'GPU')
|
||||
|
||||
|
||||
def use_multi_device(context):
|
||||
cscene = context.scene.cycles
|
||||
if cscene.device != 'GPU':
|
||||
@@ -133,7 +140,6 @@ def get_effective_preview_denoiser(context):
|
||||
return 'OIDN'
|
||||
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_sampling(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Sampling"
|
||||
|
||||
@@ -353,6 +359,7 @@ class CYCLES_RENDER_PT_curves(CyclesButtonsPanel, Panel):
|
||||
if ccscene.shape == 'RIBBONS':
|
||||
col.prop(ccscene, "subdivisions", text="Curve Subdivisions")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_curves_viewport_display(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Viewport Display"
|
||||
bl_parent_id = "CYCLES_RENDER_PT_curves"
|
||||
@@ -361,6 +368,7 @@ class CYCLES_RENDER_PT_curves_viewport_display(CyclesButtonsPanel, Panel):
|
||||
def draw(self, context):
|
||||
draw_curves_settings(self, context)
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_volumes(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Volumes"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -478,10 +486,10 @@ class CYCLES_RENDER_PT_light_paths_fast_gi(CyclesButtonsPanel, Panel):
|
||||
col.prop(cscene, "fast_gi_method", text="Method")
|
||||
|
||||
if world:
|
||||
light = world.light_settings
|
||||
col = layout.column(align=True)
|
||||
col.prop(light, "ao_factor", text="AO Factor")
|
||||
col.prop(light, "distance", text="AO Distance")
|
||||
light = world.light_settings
|
||||
col = layout.column(align=True)
|
||||
col.prop(light, "ao_factor", text="AO Factor")
|
||||
col.prop(light, "distance", text="AO Distance")
|
||||
|
||||
if cscene.fast_gi_method == 'REPLACE':
|
||||
col = layout.column(align=True)
|
||||
@@ -1034,7 +1042,8 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel):
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
if CyclesButtonsPanel.poll(context) and ob:
|
||||
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'CURVES', 'POINTCLOUD'}:
|
||||
if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT',
|
||||
'META', 'CAMERA', 'CURVES', 'POINTCLOUD', 'VOLUME'}:
|
||||
return True
|
||||
if ob.instance_type == 'COLLECTION' and ob.instance_collection:
|
||||
return True
|
||||
@@ -1446,7 +1455,14 @@ class CYCLES_WORLD_PT_surface(CyclesButtonsPanel, Panel):
|
||||
row.use_property_decorate = False
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.prop_search(world, "lightgroup", view_layer, "lightgroups", text="Light Group", results_are_suggestions=True)
|
||||
sub.prop_search(
|
||||
world,
|
||||
"lightgroup",
|
||||
view_layer,
|
||||
"lightgroups",
|
||||
text="Light Group",
|
||||
results_are_suggestions=True,
|
||||
)
|
||||
|
||||
sub = row.column(align=True)
|
||||
sub.active = bool(world.lightgroup) and not any(lg.name == world.lightgroup for lg in view_layer.lightgroups)
|
||||
@@ -1572,7 +1588,6 @@ class CYCLES_WORLD_PT_settings_surface(CyclesButtonsPanel, Panel):
|
||||
sub.prop(cworld, "is_caustics_light", text="Shadow Caustics")
|
||||
|
||||
|
||||
|
||||
class CYCLES_WORLD_PT_settings_volume(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Volume"
|
||||
bl_parent_id = "CYCLES_WORLD_PT_settings"
|
||||
@@ -1894,6 +1909,7 @@ class CYCLES_RENDER_PT_bake_output(CyclesButtonsPanel, Panel):
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "use_clear", text="Clear Image")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_bake_output_margin(CyclesButtonsPanel, Panel):
|
||||
bl_label = "Margin"
|
||||
bl_context = "render"
|
||||
@@ -1916,14 +1932,20 @@ class CYCLES_RENDER_PT_bake_output_margin(CyclesButtonsPanel, Panel):
|
||||
cbk = scene.render.bake
|
||||
rd = scene.render
|
||||
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin_type", text="Type")
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
if (cscene.bake_type == 'NORMAL' and cbk.normal_space == 'TANGENT') or cscene.bake_type == 'UV':
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
else:
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
else:
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin_type", text="Type")
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
|
||||
if rd.use_bake_multires:
|
||||
layout.prop(rd, "bake_margin_type", text="Type")
|
||||
layout.prop(rd, "bake_margin", text="Size")
|
||||
else:
|
||||
if cbk.target == 'IMAGE_TEXTURES':
|
||||
layout.prop(cbk, "margin_type", text="Type")
|
||||
layout.prop(cbk, "margin", text="Size")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_debug(CyclesDebugButtonsPanel, Panel):
|
||||
|
@@ -72,7 +72,7 @@ def do_versions(self):
|
||||
# Device might not currently be available so this can fail
|
||||
try:
|
||||
if system.legacy_compute_device_type == 1:
|
||||
prop.compute_device_type = 'NONE' # Was OpenCL
|
||||
prop.compute_device_type = 'NONE' # Was OpenCL
|
||||
elif system.legacy_compute_device_type == 2:
|
||||
prop.compute_device_type = 'CUDA'
|
||||
else:
|
||||
@@ -181,24 +181,24 @@ def do_versions(self):
|
||||
|
||||
if version <= (2, 92, 4):
|
||||
if scene.render.engine == 'CYCLES':
|
||||
for view_layer in scene.view_layers:
|
||||
cview_layer = view_layer.cycles
|
||||
view_layer.use_pass_cryptomatte_object = cview_layer.get("use_pass_crypto_object", False)
|
||||
view_layer.use_pass_cryptomatte_material = cview_layer.get("use_pass_crypto_material", False)
|
||||
view_layer.use_pass_cryptomatte_asset = cview_layer.get("use_pass_crypto_asset", False)
|
||||
view_layer.pass_cryptomatte_depth = cview_layer.get("pass_crypto_depth", 6)
|
||||
for view_layer in scene.view_layers:
|
||||
cview_layer = view_layer.cycles
|
||||
view_layer.use_pass_cryptomatte_object = cview_layer.get("use_pass_crypto_object", False)
|
||||
view_layer.use_pass_cryptomatte_material = cview_layer.get("use_pass_crypto_material", False)
|
||||
view_layer.use_pass_cryptomatte_asset = cview_layer.get("use_pass_crypto_asset", False)
|
||||
view_layer.pass_cryptomatte_depth = cview_layer.get("pass_crypto_depth", 6)
|
||||
|
||||
if version <= (2, 93, 7):
|
||||
if scene.render.engine == 'CYCLES':
|
||||
for view_layer in scene.view_layers:
|
||||
cview_layer = view_layer.cycles
|
||||
for caov in cview_layer.get("aovs", []):
|
||||
aov_name = caov.get("name", "AOV")
|
||||
if aov_name in view_layer.aovs:
|
||||
continue
|
||||
baov = view_layer.aovs.add()
|
||||
baov.name = caov.get("name", "AOV")
|
||||
baov.type = "COLOR" if caov.get("type", 1) == 1 else "VALUE"
|
||||
for view_layer in scene.view_layers:
|
||||
cview_layer = view_layer.cycles
|
||||
for caov in cview_layer.get("aovs", []):
|
||||
aov_name = caov.get("name", "AOV")
|
||||
if aov_name in view_layer.aovs:
|
||||
continue
|
||||
baov = view_layer.aovs.add()
|
||||
baov.name = caov.get("name", "AOV")
|
||||
baov.type = "COLOR" if caov.get("type", 1) == 1 else "VALUE"
|
||||
|
||||
if version <= (2, 93, 16):
|
||||
cscene = scene.cycles
|
||||
|
@@ -23,7 +23,7 @@ struct BlenderCamera {
|
||||
|
||||
float lens;
|
||||
float shuttertime;
|
||||
Camera::MotionPosition motion_position;
|
||||
MotionPosition motion_position;
|
||||
array<float> shutter_curve;
|
||||
|
||||
Camera::RollingShutterType rolling_shutter_type;
|
||||
@@ -114,7 +114,7 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings &b_rende
|
||||
bcam->sensor_width = 36.0f;
|
||||
bcam->sensor_height = 24.0f;
|
||||
bcam->sensor_fit = BlenderCamera::AUTO;
|
||||
bcam->motion_position = Camera::MOTION_POSITION_CENTER;
|
||||
bcam->motion_position = MOTION_POSITION_CENTER;
|
||||
bcam->border.right = 1.0f;
|
||||
bcam->border.top = 1.0f;
|
||||
bcam->viewport_camera_border.right = 1.0f;
|
||||
@@ -555,10 +555,8 @@ void BlenderSync::sync_camera(BL::RenderSettings &b_render,
|
||||
curvemapping_to_array(b_shutter_curve, bcam.shutter_curve, RAMP_TABLE_SIZE);
|
||||
|
||||
PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
|
||||
bcam.motion_position = (Camera::MotionPosition)get_enum(cscene,
|
||||
"motion_blur_position",
|
||||
Camera::MOTION_NUM_POSITIONS,
|
||||
Camera::MOTION_POSITION_CENTER);
|
||||
bcam.motion_position = (MotionPosition)get_enum(
|
||||
cscene, "motion_blur_position", MOTION_NUM_POSITIONS, MOTION_POSITION_CENTER);
|
||||
bcam.rolling_shutter_type = (Camera::RollingShutterType)get_enum(
|
||||
cscene,
|
||||
"rolling_shutter_type",
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "scene/shader.h"
|
||||
#include "scene/shader_graph.h"
|
||||
#include "scene/shader_nodes.h"
|
||||
#include "scene/volume.h"
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/hash.h"
|
||||
@@ -715,13 +716,13 @@ void BlenderSync::sync_motion(BL::RenderSettings &b_render,
|
||||
float frame_center_delta = 0.0f;
|
||||
|
||||
if (scene->need_motion() != Scene::MOTION_PASS &&
|
||||
scene->camera->get_motion_position() != Camera::MOTION_POSITION_CENTER) {
|
||||
scene->camera->get_motion_position() != MOTION_POSITION_CENTER) {
|
||||
float shuttertime = scene->camera->get_shuttertime();
|
||||
if (scene->camera->get_motion_position() == Camera::MOTION_POSITION_END) {
|
||||
if (scene->camera->get_motion_position() == MOTION_POSITION_END) {
|
||||
frame_center_delta = -shuttertime * 0.5f;
|
||||
}
|
||||
else {
|
||||
assert(scene->camera->get_motion_position() == Camera::MOTION_POSITION_START);
|
||||
assert(scene->camera->get_motion_position() == MOTION_POSITION_START);
|
||||
frame_center_delta = shuttertime * 0.5f;
|
||||
}
|
||||
|
||||
|
@@ -272,7 +272,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
|
||||
geometry_synced.clear(); /* use for objects and motion sync */
|
||||
|
||||
if (scene->need_motion() == Scene::MOTION_PASS || scene->need_motion() == Scene::MOTION_NONE ||
|
||||
scene->camera->get_motion_position() == Camera::MOTION_POSITION_CENTER) {
|
||||
scene->camera->get_motion_position() == MOTION_POSITION_CENTER) {
|
||||
sync_objects(b_depsgraph, b_v3d);
|
||||
}
|
||||
sync_motion(b_render, b_depsgraph, b_v3d, b_override, width, height, python_thread_state);
|
||||
|
@@ -168,7 +168,8 @@ class BlenderSmokeLoader : public ImageLoader {
|
||||
AttributeStandard attribute;
|
||||
};
|
||||
|
||||
static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame)
|
||||
static void sync_smoke_volume(
|
||||
BL::Scene &b_scene, Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame)
|
||||
{
|
||||
if (!b_ob_info.is_real_object_data()) {
|
||||
return;
|
||||
@@ -178,6 +179,18 @@ static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volu
|
||||
return;
|
||||
}
|
||||
|
||||
float velocity_scale = b_domain.velocity_scale();
|
||||
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
||||
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
||||
const float motion_scale = (need_motion) ?
|
||||
scene->motion_shutter_time() /
|
||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||
0.0f;
|
||||
|
||||
velocity_scale *= motion_scale;
|
||||
|
||||
volume->set_velocity_scale(velocity_scale);
|
||||
|
||||
AttributeStandard attributes[] = {ATTR_STD_VOLUME_DENSITY,
|
||||
ATTR_STD_VOLUME_COLOR,
|
||||
ATTR_STD_VOLUME_FLAME,
|
||||
@@ -234,6 +247,7 @@ class BlenderVolumeLoader : public VDBImageLoader {
|
||||
};
|
||||
|
||||
static void sync_volume_object(BL::BlendData &b_data,
|
||||
BL::Scene &b_scene,
|
||||
BObjectInfo &b_ob_info,
|
||||
Scene *scene,
|
||||
Volume *volume)
|
||||
@@ -247,6 +261,20 @@ static void sync_volume_object(BL::BlendData &b_data,
|
||||
volume->set_step_size(b_render.step_size());
|
||||
volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT));
|
||||
|
||||
float velocity_scale = b_volume.velocity_scale();
|
||||
if (b_volume.velocity_unit() == BL::Volume::velocity_unit_SECOND) {
|
||||
/* Motion blur attribute is relative to seconds, we need it relative to frames. */
|
||||
const bool need_motion = object_need_motion_attribute(b_ob_info, scene);
|
||||
const float motion_scale = (need_motion) ?
|
||||
scene->motion_shutter_time() /
|
||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||
0.0f;
|
||||
|
||||
velocity_scale *= motion_scale;
|
||||
}
|
||||
|
||||
volume->set_velocity_scale(velocity_scale);
|
||||
|
||||
/* Find grid with matching name. */
|
||||
for (BL::VolumeGrid &b_grid : b_volume.grids) {
|
||||
ustring name = ustring(b_grid.name());
|
||||
@@ -267,9 +295,22 @@ static void sync_volume_object(BL::BlendData &b_data,
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
|
||||
std = ATTR_STD_VOLUME_TEMPERATURE;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY) ||
|
||||
name == b_volume.velocity_grid()) {
|
||||
std = ATTR_STD_VOLUME_VELOCITY;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_X) ||
|
||||
name == b_volume.velocity_x_grid()) {
|
||||
std = ATTR_STD_VOLUME_VELOCITY_X;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_Y) ||
|
||||
name == b_volume.velocity_y_grid()) {
|
||||
std = ATTR_STD_VOLUME_VELOCITY_Y;
|
||||
}
|
||||
else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY_Z) ||
|
||||
name == b_volume.velocity_z_grid()) {
|
||||
std = ATTR_STD_VOLUME_VELOCITY_Z;
|
||||
}
|
||||
|
||||
if ((std != ATTR_STD_NONE && volume->need_attribute(scene, std)) ||
|
||||
volume->need_attribute(scene, name)) {
|
||||
@@ -294,11 +335,11 @@ void BlenderSync::sync_volume(BObjectInfo &b_ob_info, Volume *volume)
|
||||
if (b_ob_info.object_data.is_a(&RNA_Volume)) {
|
||||
/* Volume object. Create only attributes, bounding mesh will then
|
||||
* be automatically generated later. */
|
||||
sync_volume_object(b_data, b_ob_info, scene, volume);
|
||||
sync_volume_object(b_data, b_scene, b_ob_info, scene, volume);
|
||||
}
|
||||
else {
|
||||
/* Smoke domain. */
|
||||
sync_smoke_volume(scene, b_ob_info, volume, b_scene.frame_current());
|
||||
sync_smoke_volume(b_scene, scene, b_ob_info, volume, b_scene.frame_current());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -71,11 +71,6 @@ void CUDADeviceQueue::init_execution()
|
||||
debug_init_execution();
|
||||
}
|
||||
|
||||
bool CUDADeviceQueue::kernel_available(DeviceKernel kernel) const
|
||||
{
|
||||
return cuda_device_->kernels.available(kernel);
|
||||
}
|
||||
|
||||
bool CUDADeviceQueue::enqueue(DeviceKernel kernel,
|
||||
const int work_size,
|
||||
DeviceKernelArguments const &args)
|
||||
|
@@ -27,8 +27,6 @@ class CUDADeviceQueue : public DeviceQueue {
|
||||
|
||||
virtual void init_execution() override;
|
||||
|
||||
virtual bool kernel_available(DeviceKernel kernel) const override;
|
||||
|
||||
virtual bool enqueue(DeviceKernel kernel,
|
||||
const int work_size,
|
||||
DeviceKernelArguments const &args) override;
|
||||
|
@@ -71,11 +71,6 @@ void HIPDeviceQueue::init_execution()
|
||||
debug_init_execution();
|
||||
}
|
||||
|
||||
bool HIPDeviceQueue::kernel_available(DeviceKernel kernel) const
|
||||
{
|
||||
return hip_device_->kernels.available(kernel);
|
||||
}
|
||||
|
||||
bool HIPDeviceQueue::enqueue(DeviceKernel kernel,
|
||||
const int work_size,
|
||||
DeviceKernelArguments const &args)
|
||||
|
@@ -27,8 +27,6 @@ class HIPDeviceQueue : public DeviceQueue {
|
||||
|
||||
virtual void init_execution() override;
|
||||
|
||||
virtual bool kernel_available(DeviceKernel kernel) const override;
|
||||
|
||||
virtual bool enqueue(DeviceKernel kernel,
|
||||
const int work_size,
|
||||
DeviceKernelArguments const &args) override;
|
||||
|
@@ -51,7 +51,7 @@ static inline bool hipSupportsDevice(const int hipDevId)
|
||||
hipDeviceGetAttribute(&major, hipDeviceAttributeComputeCapabilityMajor, hipDevId);
|
||||
hipDeviceGetAttribute(&minor, hipDeviceAttributeComputeCapabilityMinor, hipDevId);
|
||||
|
||||
return (major >= 9);
|
||||
return (major > 10) || (major == 10 && minor >= 1);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -459,7 +459,7 @@ bool MetalDeviceKernels::load(MetalDevice *device, int kernel_type)
|
||||
|
||||
tbb::task_arena local_arena(max_mtlcompiler_threads);
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(int(0), int(DEVICE_KERNEL_NUM), [&](int i) {
|
||||
parallel_for(int(0), int(DEVICE_KERNEL_NUM), [&](int i) {
|
||||
/* skip megakernel */
|
||||
if (i == DEVICE_KERNEL_INTEGRATOR_MEGAKERNEL) {
|
||||
return;
|
||||
|
@@ -39,8 +39,6 @@ class MetalDeviceQueue : public DeviceQueue {
|
||||
virtual void copy_to_device(device_memory &mem) override;
|
||||
virtual void copy_from_device(device_memory &mem) override;
|
||||
|
||||
virtual bool kernel_available(DeviceKernel kernel) const override;
|
||||
|
||||
protected:
|
||||
void prepare_resources(DeviceKernel kernel);
|
||||
|
||||
|
@@ -492,11 +492,6 @@ void MetalDeviceQueue::copy_from_device(device_memory &mem)
|
||||
}
|
||||
}
|
||||
|
||||
bool MetalDeviceQueue::kernel_available(DeviceKernel kernel) const
|
||||
{
|
||||
return metal_device->kernels.available(kernel);
|
||||
}
|
||||
|
||||
void MetalDeviceQueue::prepare_resources(DeviceKernel kernel)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(metal_device->metal_mem_map_mutex);
|
||||
|
@@ -112,9 +112,6 @@ class DeviceQueue {
|
||||
* Use this method after device synchronization has finished before enqueueing any kernels. */
|
||||
virtual void init_execution() = 0;
|
||||
|
||||
/* Test if an optional device kernel is available. */
|
||||
virtual bool kernel_available(DeviceKernel kernel) const = 0;
|
||||
|
||||
/* Enqueue kernel execution.
|
||||
*
|
||||
* Execute the kernel work_size times on the device.
|
||||
|
@@ -3,6 +3,7 @@
|
||||
* Copyright 2022 Blender Foundation */
|
||||
|
||||
#include "hydra/camera.h"
|
||||
#include "hydra/session.h"
|
||||
#include "scene/camera.h"
|
||||
|
||||
#include <pxr/base/gf/frustum.h>
|
||||
@@ -12,6 +13,19 @@
|
||||
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
||||
|
||||
extern Transform convert_transform(const GfMatrix4d &matrix);
|
||||
Transform convert_camera_transform(const GfMatrix4d &matrix, float metersPerUnit)
|
||||
{
|
||||
Transform t = convert_transform(matrix);
|
||||
// Flip Z axis
|
||||
t.x.z *= -1.0f;
|
||||
t.y.z *= -1.0f;
|
||||
t.z.z *= -1.0f;
|
||||
// Scale translation
|
||||
t.x.w *= metersPerUnit;
|
||||
t.y.w *= metersPerUnit;
|
||||
t.z.w *= metersPerUnit;
|
||||
return t;
|
||||
}
|
||||
|
||||
#if PXR_VERSION < 2102
|
||||
// clang-format off
|
||||
@@ -61,13 +75,20 @@ void HdCyclesCamera::Sync(HdSceneDelegate *sceneDelegate,
|
||||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
sceneDelegate->SampleTransform(id, &_transformSamples);
|
||||
|
||||
bool transform_found = false;
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
if (_transformSamples.times[i] == 0.0f) {
|
||||
_transform = _transformSamples.values[i];
|
||||
_data.SetTransform(_transform);
|
||||
transform_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!transform_found && _transformSamples.count) {
|
||||
_transform = _transformSamples.values[0];
|
||||
_data.SetTransform(_transform);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (*dirtyBits & DirtyBits::DirtyViewMatrix) {
|
||||
@@ -236,18 +257,21 @@ void HdCyclesCamera::Finalize(HdRenderParam *renderParam)
|
||||
HdCamera::Finalize(renderParam);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(Camera *cam) const
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam, Camera *cam) const
|
||||
{
|
||||
ApplyCameraSettings(_data, _windowPolicy, cam);
|
||||
ApplyCameraSettings(renderParam, _data, _windowPolicy, cam);
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
array<Transform> motion(_transformSamples.count);
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i)
|
||||
motion[i] = convert_transform(_transformSamples.values[i]) *
|
||||
transform_scale(1.0f, 1.0f, -1.0f);
|
||||
for (size_t i = 0; i < _transformSamples.count; ++i) {
|
||||
motion[i] = convert_camera_transform(_transformSamples.values[i], metersPerUnit);
|
||||
}
|
||||
cam->set_motion(motion);
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfCamera &dataUnconformedWindow,
|
||||
CameraUtilConformWindowPolicy windowPolicy,
|
||||
Camera *cam)
|
||||
{
|
||||
@@ -261,20 +285,22 @@ void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
||||
GfCamera::Orthographic == CAMERA_ORTHOGRAPHIC);
|
||||
cam->set_camera_type(static_cast<CameraType>(data.GetProjection()));
|
||||
|
||||
const float metersPerUnit = static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
auto viewplane = data.GetFrustum().GetWindow();
|
||||
auto focalLength = 1.0f;
|
||||
if (data.GetProjection() == GfCamera::Perspective) {
|
||||
viewplane *= 2.0 / viewplane.GetSize()[1]; // Normalize viewplane
|
||||
focalLength = data.GetFocalLength() * 1e-3f;
|
||||
focalLength = data.GetFocalLength() * GfCamera::FOCAL_LENGTH_UNIT * metersPerUnit;
|
||||
|
||||
cam->set_fov(GfDegreesToRadians(data.GetFieldOfView(GfCamera::FOVVertical)));
|
||||
}
|
||||
|
||||
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT);
|
||||
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT);
|
||||
cam->set_sensorwidth(data.GetHorizontalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
cam->set_sensorheight(data.GetVerticalAperture() * GfCamera::APERTURE_UNIT * metersPerUnit);
|
||||
|
||||
cam->set_nearclip(data.GetClippingRange().GetMin());
|
||||
cam->set_farclip(data.GetClippingRange().GetMax());
|
||||
cam->set_nearclip(data.GetClippingRange().GetMin() * metersPerUnit);
|
||||
cam->set_farclip(data.GetClippingRange().GetMax() * metersPerUnit);
|
||||
|
||||
cam->set_viewplane_left(viewplane.GetMin()[0]);
|
||||
cam->set_viewplane_right(viewplane.GetMax()[0]);
|
||||
@@ -282,14 +308,15 @@ void HdCyclesCamera::ApplyCameraSettings(const GfCamera &dataUnconformedWindow,
|
||||
cam->set_viewplane_top(viewplane.GetMax()[1]);
|
||||
|
||||
if (data.GetFStop() != 0.0f) {
|
||||
cam->set_focaldistance(data.GetFocusDistance());
|
||||
cam->set_focaldistance(data.GetFocusDistance() * metersPerUnit);
|
||||
cam->set_aperturesize(focalLength / (2.0f * data.GetFStop()));
|
||||
}
|
||||
|
||||
cam->set_matrix(convert_transform(data.GetTransform()) * transform_scale(1.0f, 1.0f, -1.0f));
|
||||
cam->set_matrix(convert_camera_transform(data.GetTransform(), metersPerUnit));
|
||||
}
|
||||
|
||||
void HdCyclesCamera::ApplyCameraSettings(const GfMatrix4d &worldToViewMatrix,
|
||||
void HdCyclesCamera::ApplyCameraSettings(HdRenderParam *renderParam,
|
||||
const GfMatrix4d &worldToViewMatrix,
|
||||
const GfMatrix4d &projectionMatrix,
|
||||
const std::vector<GfVec4d> &clipPlanes,
|
||||
Camera *cam)
|
||||
@@ -298,7 +325,7 @@ void HdCyclesCamera::ApplyCameraSettings(const GfMatrix4d &worldToViewMatrix,
|
||||
GfCamera data;
|
||||
data.SetFromViewAndProjectionMatrix(worldToViewMatrix, projectionMatrix);
|
||||
|
||||
ApplyCameraSettings(data, CameraUtilFit, cam);
|
||||
ApplyCameraSettings(renderParam, data, CameraUtilFit, cam);
|
||||
#else
|
||||
TF_CODING_ERROR("Not implemented");
|
||||
#endif
|
||||
|
@@ -17,12 +17,14 @@ class HdCyclesCamera final : public PXR_NS::HdCamera {
|
||||
HdCyclesCamera(const PXR_NS::SdfPath &sprimId);
|
||||
~HdCyclesCamera() override;
|
||||
|
||||
void ApplyCameraSettings(CCL_NS::Camera *targetCamera) const;
|
||||
void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam, CCL_NS::Camera *targetCamera) const;
|
||||
|
||||
static void ApplyCameraSettings(const PXR_NS::GfCamera &cameraData,
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfCamera &cameraData,
|
||||
PXR_NS::CameraUtilConformWindowPolicy windowPolicy,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
static void ApplyCameraSettings(const PXR_NS::GfMatrix4d &worldToViewMatrix,
|
||||
static void ApplyCameraSettings(PXR_NS::HdRenderParam *renderParam,
|
||||
const PXR_NS::GfMatrix4d &worldToViewMatrix,
|
||||
const PXR_NS::GfMatrix4d &projectionMatrix,
|
||||
const std::vector<PXR_NS::GfVec4d> &clipPlanes,
|
||||
CCL_NS::Camera *targetCamera);
|
||||
|
@@ -153,7 +153,11 @@ void HdCyclesGeometry<Base, CyclesBase>::Sync(HdSceneDelegate *sceneDelegate,
|
||||
|
||||
// Update transforms of all instances
|
||||
for (size_t i = 0; i < transforms.size(); ++i) {
|
||||
const Transform tfm = convert_transform(_geomTransform * transforms[i]);
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
convert_transform(_geomTransform * transforms[i]);
|
||||
_instances[i]->set_tfm(tfm);
|
||||
}
|
||||
}
|
||||
|
@@ -54,11 +54,16 @@ void HdCyclesLight::Sync(HdSceneDelegate *sceneDelegate,
|
||||
const SdfPath &id = GetId();
|
||||
|
||||
if (*dirtyBits & DirtyBits::DirtyTransform) {
|
||||
const float metersPerUnit =
|
||||
static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
|
||||
|
||||
const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
|
||||
#if PXR_VERSION >= 2011
|
||||
const Transform tfm = convert_transform(sceneDelegate->GetTransform(id));
|
||||
convert_transform(sceneDelegate->GetTransform(id));
|
||||
#else
|
||||
const Transform tfm = convert_transform(
|
||||
sceneDelegate->GetLightParamValue(id, HdTokens->transform).Get<GfMatrix4d>());
|
||||
convert_transform(
|
||||
sceneDelegate->GetLightParamValue(id, HdTokens->transform)
|
||||
.Get<GfMatrix4d>());
|
||||
#endif
|
||||
_light->set_tfm(tfm);
|
||||
|
||||
|
@@ -33,11 +33,12 @@ TF_DEFINE_PRIVATE_TOKENS(_tokens,
|
||||
);
|
||||
|
||||
TF_DEFINE_PRIVATE_TOKENS(HdCyclesRenderSettingsTokens,
|
||||
(stageMetersPerUnit)
|
||||
((device, "cycles:device"))
|
||||
((threads, "cycles:threads"))
|
||||
((time_limit, "cycles:time_limit"))
|
||||
((timeLimit, "cycles:time_limit"))
|
||||
((samples, "cycles:samples"))
|
||||
((sample_offset, "cycles:sample_offset"))
|
||||
((sampleOffset, "cycles:sample_offset"))
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
@@ -424,7 +425,7 @@ HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() co
|
||||
|
||||
descriptors.push_back({
|
||||
"Time Limit",
|
||||
HdCyclesRenderSettingsTokens->time_limit,
|
||||
HdCyclesRenderSettingsTokens->timeLimit,
|
||||
VtValue(0.0),
|
||||
});
|
||||
descriptors.push_back({
|
||||
@@ -434,7 +435,7 @@ HdRenderSettingDescriptorList HdCyclesDelegate::GetRenderSettingDescriptors() co
|
||||
});
|
||||
descriptors.push_back({
|
||||
"Sample Offset",
|
||||
HdCyclesRenderSettingsTokens->sample_offset,
|
||||
HdCyclesRenderSettingsTokens->sampleOffset,
|
||||
VtValue(0),
|
||||
});
|
||||
|
||||
@@ -452,7 +453,11 @@ void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->time_limit) {
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
_renderParam->SetStageMetersPerUnit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(_renderParam->GetStageMetersPerUnit()));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
session->set_time_limit(
|
||||
VtValue::Cast<double>(value).GetWithDefault(session->params.time_limit));
|
||||
}
|
||||
@@ -462,7 +467,7 @@ void HdCyclesDelegate::SetRenderSetting(const PXR_NS::TfToken &key, const PXR_NS
|
||||
samples = std::min(std::max(1, samples), max_samples);
|
||||
session->set_samples(samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
session->params.sample_offset = VtValue::Cast<int>(value).GetWithDefault(
|
||||
session->params.sample_offset);
|
||||
++_settingsVersion;
|
||||
@@ -484,19 +489,22 @@ VtValue HdCyclesDelegate::GetRenderSetting(const TfToken &key) const
|
||||
Scene *const scene = _renderParam->session->scene;
|
||||
Session *const session = _renderParam->session;
|
||||
|
||||
if (key == HdCyclesRenderSettingsTokens->device) {
|
||||
if (key == HdCyclesRenderSettingsTokens->stageMetersPerUnit) {
|
||||
return VtValue(_renderParam->GetStageMetersPerUnit());
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->device) {
|
||||
return VtValue(TfToken(Device::string_from_type(session->params.device.type)));
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->threads) {
|
||||
return VtValue(session->params.threads);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->time_limit) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->timeLimit) {
|
||||
return VtValue(session->params.time_limit);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->samples) {
|
||||
return VtValue(session->params.samples);
|
||||
}
|
||||
else if (key == HdCyclesRenderSettingsTokens->sample_offset) {
|
||||
else if (key == HdCyclesRenderSettingsTokens->sampleOffset) {
|
||||
return VtValue(session->params.sample_offset);
|
||||
}
|
||||
else {
|
||||
|
@@ -117,10 +117,11 @@ void HdCyclesRenderPass::_Execute(const HdRenderPassStateSharedPtr &renderPassSt
|
||||
#endif
|
||||
|
||||
if (const auto camera = static_cast<const HdCyclesCamera *>(renderPassState->GetCamera())) {
|
||||
camera->ApplyCameraSettings(scene->camera);
|
||||
camera->ApplyCameraSettings(_renderParam, scene->camera);
|
||||
}
|
||||
else {
|
||||
HdCyclesCamera::ApplyCameraSettings(renderPassState->GetWorldToViewMatrix(),
|
||||
HdCyclesCamera::ApplyCameraSettings(_renderParam,
|
||||
renderPassState->GetWorldToViewMatrix(),
|
||||
renderPassState->GetProjectionMatrix(),
|
||||
renderPassState->GetClipPlanes(),
|
||||
scene->camera);
|
||||
|
@@ -29,6 +29,16 @@ class HdCyclesSession final : public PXR_NS::HdRenderParam {
|
||||
|
||||
void UpdateScene();
|
||||
|
||||
double GetStageMetersPerUnit() const
|
||||
{
|
||||
return _stageMetersPerUnit;
|
||||
}
|
||||
|
||||
void SetStageMetersPerUnit(double stageMetersPerUnit)
|
||||
{
|
||||
_stageMetersPerUnit = stageMetersPerUnit;
|
||||
}
|
||||
|
||||
PXR_NS::HdRenderPassAovBinding GetDisplayAovBinding() const
|
||||
{
|
||||
return _displayAovBinding;
|
||||
@@ -52,6 +62,7 @@ class HdCyclesSession final : public PXR_NS::HdRenderParam {
|
||||
|
||||
private:
|
||||
const bool _ownCyclesSession;
|
||||
double _stageMetersPerUnit = 0.01;
|
||||
PXR_NS::HdRenderPassAovBindingVector _aovBindings;
|
||||
PXR_NS::HdRenderPassAovBinding _displayAovBinding;
|
||||
};
|
||||
|
@@ -44,7 +44,7 @@ inline void PassAccessorCPU::run_get_pass_kernel_processor_float(
|
||||
const int pixel_stride = destination.pixel_stride ? destination.pixel_stride :
|
||||
destination.num_components;
|
||||
|
||||
tbb::parallel_for(0, buffer_params.window_height, [&](int64_t y) {
|
||||
parallel_for(0, buffer_params.window_height, [&](int64_t y) {
|
||||
const float *buffer = window_data + y * buffer_row_stride;
|
||||
float *pixel = destination.pixels +
|
||||
(y * buffer_params.width + destination.offset) * pixel_stride;
|
||||
@@ -69,7 +69,7 @@ inline void PassAccessorCPU::run_get_pass_kernel_processor_half_rgba(
|
||||
const int destination_stride = destination.stride != 0 ? destination.stride :
|
||||
buffer_params.width;
|
||||
|
||||
tbb::parallel_for(0, buffer_params.window_height, [&](int64_t y) {
|
||||
parallel_for(0, buffer_params.window_height, [&](int64_t y) {
|
||||
const float *buffer = window_data + y * buffer_row_stride;
|
||||
half4 *pixel = dst_start + y * destination_stride;
|
||||
func(kfilm_convert, buffer, pixel, buffer_params.window_width, pass_stride);
|
||||
|
@@ -334,7 +334,7 @@ void PathTrace::init_render_buffers(const RenderWork &render_work)
|
||||
|
||||
/* Handle initialization scheduled by the render scheduler. */
|
||||
if (render_work.init_render_buffers) {
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->zero_render_buffers();
|
||||
});
|
||||
|
||||
@@ -355,7 +355,9 @@ void PathTrace::path_trace(RenderWork &render_work)
|
||||
|
||||
const int num_works = path_trace_works_.size();
|
||||
|
||||
tbb::parallel_for(0, num_works, [&](int i) {
|
||||
thread_capture_fp_settings();
|
||||
|
||||
parallel_for(0, num_works, [&](int i) {
|
||||
const double work_start_time = time_dt();
|
||||
const int num_samples = render_work.path_trace.num_samples;
|
||||
|
||||
@@ -405,7 +407,7 @@ void PathTrace::adaptive_sample(RenderWork &render_work)
|
||||
const double start_time = time_dt();
|
||||
|
||||
uint num_active_pixels = 0;
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
const uint num_active_pixels_in_work =
|
||||
path_trace_work->adaptive_sampling_converge_filter_count_active(
|
||||
render_work.adaptive_sampling.threshold, render_work.adaptive_sampling.reset);
|
||||
@@ -483,7 +485,7 @@ void PathTrace::cryptomatte_postprocess(const RenderWork &render_work)
|
||||
}
|
||||
VLOG(3) << "Perform cryptomatte work.";
|
||||
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->cryptomatte_postproces();
|
||||
});
|
||||
}
|
||||
@@ -536,7 +538,7 @@ void PathTrace::denoise(const RenderWork &render_work)
|
||||
|
||||
if (multi_device_buffers) {
|
||||
multi_device_buffers->copy_from_device();
|
||||
tbb::parallel_for_each(
|
||||
parallel_for_each(
|
||||
path_trace_works_, [&multi_device_buffers](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_from_denoised_render_buffers(multi_device_buffers.get());
|
||||
});
|
||||
@@ -806,7 +808,7 @@ void PathTrace::tile_buffer_read()
|
||||
}
|
||||
|
||||
/* Read buffers back from device. */
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_render_buffers_from_device();
|
||||
});
|
||||
|
||||
@@ -814,7 +816,7 @@ void PathTrace::tile_buffer_read()
|
||||
PathTraceTile tile(*this);
|
||||
if (output_driver_->read_render_tile(tile)) {
|
||||
/* Copy buffers to device again. */
|
||||
tbb::parallel_for_each(path_trace_works_, [](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_render_buffers_to_device();
|
||||
});
|
||||
}
|
||||
@@ -878,20 +880,20 @@ void PathTrace::progress_set_status(const string &status, const string &substatu
|
||||
|
||||
void PathTrace::copy_to_render_buffers(RenderBuffers *render_buffers)
|
||||
{
|
||||
tbb::parallel_for_each(path_trace_works_,
|
||||
[&render_buffers](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_to_render_buffers(render_buffers);
|
||||
});
|
||||
parallel_for_each(path_trace_works_,
|
||||
[&render_buffers](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_to_render_buffers(render_buffers);
|
||||
});
|
||||
render_buffers->copy_to_device();
|
||||
}
|
||||
|
||||
void PathTrace::copy_from_render_buffers(RenderBuffers *render_buffers)
|
||||
{
|
||||
render_buffers->copy_from_device();
|
||||
tbb::parallel_for_each(path_trace_works_,
|
||||
[&render_buffers](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_from_render_buffers(render_buffers);
|
||||
});
|
||||
parallel_for_each(path_trace_works_,
|
||||
[&render_buffers](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
path_trace_work->copy_from_render_buffers(render_buffers);
|
||||
});
|
||||
}
|
||||
|
||||
bool PathTrace::copy_render_tile_from_device()
|
||||
@@ -903,7 +905,7 @@ bool PathTrace::copy_render_tile_from_device()
|
||||
|
||||
bool success = true;
|
||||
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
@@ -1004,7 +1006,7 @@ bool PathTrace::get_render_tile_pixels(const PassAccessor &pass_accessor,
|
||||
|
||||
bool success = true;
|
||||
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
@@ -1021,7 +1023,7 @@ bool PathTrace::set_render_tile_pixels(PassAccessor &pass_accessor,
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
tbb::parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
parallel_for_each(path_trace_works_, [&](unique_ptr<PathTraceWork> &path_trace_work) {
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ void PathTraceWorkCPU::render_samples(RenderStatistics &statistics,
|
||||
|
||||
tbb::task_arena local_arena = local_tbb_arena_create(device_);
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(int64_t(0), total_pixels_num, [&](int64_t work_index) {
|
||||
parallel_for(int64_t(0), total_pixels_num, [&](int64_t work_index) {
|
||||
if (is_cancel_requested()) {
|
||||
return;
|
||||
}
|
||||
@@ -219,7 +219,7 @@ int PathTraceWorkCPU::adaptive_sampling_converge_filter_count_active(float thres
|
||||
|
||||
/* Check convergency and do x-filter in a single `parallel_for`, to reduce threading overhead. */
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(full_y, full_y + height, [&](int y) {
|
||||
parallel_for(full_y, full_y + height, [&](int y) {
|
||||
CPUKernelThreadGlobals *kernel_globals = &kernel_thread_globals_[0];
|
||||
|
||||
bool row_converged = true;
|
||||
@@ -243,7 +243,7 @@ int PathTraceWorkCPU::adaptive_sampling_converge_filter_count_active(float thres
|
||||
|
||||
if (num_active_pixels) {
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(full_x, full_x + width, [&](int x) {
|
||||
parallel_for(full_x, full_x + width, [&](int x) {
|
||||
CPUKernelThreadGlobals *kernel_globals = &kernel_thread_globals_[0];
|
||||
kernels_.adaptive_sampling_filter_y(
|
||||
kernel_globals, render_buffer, x, full_y, height, offset, stride);
|
||||
@@ -265,7 +265,7 @@ void PathTraceWorkCPU::cryptomatte_postproces()
|
||||
|
||||
/* Check convergency and do x-filter in a single `parallel_for`, to reduce threading overhead. */
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(0, height, [&](int y) {
|
||||
parallel_for(0, height, [&](int y) {
|
||||
CPUKernelThreadGlobals *kernel_globals = &kernel_thread_globals_[0];
|
||||
int pixel_index = y * width;
|
||||
|
||||
|
@@ -92,7 +92,7 @@ bool ShaderEval::eval_cpu(Device *device,
|
||||
|
||||
tbb::task_arena local_arena(device->info.cpu_threads);
|
||||
local_arena.execute([&]() {
|
||||
tbb::parallel_for(int64_t(0), work_size, [&](int64_t work_index) {
|
||||
parallel_for(int64_t(0), work_size, [&](int64_t work_index) {
|
||||
/* TODO: is this fast enough? */
|
||||
if (progress_.get_cancel()) {
|
||||
success = false;
|
||||
|
@@ -831,6 +831,65 @@ ccl_device_inline void shader_eval_volume(KernelGlobals kg,
|
||||
/* todo: this is inefficient for motion blur, we should be
|
||||
* caching matrices instead of recomputing them each step */
|
||||
shader_setup_object_transforms(kg, sd, sd->time);
|
||||
|
||||
if ((sd->object_flag & SD_OBJECT_HAS_VOLUME_MOTION) != 0) {
|
||||
AttributeDescriptor v_desc = find_attribute(kg, sd, ATTR_STD_VOLUME_VELOCITY);
|
||||
kernel_assert(v_desc.offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
const float3 P = sd->P;
|
||||
const float velocity_scale = kernel_tex_fetch(__objects, sd->object).velocity_scale;
|
||||
const float time_offset = kernel_data.cam.motion_position == MOTION_POSITION_CENTER ?
|
||||
0.5f :
|
||||
0.0f;
|
||||
const float time = kernel_data.cam.motion_position == MOTION_POSITION_END ?
|
||||
(1.0f - kernel_data.cam.shuttertime) + sd->time :
|
||||
sd->time;
|
||||
|
||||
/* Use a 1st order semi-lagrangian advection scheme to estimate what volume quantity
|
||||
* existed, or will exist, at the given time:
|
||||
*
|
||||
* `phi(x, T) = phi(x - (T - t) * u(x, T), t)`
|
||||
*
|
||||
* where
|
||||
*
|
||||
* x : position
|
||||
* T : super-sampled time (or ray time)
|
||||
* t : current time of the simulation (in rendering we assume this is center frame with
|
||||
* relative time = 0)
|
||||
* phi : the volume quantity
|
||||
* u : the velocity field
|
||||
*
|
||||
* But first we need to determine the velocity field `u(x, T)`, which we can estimate also
|
||||
* using semi-lagrangian advection.
|
||||
*
|
||||
* `u(x, T) = u(x - (T - t) * u(x, T), t)`
|
||||
*
|
||||
* This is the typical way to model self-advection in fluid dynamics, however, we do not
|
||||
* account for other forces affecting the velocity during simulation (pressure, buyoancy,
|
||||
* etc.): this gives a linear interpolation when fluid are mostly "curvy". For better
|
||||
* results, a higher order interpolation scheme can be used (at the cost of more lookups),
|
||||
* or an interpolation of the velocity fields for the previous and next frames could also
|
||||
* be used to estimate `u(x, T)` (which will cost more memory and lookups).
|
||||
*
|
||||
* References:
|
||||
* "Eulerian Motion Blur", Kim and Ko, 2007
|
||||
* "Production Volume Rendering", Wreninge et al., 2012
|
||||
*/
|
||||
|
||||
/* Find velocity. */
|
||||
float3 velocity = primitive_volume_attribute_float3(kg, sd, v_desc);
|
||||
object_dir_transform(kg, sd, &velocity);
|
||||
|
||||
/* Find advected P. */
|
||||
sd->P = P - (time - time_offset) * velocity_scale * velocity;
|
||||
|
||||
/* Find advected velocity. */
|
||||
velocity = primitive_volume_attribute_float3(kg, sd, v_desc);
|
||||
object_dir_transform(kg, sd, &velocity);
|
||||
|
||||
/* Find advected P. */
|
||||
sd->P = P - (time - time_offset) * velocity_scale * velocity;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
|
@@ -32,7 +32,7 @@ ccl_device void svm_node_aov_color(KernelGlobals kg,
|
||||
kernel_data.film.pass_stride;
|
||||
ccl_global float *buffer = render_buffer + render_buffer_offset +
|
||||
(kernel_data.film.pass_aov_color + node.z);
|
||||
kernel_write_pass_float3(buffer, make_float3(val.x, val.y, val.z));
|
||||
kernel_write_pass_float4(buffer, make_float4(val.x, val.y, val.z, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@ ccl_device_noinline void svm_node_blackbody(KernelGlobals kg,
|
||||
/* Input */
|
||||
float temperature = stack_load_float(stack, temperature_offset);
|
||||
|
||||
float3 color_rgb = svm_math_blackbody_color(temperature);
|
||||
float3 color_rgb = rec709_to_rgb(kg, svm_math_blackbody_color_rec709(temperature));
|
||||
|
||||
stack_store_float3(stack, col_offset, color_rgb);
|
||||
}
|
||||
|
@@ -1111,7 +1111,8 @@ ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg,
|
||||
|
||||
if (intensity > CLOSURE_WEIGHT_CUTOFF) {
|
||||
float3 blackbody_tint = stack_load_float3(stack, node.w);
|
||||
float3 bb = blackbody_tint * intensity * svm_math_blackbody_color(T);
|
||||
float3 bb = blackbody_tint * intensity *
|
||||
rec709_to_rgb(kg, svm_math_blackbody_color_rec709(T));
|
||||
emission_setup(sd, bb);
|
||||
}
|
||||
}
|
||||
|
@@ -189,10 +189,8 @@ ccl_device float svm_math(NodeMathType type, float a, float b, float c)
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device float3 svm_math_blackbody_color(float t)
|
||||
ccl_device float3 svm_math_blackbody_color_rec709(float t)
|
||||
{
|
||||
/* TODO(lukas): Reimplement in XYZ. */
|
||||
|
||||
/* Calculate color in range 800..12000 using an approximation
|
||||
* a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
|
||||
* Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
|
||||
|
@@ -489,6 +489,18 @@ enum PanoramaType {
|
||||
PANORAMA_NUM_TYPES,
|
||||
};
|
||||
|
||||
/* Specifies an offset for the shutter's time interval. */
|
||||
enum MotionPosition {
|
||||
/* Shutter opens at the current frame. */
|
||||
MOTION_POSITION_START = 0,
|
||||
/* Shutter is fully open at the current frame. */
|
||||
MOTION_POSITION_CENTER = 1,
|
||||
/* Shutter closes at the current frame. */
|
||||
MOTION_POSITION_END = 2,
|
||||
|
||||
MOTION_NUM_POSITIONS,
|
||||
};
|
||||
|
||||
/* Direct Light Sampling */
|
||||
|
||||
enum DirectLightSamplingType {
|
||||
@@ -635,6 +647,9 @@ typedef enum AttributeStandard {
|
||||
ATTR_STD_VOLUME_HEAT,
|
||||
ATTR_STD_VOLUME_TEMPERATURE,
|
||||
ATTR_STD_VOLUME_VELOCITY,
|
||||
ATTR_STD_VOLUME_VELOCITY_X,
|
||||
ATTR_STD_VOLUME_VELOCITY_Y,
|
||||
ATTR_STD_VOLUME_VELOCITY_Z,
|
||||
ATTR_STD_POINTINESS,
|
||||
ATTR_STD_RANDOM_PER_ISLAND,
|
||||
ATTR_STD_SHADOW_TRANSPARENCY,
|
||||
@@ -808,6 +823,8 @@ enum ShaderDataObjectFlag {
|
||||
SD_OBJECT_CAUSTICS_CASTER = (1 << 9),
|
||||
/* object is caustics receiver */
|
||||
SD_OBJECT_CAUSTICS_RECEIVER = (1 << 10),
|
||||
/* object has attribute for volume motion */
|
||||
SD_OBJECT_HAS_VOLUME_MOTION = (1 << 11),
|
||||
|
||||
/* object is using caustics */
|
||||
SD_OBJECT_CAUSTICS = (SD_OBJECT_CAUSTICS_CASTER | SD_OBJECT_CAUSTICS_RECEIVER),
|
||||
@@ -815,7 +832,8 @@ enum ShaderDataObjectFlag {
|
||||
SD_OBJECT_FLAGS = (SD_OBJECT_HOLDOUT_MASK | SD_OBJECT_MOTION | SD_OBJECT_TRANSFORM_APPLIED |
|
||||
SD_OBJECT_NEGATIVE_SCALE_APPLIED | SD_OBJECT_HAS_VOLUME |
|
||||
SD_OBJECT_INTERSECTS_VOLUME | SD_OBJECT_SHADOW_CATCHER |
|
||||
SD_OBJECT_HAS_VOLUME_ATTRIBUTES | SD_OBJECT_CAUSTICS)
|
||||
SD_OBJECT_HAS_VOLUME_ATTRIBUTES | SD_OBJECT_CAUSTICS |
|
||||
SD_OBJECT_HAS_VOLUME_MOTION)
|
||||
};
|
||||
|
||||
typedef struct ccl_align(16) ShaderData
|
||||
@@ -1040,7 +1058,7 @@ typedef struct KernelCamera {
|
||||
int rolling_shutter_type;
|
||||
float rolling_shutter_duration;
|
||||
|
||||
int pad;
|
||||
int motion_position;
|
||||
} KernelCamera;
|
||||
static_assert_align(KernelCamera, 16);
|
||||
|
||||
@@ -1117,13 +1135,18 @@ typedef struct KernelFilm {
|
||||
float4 xyz_to_g;
|
||||
float4 xyz_to_b;
|
||||
float4 rgb_to_y;
|
||||
/* Rec709 to rendering color space. */
|
||||
float4 rec709_to_r;
|
||||
float4 rec709_to_g;
|
||||
float4 rec709_to_b;
|
||||
int is_rec709;
|
||||
|
||||
int pass_bake_primitive;
|
||||
int pass_bake_differential;
|
||||
|
||||
int use_approximate_shadow_catcher;
|
||||
|
||||
int pad1, pad2;
|
||||
int pad1;
|
||||
} KernelFilm;
|
||||
static_assert_align(KernelFilm, 16);
|
||||
|
||||
@@ -1381,7 +1404,8 @@ typedef struct KernelObject {
|
||||
uint visibility;
|
||||
int primitive_type;
|
||||
|
||||
int pad1;
|
||||
/* Volume velocity scale. */
|
||||
float velocity_scale;
|
||||
} KernelObject;
|
||||
static_assert_align(KernelObject, 16);
|
||||
|
||||
|
@@ -14,6 +14,15 @@ ccl_device float3 xyz_to_rgb(KernelGlobals kg, float3 xyz)
|
||||
dot(float4_to_float3(kernel_data.film.xyz_to_b), xyz));
|
||||
}
|
||||
|
||||
ccl_device float3 rec709_to_rgb(KernelGlobals kg, float3 rec709)
|
||||
{
|
||||
return (kernel_data.film.is_rec709) ?
|
||||
rec709 :
|
||||
make_float3(dot(float4_to_float3(kernel_data.film.rec709_to_r), rec709),
|
||||
dot(float4_to_float3(kernel_data.film.rec709_to_g), rec709),
|
||||
dot(float4_to_float3(kernel_data.film.rec709_to_b), rec709));
|
||||
}
|
||||
|
||||
ccl_device float linear_rgb_to_gray(KernelGlobals kg, float3 c)
|
||||
{
|
||||
return dot(c, float4_to_float3(kernel_data.film.rgb_to_y));
|
||||
|
@@ -360,6 +360,12 @@ const char *Attribute::standard_name(AttributeStandard std)
|
||||
return "temperature";
|
||||
case ATTR_STD_VOLUME_VELOCITY:
|
||||
return "velocity";
|
||||
case ATTR_STD_VOLUME_VELOCITY_X:
|
||||
return "velocity_x";
|
||||
case ATTR_STD_VOLUME_VELOCITY_Y:
|
||||
return "velocity_y";
|
||||
case ATTR_STD_VOLUME_VELOCITY_Z:
|
||||
return "velocity_z";
|
||||
case ATTR_STD_POINTINESS:
|
||||
return "pointiness";
|
||||
case ATTR_STD_RANDOM_PER_ISLAND:
|
||||
@@ -587,6 +593,9 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
||||
case ATTR_STD_VOLUME_FLAME:
|
||||
case ATTR_STD_VOLUME_HEAT:
|
||||
case ATTR_STD_VOLUME_TEMPERATURE:
|
||||
case ATTR_STD_VOLUME_VELOCITY_X:
|
||||
case ATTR_STD_VOLUME_VELOCITY_Y:
|
||||
case ATTR_STD_VOLUME_VELOCITY_Z:
|
||||
attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
|
||||
break;
|
||||
case ATTR_STD_VOLUME_COLOR:
|
||||
|
@@ -397,6 +397,7 @@ void Camera::update(Scene *scene)
|
||||
|
||||
/* motion blur */
|
||||
kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime : -1.0f;
|
||||
kcam->motion_position = motion_position;
|
||||
|
||||
/* type */
|
||||
kcam->type = camera_type;
|
||||
|
@@ -30,18 +30,6 @@ class Camera : public Node {
|
||||
public:
|
||||
NODE_DECLARE
|
||||
|
||||
/* Specifies an offset for the shutter's time interval. */
|
||||
enum MotionPosition {
|
||||
/* Shutter opens at the current frame. */
|
||||
MOTION_POSITION_START = 0,
|
||||
/* Shutter is fully open at the current frame. */
|
||||
MOTION_POSITION_CENTER = 1,
|
||||
/* Shutter closes at the current frame. */
|
||||
MOTION_POSITION_END = 2,
|
||||
|
||||
MOTION_NUM_POSITIONS,
|
||||
};
|
||||
|
||||
/* Specifies rolling shutter effect. */
|
||||
enum RollingShutterType {
|
||||
/* No rolling shutter effect. */
|
||||
|
@@ -1541,7 +1541,7 @@ void GeometryManager::device_update_preprocess(Device *device, Scene *scene, Pro
|
||||
}
|
||||
|
||||
Volume *volume = static_cast<Volume *>(geom);
|
||||
create_volume_mesh(volume, progress);
|
||||
create_volume_mesh(scene, volume, progress);
|
||||
|
||||
/* always reallocate when we have a volume, as we need to rebuild the BVH */
|
||||
device_update_flags |= DEVICE_MESH_DATA_NEEDS_REALLOC;
|
||||
|
@@ -216,7 +216,7 @@ class GeometryManager {
|
||||
protected:
|
||||
bool displace(Device *device, Scene *scene, Mesh *mesh, Progress &progress);
|
||||
|
||||
void create_volume_mesh(Volume *volume, Progress &progress);
|
||||
void create_volume_mesh(const Scene *scene, Volume *volume, Progress &progress);
|
||||
|
||||
/* Attributes */
|
||||
void update_osl_attributes(Device *device,
|
||||
|
@@ -64,6 +64,11 @@ struct ToNanoOp {
|
||||
}
|
||||
};
|
||||
# endif
|
||||
|
||||
VDBImageLoader::VDBImageLoader(openvdb::GridBase::ConstPtr grid_, const string &grid_name)
|
||||
: grid_name(grid_name), grid(grid_)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
VDBImageLoader::VDBImageLoader(const string &grid_name) : grid_name(grid_name)
|
||||
|
@@ -17,6 +17,9 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
class VDBImageLoader : public ImageLoader {
|
||||
public:
|
||||
#ifdef WITH_OPENVDB
|
||||
VDBImageLoader(openvdb::GridBase::ConstPtr grid_, const string &grid_name);
|
||||
#endif
|
||||
VDBImageLoader(const string &grid_name);
|
||||
~VDBImageLoader();
|
||||
|
||||
|
@@ -690,12 +690,16 @@ void Mesh::pack_shaders(Scene *scene, uint *tri_shader)
|
||||
bool last_smooth = false;
|
||||
|
||||
size_t triangles_size = num_triangles();
|
||||
int *shader_ptr = shader.data();
|
||||
const int *shader_ptr = shader.data();
|
||||
const bool *smooth_ptr = smooth.data();
|
||||
|
||||
for (size_t i = 0; i < triangles_size; i++) {
|
||||
if (shader_ptr[i] != last_shader || last_smooth != smooth[i]) {
|
||||
last_shader = shader_ptr[i];
|
||||
last_smooth = smooth[i];
|
||||
const int new_shader = shader_ptr ? shader_ptr[i] : INT_MAX;
|
||||
const bool new_smooth = smooth_ptr ? smooth_ptr[i] : false;
|
||||
|
||||
if (new_shader != last_shader || last_smooth != new_smooth) {
|
||||
last_shader = new_shader;
|
||||
last_smooth = new_smooth;
|
||||
Shader *shader = (last_shader < used_shaders.size()) ?
|
||||
static_cast<Shader *>(used_shaders[last_shader]) :
|
||||
scene->default_surface;
|
||||
|
@@ -439,6 +439,14 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
|
||||
flag |= SD_OBJECT_HAS_VERTEX_MOTION;
|
||||
}
|
||||
}
|
||||
else if (geom->is_volume()) {
|
||||
Volume *volume = static_cast<Volume *>(geom);
|
||||
if (volume->attributes.find(ATTR_STD_VOLUME_VELOCITY) &&
|
||||
volume->get_velocity_scale() != 0.0f) {
|
||||
flag |= SD_OBJECT_HAS_VOLUME_MOTION;
|
||||
kobject.velocity_scale = volume->get_velocity_scale();
|
||||
}
|
||||
}
|
||||
|
||||
if (state->need_motion == Scene::MOTION_PASS) {
|
||||
/* Clear motion array if there is no actual motion. */
|
||||
|
@@ -321,7 +321,7 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo, const bo
|
||||
break;
|
||||
|
||||
case PASS_AOV_COLOR:
|
||||
pass_info.num_components = 3;
|
||||
pass_info.num_components = 4;
|
||||
break;
|
||||
case PASS_AOV_VALUE:
|
||||
pass_info.num_components = 1;
|
||||
|
@@ -381,7 +381,7 @@ void Scene::device_update(Device *device_, Progress &progress)
|
||||
}
|
||||
}
|
||||
|
||||
Scene::MotionType Scene::need_motion()
|
||||
Scene::MotionType Scene::need_motion() const
|
||||
{
|
||||
if (integrator->get_motion_blur())
|
||||
return MOTION_BLUR;
|
||||
@@ -407,6 +407,10 @@ bool Scene::need_global_attribute(AttributeStandard std)
|
||||
return need_motion() != MOTION_NONE;
|
||||
else if (std == ATTR_STD_MOTION_VERTEX_NORMAL)
|
||||
return need_motion() == MOTION_BLUR;
|
||||
else if (std == ATTR_STD_VOLUME_VELOCITY || std == ATTR_STD_VOLUME_VELOCITY_X ||
|
||||
std == ATTR_STD_VOLUME_VELOCITY_Y || std == ATTR_STD_VOLUME_VELOCITY_Z) {
|
||||
return need_motion() != MOTION_NONE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -257,7 +257,7 @@ class Scene : public NodeOwner {
|
||||
void need_global_attributes(AttributeRequestSet &attributes);
|
||||
|
||||
enum MotionType { MOTION_NONE = 0, MOTION_PASS, MOTION_BLUR };
|
||||
MotionType need_motion();
|
||||
MotionType need_motion() const;
|
||||
float motion_shutter_time();
|
||||
|
||||
bool need_update();
|
||||
|
@@ -579,6 +579,10 @@ void ShaderManager::device_update_common(Device * /*device*/,
|
||||
kfilm->xyz_to_g = float3_to_float4(xyz_to_g);
|
||||
kfilm->xyz_to_b = float3_to_float4(xyz_to_b);
|
||||
kfilm->rgb_to_y = float3_to_float4(rgb_to_y);
|
||||
kfilm->rec709_to_r = float3_to_float4(rec709_to_r);
|
||||
kfilm->rec709_to_g = float3_to_float4(rec709_to_g);
|
||||
kfilm->rec709_to_b = float3_to_float4(rec709_to_b);
|
||||
kfilm->is_rec709 = is_rec709;
|
||||
}
|
||||
|
||||
void ShaderManager::device_free_common(Device *, DeviceScene *dscene, Scene *scene)
|
||||
@@ -740,6 +744,11 @@ float ShaderManager::linear_rgb_to_gray(float3 c)
|
||||
return dot(c, rgb_to_y);
|
||||
}
|
||||
|
||||
float3 ShaderManager::rec709_to_scene_linear(float3 c)
|
||||
{
|
||||
return make_float3(dot(rec709_to_r, c), dot(rec709_to_g, c), dot(rec709_to_b, c));
|
||||
}
|
||||
|
||||
string ShaderManager::get_cryptomatte_materials(Scene *scene)
|
||||
{
|
||||
string manifest = "{";
|
||||
@@ -802,11 +811,29 @@ void ShaderManager::init_xyz_transforms()
|
||||
{
|
||||
/* Default to ITU-BT.709 in case no appropriate transform found.
|
||||
* Note XYZ here is defined as having a D65 white point. */
|
||||
xyz_to_r = make_float3(3.2404542f, -1.5371385f, -0.4985314f);
|
||||
xyz_to_g = make_float3(-0.9692660f, 1.8760108f, 0.0415560f);
|
||||
xyz_to_b = make_float3(0.0556434f, -0.2040259f, 1.0572252f);
|
||||
const Transform xyz_to_rec709 = make_transform(3.2404542f,
|
||||
-1.5371385f,
|
||||
-0.4985314f,
|
||||
0.0f,
|
||||
-0.9692660f,
|
||||
1.8760108f,
|
||||
0.0415560f,
|
||||
0.0f,
|
||||
0.0556434f,
|
||||
-0.2040259f,
|
||||
1.0572252f,
|
||||
0.0f);
|
||||
|
||||
xyz_to_r = float4_to_float3(xyz_to_rec709.x);
|
||||
xyz_to_g = float4_to_float3(xyz_to_rec709.y);
|
||||
xyz_to_b = float4_to_float3(xyz_to_rec709.z);
|
||||
rgb_to_y = make_float3(0.2126729f, 0.7151522f, 0.0721750f);
|
||||
|
||||
rec709_to_r = make_float3(1.0f, 0.0f, 0.0f);
|
||||
rec709_to_g = make_float3(0.0f, 1.0f, 0.0f);
|
||||
rec709_to_b = make_float3(0.0f, 0.0f, 1.0f);
|
||||
is_rec709 = true;
|
||||
|
||||
#ifdef WITH_OCIO
|
||||
/* Get from OpenColorO config if it has the required roles. */
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
@@ -857,6 +884,12 @@ void ShaderManager::init_xyz_transforms()
|
||||
|
||||
const Transform rgb_to_xyz = transform_inverse(xyz_to_rgb);
|
||||
rgb_to_y = float4_to_float3(rgb_to_xyz.y);
|
||||
|
||||
const Transform rec709_to_rgb = xyz_to_rgb * transform_inverse(xyz_to_rec709);
|
||||
rec709_to_r = float4_to_float3(rec709_to_rgb.x);
|
||||
rec709_to_g = float4_to_float3(rec709_to_rgb.y);
|
||||
rec709_to_b = float4_to_float3(rec709_to_rgb.z);
|
||||
is_rec709 = transform_equal_threshold(xyz_to_rgb, xyz_to_rec709, 0.0001f);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -208,6 +208,7 @@ class ShaderManager {
|
||||
static void free_memory();
|
||||
|
||||
float linear_rgb_to_gray(float3 c);
|
||||
float3 rec709_to_scene_linear(float3 c);
|
||||
|
||||
string get_cryptomatte_materials(Scene *scene);
|
||||
|
||||
@@ -239,6 +240,10 @@ class ShaderManager {
|
||||
float3 xyz_to_g;
|
||||
float3 xyz_to_b;
|
||||
float3 rgb_to_y;
|
||||
float3 rec709_to_r;
|
||||
float3 rec709_to_g;
|
||||
float3 rec709_to_b;
|
||||
bool is_rec709;
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@@ -5763,7 +5763,9 @@ BlackbodyNode::BlackbodyNode() : ShaderNode(get_node_type())
|
||||
void BlackbodyNode::constant_fold(const ConstantFolder &folder)
|
||||
{
|
||||
if (folder.all_inputs_constant()) {
|
||||
folder.make_constant(svm_math_blackbody_color(temperature));
|
||||
const float3 rgb_rec709 = svm_math_blackbody_color_rec709(temperature);
|
||||
const float3 rgb = folder.scene->shader_manager->rec709_to_scene_linear(rgb_rec709);
|
||||
folder.make_constant(rgb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,9 +10,9 @@
|
||||
# include <openvdb/tools/Dense.h>
|
||||
# include <openvdb/tools/GridTransformer.h>
|
||||
# include <openvdb/tools/Morphology.h>
|
||||
# include <openvdb/tools/Statistics.h>
|
||||
#endif
|
||||
|
||||
#include "util/foreach.h"
|
||||
#include "util/hash.h"
|
||||
#include "util/log.h"
|
||||
#include "util/openvdb.h"
|
||||
@@ -28,6 +28,7 @@ NODE_DEFINE(Volume)
|
||||
SOCKET_FLOAT(clipping, "Clipping", 0.001f);
|
||||
SOCKET_FLOAT(step_size, "Step Size", 0.0f);
|
||||
SOCKET_BOOLEAN(object_space, "Object Space", false);
|
||||
SOCKET_FLOAT(velocity_scale, "Velocity Scale", 1.0f);
|
||||
|
||||
return type;
|
||||
}
|
||||
@@ -482,11 +483,141 @@ static openvdb::GridBase::ConstPtr openvdb_grid_from_device_texture(device_textu
|
||||
|
||||
return sparse;
|
||||
}
|
||||
|
||||
static int estimate_required_velocity_padding(openvdb::GridBase::ConstPtr grid,
|
||||
float velocity_scale)
|
||||
{
|
||||
/* TODO: we may need to also find outliers and clamp them to avoid adding too much padding. */
|
||||
openvdb::math::Extrema extrema;
|
||||
openvdb::Vec3d voxel_size;
|
||||
|
||||
/* External .vdb files have a vec3 type for velocity, but the Blender exporter creates a vec4. */
|
||||
if (grid->isType<openvdb::Vec3fGrid>()) {
|
||||
openvdb::Vec3fGrid::ConstPtr vel_grid = openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid);
|
||||
extrema = openvdb::tools::extrema(vel_grid->cbeginValueOn());
|
||||
voxel_size = vel_grid->voxelSize();
|
||||
}
|
||||
else if (grid->isType<openvdb::Vec4fGrid>()) {
|
||||
openvdb::Vec4fGrid::ConstPtr vel_grid = openvdb::gridConstPtrCast<openvdb::Vec4fGrid>(grid);
|
||||
extrema = openvdb::tools::extrema(vel_grid->cbeginValueOn());
|
||||
voxel_size = vel_grid->voxelSize();
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We should only have uniform grids, so x = y = z, but we never know. */
|
||||
const double max_voxel_size = openvdb::math::Max(voxel_size.x(), voxel_size.y(), voxel_size.z());
|
||||
if (max_voxel_size == 0.0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const double estimated_padding = extrema.max() * static_cast<double>(velocity_scale) /
|
||||
max_voxel_size;
|
||||
|
||||
return static_cast<int>(std::ceil(estimated_padding));
|
||||
}
|
||||
|
||||
static openvdb::FloatGrid::ConstPtr get_vdb_for_attribute(Volume *volume, AttributeStandard std)
|
||||
{
|
||||
Attribute *attr = volume->attributes.find(std);
|
||||
if (!attr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ImageHandle &handle = attr->data_voxel();
|
||||
VDBImageLoader *vdb_loader = handle.vdb_loader();
|
||||
if (!vdb_loader) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
openvdb::GridBase::ConstPtr grid = vdb_loader->get_grid();
|
||||
if (!grid) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!grid->isType<openvdb::FloatGrid>()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid);
|
||||
}
|
||||
|
||||
class MergeScalarGrids {
|
||||
typedef openvdb::FloatTree ScalarTree;
|
||||
|
||||
openvdb::tree::ValueAccessor<const ScalarTree> m_acc_x, m_acc_y, m_acc_z;
|
||||
|
||||
public:
|
||||
MergeScalarGrids(const ScalarTree *x_tree, const ScalarTree *y_tree, const ScalarTree *z_tree)
|
||||
: m_acc_x(*x_tree), m_acc_y(*y_tree), m_acc_z(*z_tree)
|
||||
{
|
||||
}
|
||||
|
||||
MergeScalarGrids(const MergeScalarGrids &other)
|
||||
: m_acc_x(other.m_acc_x), m_acc_y(other.m_acc_y), m_acc_z(other.m_acc_z)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(const openvdb::Vec3STree::ValueOnIter &it) const
|
||||
{
|
||||
using namespace openvdb;
|
||||
|
||||
const math::Coord xyz = it.getCoord();
|
||||
float x = m_acc_x.getValue(xyz);
|
||||
float y = m_acc_y.getValue(xyz);
|
||||
float z = m_acc_z.getValue(xyz);
|
||||
|
||||
it.setValue(math::Vec3s(x, y, z));
|
||||
}
|
||||
};
|
||||
|
||||
static void merge_scalar_grids_for_velocity(const Scene *scene, Volume *volume)
|
||||
{
|
||||
if (volume->attributes.find(ATTR_STD_VOLUME_VELOCITY)) {
|
||||
/* A vector grid for velocity is already available. */
|
||||
return;
|
||||
}
|
||||
|
||||
openvdb::FloatGrid::ConstPtr vel_x_grid = get_vdb_for_attribute(volume,
|
||||
ATTR_STD_VOLUME_VELOCITY_X);
|
||||
openvdb::FloatGrid::ConstPtr vel_y_grid = get_vdb_for_attribute(volume,
|
||||
ATTR_STD_VOLUME_VELOCITY_Y);
|
||||
openvdb::FloatGrid::ConstPtr vel_z_grid = get_vdb_for_attribute(volume,
|
||||
ATTR_STD_VOLUME_VELOCITY_Z);
|
||||
|
||||
if (!(vel_x_grid && vel_y_grid && vel_z_grid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
openvdb::Vec3fGrid::Ptr vecgrid = openvdb::Vec3SGrid::create(openvdb::Vec3s(0.0f));
|
||||
|
||||
/* Activate voxels in the vector grid based on the scalar grids to ensure thread safety during
|
||||
* the merge. */
|
||||
vecgrid->tree().topologyUnion(vel_x_grid->tree());
|
||||
vecgrid->tree().topologyUnion(vel_y_grid->tree());
|
||||
vecgrid->tree().topologyUnion(vel_z_grid->tree());
|
||||
|
||||
MergeScalarGrids op(&vel_x_grid->tree(), &vel_y_grid->tree(), &vel_z_grid->tree());
|
||||
openvdb::tools::foreach (vecgrid->beginValueOn(), op, true, false);
|
||||
|
||||
/* Assume all grids have the same transformation. */
|
||||
openvdb::math::Transform::Ptr transform = openvdb::ConstPtrCast<openvdb::math::Transform>(
|
||||
vel_x_grid->transformPtr());
|
||||
vecgrid->setTransform(transform);
|
||||
|
||||
/* Make an attribute for it. */
|
||||
Attribute *attr = volume->attributes.add(ATTR_STD_VOLUME_VELOCITY);
|
||||
ImageLoader *loader = new VDBImageLoader(vecgrid, "merged_velocity");
|
||||
ImageParams params;
|
||||
attr->data_voxel() = scene->image_manager->add_image(loader, params);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
|
||||
void GeometryManager::create_volume_mesh(const Scene *scene, Volume *volume, Progress &progress)
|
||||
{
|
||||
string msg = string_printf("Computing Volume Mesh %s", volume->name.c_str());
|
||||
progress.set_status("Updating Mesh", msg);
|
||||
@@ -495,7 +626,7 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
|
||||
Shader *volume_shader = NULL;
|
||||
int pad_size = 0;
|
||||
|
||||
foreach (Node *node, volume->get_used_shaders()) {
|
||||
for (Node *node : volume->get_used_shaders()) {
|
||||
Shader *shader = static_cast<Shader *>(node);
|
||||
|
||||
if (!shader->has_volume) {
|
||||
@@ -529,7 +660,9 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
|
||||
VolumeMeshBuilder builder;
|
||||
|
||||
#ifdef WITH_OPENVDB
|
||||
foreach (Attribute &attr, volume->attributes.attributes) {
|
||||
merge_scalar_grids_for_velocity(scene, volume);
|
||||
|
||||
for (Attribute &attr : volume->attributes.attributes) {
|
||||
if (attr.element != ATTR_ELEMENT_VOXEL) {
|
||||
continue;
|
||||
}
|
||||
@@ -567,9 +700,17 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
|
||||
}
|
||||
|
||||
if (grid) {
|
||||
/* Add padding based on the maximum velocity vector. */
|
||||
if (attr.std == ATTR_STD_VOLUME_VELOCITY && scene->need_motion() != Scene::MOTION_NONE) {
|
||||
pad_size = max(pad_size,
|
||||
estimate_required_velocity_padding(grid, volume->get_velocity_scale()));
|
||||
}
|
||||
|
||||
builder.add_grid(grid, do_clipping, volume->get_clipping());
|
||||
}
|
||||
}
|
||||
#else
|
||||
(void)scene;
|
||||
#endif
|
||||
|
||||
/* If nothing to build, early out. */
|
||||
|
@@ -18,6 +18,7 @@ class Volume : public Mesh {
|
||||
NODE_SOCKET_API(float, clipping)
|
||||
NODE_SOCKET_API(float, step_size)
|
||||
NODE_SOCKET_API(bool, object_space)
|
||||
NODE_SOCKET_API(float, velocity_scale)
|
||||
|
||||
virtual void clear(bool preserve_shaders = false) override;
|
||||
};
|
||||
|
@@ -32,6 +32,12 @@
|
||||
# define SIMD_SET_FLUSH_TO_ZERO \
|
||||
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); \
|
||||
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||
# define _MM_FLUSH_ZERO_ON 24
|
||||
# define __get_fpcr(__fpcr) __asm__ __volatile__("mrs %0,fpcr" : "=r"(__fpcr))
|
||||
# define __set_fpcr(__fpcr) __asm__ __volatile__("msr fpcr,%0" : : "ri"(__fpcr))
|
||||
# define SIMD_SET_FLUSH_TO_ZERO set_fz(_MM_FLUSH_ZERO_ON);
|
||||
# define SIMD_GET_FLUSH_TO_ZERO get_fz(_MM_FLUSH_ZERO_ON)
|
||||
#else
|
||||
# define SIMD_SET_FLUSH_TO_ZERO
|
||||
#endif
|
||||
@@ -104,6 +110,23 @@ static struct PosInfTy {
|
||||
static struct StepTy {
|
||||
} step ccl_attr_maybe_unused;
|
||||
|
||||
#endif
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
__forceinline int set_fz(uint32_t flag)
|
||||
{
|
||||
uint64_t old_fpcr, new_fpcr;
|
||||
__get_fpcr(old_fpcr);
|
||||
new_fpcr = old_fpcr | (1ULL << flag);
|
||||
__set_fpcr(new_fpcr);
|
||||
__get_fpcr(old_fpcr);
|
||||
return old_fpcr == new_fpcr;
|
||||
}
|
||||
__forceinline int get_fz(uint32_t flag)
|
||||
{
|
||||
uint64_t cur_fpcr;
|
||||
__get_fpcr(cur_fpcr);
|
||||
return (cur_fpcr & (1ULL << flag)) > 0 ? 1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Utilities used by Neon */
|
||||
|
@@ -25,6 +25,17 @@ CCL_NAMESPACE_BEGIN
|
||||
using tbb::blocked_range;
|
||||
using tbb::enumerable_thread_specific;
|
||||
using tbb::parallel_for;
|
||||
using tbb::parallel_for_each;
|
||||
|
||||
static inline void thread_capture_fp_settings()
|
||||
{
|
||||
#if TBB_INTERFACE_VERSION_MAJOR >= 12
|
||||
tbb::task_group_context *ctx = tbb::task::current_context();
|
||||
#else
|
||||
tbb::task_group_context *ctx = tbb::task::self().group();
|
||||
#endif
|
||||
ctx->capture_fp_settings();
|
||||
}
|
||||
|
||||
static inline void parallel_for_cancel()
|
||||
{
|
||||
|
@@ -285,6 +285,21 @@ ccl_device_inline bool operator!=(const Transform &A, const Transform &B)
|
||||
return !(A == B);
|
||||
}
|
||||
|
||||
ccl_device_inline bool transform_equal_threshold(const Transform &A,
|
||||
const Transform &B,
|
||||
const float threshold)
|
||||
{
|
||||
for (int x = 0; x < 3; x++) {
|
||||
for (int y = 0; y < 4; y++) {
|
||||
if (fabsf(A[x][y] - B[x][y]) > threshold) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ccl_device_inline float3 transform_get_column(const Transform *t, int column)
|
||||
{
|
||||
return make_float3(t->x[column], t->y[column], t->z[column]);
|
||||
|
@@ -30,8 +30,10 @@ extern GHOST_SystemHandle GHOST_CreateSystem(void);
|
||||
|
||||
/**
|
||||
* Specifies whether debug messages are to be enabled for the specific system handle.
|
||||
* \param systemhandle: The handle to the system.
|
||||
* \param debug: Flag for systems to debug.
|
||||
*/
|
||||
extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, int is_debug_enabled);
|
||||
extern void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, GHOST_Debug debug);
|
||||
|
||||
/**
|
||||
* Disposes the one and only system.
|
||||
|
@@ -452,8 +452,9 @@ class GHOST_ISystem {
|
||||
|
||||
/**
|
||||
* Specify whether debug messages are to be shown.
|
||||
* \param debug: Flag for systems to debug.
|
||||
*/
|
||||
virtual void initDebug(bool is_debug_enabled) = 0;
|
||||
virtual void initDebug(GHOST_Debug debug) = 0;
|
||||
|
||||
/**
|
||||
* Check whether debug messages are to be shown.
|
||||
|
@@ -573,6 +573,16 @@ typedef struct {
|
||||
uint32_t frequency;
|
||||
} GHOST_DisplaySetting;
|
||||
|
||||
typedef enum {
|
||||
/** Axis that cursor grab will wrap. */
|
||||
GHOST_kDebugDefault = (1 << 1),
|
||||
GHOST_kDebugWintab = (1 << 2),
|
||||
} GHOST_TDebugFlags;
|
||||
|
||||
typedef struct {
|
||||
int flags;
|
||||
} GHOST_Debug;
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef void *GHOST_TEmbedderWindowID;
|
||||
#endif // _WIN32
|
||||
|
@@ -30,11 +30,11 @@ GHOST_SystemHandle GHOST_CreateSystem(void)
|
||||
return (GHOST_SystemHandle)system;
|
||||
}
|
||||
|
||||
void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, int is_debug_enabled)
|
||||
void GHOST_SystemInitDebug(GHOST_SystemHandle systemhandle, GHOST_Debug debug)
|
||||
{
|
||||
GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
|
||||
|
||||
system->initDebug(is_debug_enabled);
|
||||
system->initDebug(debug);
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_DisposeSystem(GHOST_SystemHandle systemhandle)
|
||||
|
@@ -390,9 +390,9 @@ void GHOST_System::useWindowFocus(const bool use_focus)
|
||||
m_windowFocus = use_focus;
|
||||
}
|
||||
|
||||
void GHOST_System::initDebug(bool is_debug_enabled)
|
||||
void GHOST_System::initDebug(GHOST_Debug debug)
|
||||
{
|
||||
m_is_debug_enabled = is_debug_enabled;
|
||||
m_is_debug_enabled = debug.flags & GHOST_kDebugDefault;
|
||||
}
|
||||
|
||||
bool GHOST_System::isDebugEnabled()
|
||||
|
@@ -334,8 +334,9 @@ class GHOST_System : public GHOST_ISystem {
|
||||
|
||||
/**
|
||||
* Specify whether debug messages are to be shown.
|
||||
* \param debug: Flag for systems to debug.
|
||||
*/
|
||||
virtual void initDebug(bool is_debug_enabled);
|
||||
virtual void initDebug(GHOST_Debug debug);
|
||||
|
||||
/**
|
||||
* Check whether debug messages are to be shown.
|
||||
|
@@ -872,6 +872,13 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
|
||||
int msgPosY = GET_Y_LPARAM(msgPos);
|
||||
system->pushEvent(new GHOST_EventCursor(
|
||||
::GetMessageTime(), GHOST_kEventCursorMove, window, msgPosX, msgPosY, td));
|
||||
|
||||
if (type == GHOST_kEventButtonDown) {
|
||||
WINTAB_PRINTF("HWND %p OS button down\n", window->getHWND());
|
||||
}
|
||||
else if (type == GHOST_kEventButtonUp) {
|
||||
WINTAB_PRINTF("HWND %p OS button up\n", window->getHWND());
|
||||
}
|
||||
}
|
||||
|
||||
window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased);
|
||||
@@ -914,6 +921,8 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
||||
break;
|
||||
}
|
||||
case GHOST_kEventButtonDown: {
|
||||
WINTAB_PRINTF("HWND %p Wintab button down", window->getHWND());
|
||||
|
||||
UINT message;
|
||||
switch (info.button) {
|
||||
case GHOST_kButtonMaskLeft:
|
||||
@@ -939,9 +948,12 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
||||
/* Test for Win32/Wintab button down match. */
|
||||
useWintabPos = wt->testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y);
|
||||
if (!useWintabPos) {
|
||||
WINTAB_PRINTF(" ... but associated system button mismatched position\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
WINTAB_PRINTF(" ... associated to system button\n");
|
||||
|
||||
/* Steal the Win32 event which was previously peeked. */
|
||||
PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD);
|
||||
|
||||
@@ -958,9 +970,14 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
||||
mouseMoveHandled = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
WINTAB_PRINTF(" ... but no system button\n");
|
||||
}
|
||||
}
|
||||
case GHOST_kEventButtonUp: {
|
||||
WINTAB_PRINTF("HWND %p Wintab button up", window->getHWND());
|
||||
if (!useWintabPos) {
|
||||
WINTAB_PRINTF(" ... but Wintab position isn't trusted\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -986,10 +1003,14 @@ void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
|
||||
if (PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD) &&
|
||||
msg.message != WM_QUIT) {
|
||||
|
||||
WINTAB_PRINTF(" ... associated to system button\n");
|
||||
window->updateMouseCapture(MouseReleased);
|
||||
system->pushEvent(
|
||||
new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
|
||||
}
|
||||
else {
|
||||
WINTAB_PRINTF(" ... but no system button\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -1318,6 +1339,12 @@ void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api)
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::initDebug(GHOST_Debug debug)
|
||||
{
|
||||
GHOST_System::initDebug(debug);
|
||||
GHOST_Wintab::setDebug(debug.flags & GHOST_kDebugWintab);
|
||||
}
|
||||
|
||||
void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax)
|
||||
{
|
||||
minmax->ptMinTrackSize.x = 320;
|
||||
@@ -1593,6 +1620,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
// Wintab events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WT_CSRCHANGE: {
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_CSRCHANGE\n", window->getHWND(), (void *)lParam);
|
||||
GHOST_Wintab *wt = window->getWintab();
|
||||
if (wt) {
|
||||
wt->updateCursorInfo();
|
||||
@@ -1601,6 +1629,20 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
break;
|
||||
}
|
||||
case WT_PROXIMITY: {
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_PROXIMITY\n", window->getHWND(), (void *)wParam);
|
||||
if (LOWORD(lParam)) {
|
||||
WINTAB_PRINTF(" Cursor entering context.\n");
|
||||
}
|
||||
else {
|
||||
WINTAB_PRINTF(" Cursor leaving context.\n");
|
||||
}
|
||||
if (HIWORD(lParam)) {
|
||||
WINTAB_PRINTF(" Cursor entering or leaving hardware proximity.\n");
|
||||
}
|
||||
else {
|
||||
WINTAB_PRINTF(" Cursor neither entering nor leaving hardware proximity.\n");
|
||||
}
|
||||
|
||||
GHOST_Wintab *wt = window->getWintab();
|
||||
if (wt) {
|
||||
bool inRange = LOWORD(lParam);
|
||||
@@ -1616,6 +1658,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
break;
|
||||
}
|
||||
case WT_INFOCHANGE: {
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_INFOCHANGE\n", window->getHWND(), (void *)wParam);
|
||||
GHOST_Wintab *wt = window->getWintab();
|
||||
if (wt) {
|
||||
wt->processInfoChange(lParam);
|
||||
@@ -1632,6 +1675,32 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
eventHandled = true;
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Wintab events, debug
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WT_CTXOPEN:
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXOPEN\n", window->getHWND(), (void *)wParam);
|
||||
break;
|
||||
case WT_CTXCLOSE:
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXCLOSE\n", window->getHWND(), (void *)wParam);
|
||||
break;
|
||||
case WT_CTXUPDATE:
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXUPDATE\n", window->getHWND(), (void *)wParam);
|
||||
break;
|
||||
case WT_CTXOVERLAP:
|
||||
WINTAB_PRINTF("HWND %p HCTX %p WT_CTXOVERLAP", window->getHWND(), (void *)wParam);
|
||||
switch (lParam) {
|
||||
case CXS_DISABLED:
|
||||
WINTAB_PRINTF(" CXS_DISABLED\n");
|
||||
break;
|
||||
case CXS_OBSCURED:
|
||||
WINTAB_PRINTF(" CXS_OBSCURED\n");
|
||||
break;
|
||||
case CXS_ONTOP:
|
||||
WINTAB_PRINTF(" CXS_ONTOP\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Pointer events, processed
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
case WM_POINTERUPDATE:
|
||||
@@ -1692,6 +1761,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
if (!window->m_mousePresent) {
|
||||
WINTAB_PRINTF("HWND %p mouse enter\n", window->getHWND());
|
||||
TRACKMOUSEEVENT tme = {sizeof(tme)};
|
||||
tme.dwFlags = TME_LEAVE;
|
||||
tme.hwndTrack = hwnd;
|
||||
@@ -1740,6 +1810,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
}
|
||||
break;
|
||||
case WM_MOUSELEAVE: {
|
||||
WINTAB_PRINTF("HWND %p mouse leave\n", window->getHWND());
|
||||
window->m_mousePresent = false;
|
||||
if (window->getTabletData().Active == GHOST_kTabletModeNone) {
|
||||
event = processCursorEvent(window);
|
||||
|
@@ -259,6 +259,16 @@ class GHOST_SystemWin32 : public GHOST_System {
|
||||
*/
|
||||
void setTabletAPI(GHOST_TTabletAPI api) override;
|
||||
|
||||
/***************************************************************************************
|
||||
** Debug Info
|
||||
***************************************************************************************/
|
||||
|
||||
/**
|
||||
* Specify which debug messages are to be shown.
|
||||
* \param debug: Flag for systems to debug.
|
||||
*/
|
||||
void initDebug(GHOST_Debug debug) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initializes the system.
|
||||
|
@@ -960,6 +960,7 @@ GHOST_Wintab *GHOST_WindowWin32::getWintab() const
|
||||
void GHOST_WindowWin32::loadWintab(bool enable)
|
||||
{
|
||||
if (!m_wintab) {
|
||||
WINTAB_PRINTF("Loading Wintab for window %p\n", m_hWnd);
|
||||
if (m_wintab = GHOST_Wintab::loadWintab(m_hWnd)) {
|
||||
if (enable) {
|
||||
m_wintab->enable();
|
||||
@@ -982,6 +983,7 @@ void GHOST_WindowWin32::loadWintab(bool enable)
|
||||
|
||||
void GHOST_WindowWin32::closeWintab()
|
||||
{
|
||||
WINTAB_PRINTF("Closing Wintab for window %p\n", m_hWnd);
|
||||
delete m_wintab;
|
||||
m_wintab = NULL;
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@
|
||||
GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
||||
{
|
||||
/* Load Wintab library if available. */
|
||||
|
||||
auto handle = unique_hmodule(::LoadLibrary("Wintab32.dll"), &::FreeLibrary);
|
||||
if (!handle) {
|
||||
return nullptr;
|
||||
@@ -116,6 +115,15 @@ GHOST_Wintab *GHOST_Wintab::loadWintab(HWND hwnd)
|
||||
}
|
||||
}
|
||||
|
||||
int sanityQueueSize = queueSizeGet(hctx.get());
|
||||
WINTAB_PRINTF("HCTX %p %s queueSize: %d, queueSizeGet: %d\n",
|
||||
hctx.get(),
|
||||
__func__,
|
||||
queueSize,
|
||||
sanityQueueSize);
|
||||
|
||||
WINTAB_PRINTF("Loaded Wintab context %p\n", hctx.get());
|
||||
|
||||
return new GHOST_Wintab(std::move(handle),
|
||||
info,
|
||||
get,
|
||||
@@ -183,7 +191,17 @@ GHOST_Wintab::GHOST_Wintab(unique_hmodule handle,
|
||||
m_pkts{queueSize}
|
||||
{
|
||||
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
|
||||
WINTAB_PRINTF("Wintab Devices: %d\n", m_numDevices);
|
||||
|
||||
updateCursorInfo();
|
||||
|
||||
/* Debug info. */
|
||||
printContextDebugInfo();
|
||||
}
|
||||
|
||||
GHOST_Wintab::~GHOST_Wintab()
|
||||
{
|
||||
WINTAB_PRINTF("Closing Wintab context %p\n", m_context.get());
|
||||
}
|
||||
|
||||
void GHOST_Wintab::enable()
|
||||
@@ -249,6 +267,7 @@ void GHOST_Wintab::updateCursorInfo()
|
||||
|
||||
BOOL pressureSupport = m_fpInfo(WTI_DEVICES, DVC_NPRESSURE, &Pressure);
|
||||
m_maxPressure = pressureSupport ? Pressure.axMax : 0;
|
||||
WINTAB_PRINTF("HCTX %p %s maxPressure: %d\n", m_context.get(), __func__, m_maxPressure);
|
||||
|
||||
BOOL tiltSupport = m_fpInfo(WTI_DEVICES, DVC_ORIENTATION, &Orientation);
|
||||
/* Check if tablet supports azimuth [0] and altitude [1], encoded in axResolution. */
|
||||
@@ -259,6 +278,11 @@ void GHOST_Wintab::updateCursorInfo()
|
||||
else {
|
||||
m_maxAzimuth = m_maxAltitude = 0;
|
||||
}
|
||||
WINTAB_PRINTF("HCTX %p %s maxAzimuth: %d, maxAltitude: %d\n",
|
||||
m_context.get(),
|
||||
__func__,
|
||||
m_maxAzimuth,
|
||||
m_maxAltitude);
|
||||
}
|
||||
|
||||
void GHOST_Wintab::processInfoChange(LPARAM lParam)
|
||||
@@ -266,6 +290,7 @@ void GHOST_Wintab::processInfoChange(LPARAM lParam)
|
||||
/* Update number of connected Wintab digitizers. */
|
||||
if (LOWORD(lParam) == WTI_INTERFACE && HIWORD(lParam) == IFC_NDEVICES) {
|
||||
m_fpInfo(WTI_INTERFACE, IFC_NDEVICES, &m_numDevices);
|
||||
WINTAB_PRINTF("HCTX %p %s numDevices: %d\n", m_context.get(), __func__, m_numDevices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,3 +481,144 @@ bool GHOST_Wintab::testCoordinates(int sysX, int sysY, int wtX, int wtY)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_Wintab::m_debug = false;
|
||||
|
||||
void GHOST_Wintab::setDebug(bool debug)
|
||||
{
|
||||
m_debug = debug;
|
||||
}
|
||||
|
||||
bool GHOST_Wintab::getDebug()
|
||||
{
|
||||
return m_debug;
|
||||
}
|
||||
|
||||
void GHOST_Wintab::printContextDebugInfo()
|
||||
{
|
||||
if (!m_debug) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print button maps. */
|
||||
BYTE logicalButtons[32] = {0};
|
||||
BYTE systemButtons[32] = {0};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
printf("initializeWintab cursor %d buttons\n", i);
|
||||
UINT lbut = m_fpInfo(WTI_CURSORS + i, CSR_BUTTONMAP, &logicalButtons);
|
||||
if (lbut) {
|
||||
printf("%d", logicalButtons[0]);
|
||||
for (int j = 1; j < lbut; j++) {
|
||||
printf(", %d", logicalButtons[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else {
|
||||
printf("logical button error\n");
|
||||
}
|
||||
UINT sbut = m_fpInfo(WTI_CURSORS + i, CSR_SYSBTNMAP, &systemButtons);
|
||||
if (sbut) {
|
||||
printf("%d", systemButtons[0]);
|
||||
for (int j = 1; j < sbut; j++) {
|
||||
printf(", %d", systemButtons[j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
else {
|
||||
printf("system button error\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print context information. */
|
||||
|
||||
/* Print open context constraints. */
|
||||
UINT maxcontexts, opencontexts;
|
||||
m_fpInfo(WTI_INTERFACE, IFC_NCONTEXTS, &maxcontexts);
|
||||
m_fpInfo(WTI_STATUS, STA_CONTEXTS, &opencontexts);
|
||||
printf("%u max contexts, %u open contexts\n", maxcontexts, opencontexts);
|
||||
|
||||
/* Print system information. */
|
||||
printf("left: %d, top: %d, width: %d, height: %d\n",
|
||||
::GetSystemMetrics(SM_XVIRTUALSCREEN),
|
||||
::GetSystemMetrics(SM_YVIRTUALSCREEN),
|
||||
::GetSystemMetrics(SM_CXVIRTUALSCREEN),
|
||||
::GetSystemMetrics(SM_CYVIRTUALSCREEN));
|
||||
|
||||
auto printContextRanges = [](LOGCONTEXT &lc) {
|
||||
printf("lcInOrgX: %d, lcInOrgY: %d, lcInExtX: %d, lcInExtY: %d\n",
|
||||
lc.lcInOrgX,
|
||||
lc.lcInOrgY,
|
||||
lc.lcInExtX,
|
||||
lc.lcInExtY);
|
||||
printf("lcOutOrgX: %d, lcOutOrgY: %d, lcOutExtX: %d, lcOutExtY: %d\n",
|
||||
lc.lcOutOrgX,
|
||||
lc.lcOutOrgY,
|
||||
lc.lcOutExtX,
|
||||
lc.lcOutExtY);
|
||||
printf("lcSysOrgX: %d, lcSysOrgY: %d, lcSysExtX: %d, lcSysExtY: %d\n",
|
||||
lc.lcSysOrgX,
|
||||
lc.lcSysOrgY,
|
||||
lc.lcSysExtX,
|
||||
lc.lcSysExtY);
|
||||
};
|
||||
|
||||
LOGCONTEXT lc;
|
||||
|
||||
/* Print system context. */
|
||||
m_fpInfo(WTI_DEFSYSCTX, 0, &lc);
|
||||
printf("WTI_DEFSYSCTX\n");
|
||||
printContextRanges(lc);
|
||||
|
||||
/* Print system context, manually populated. */
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_INORGX, &lc.lcInOrgX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_INORGY, &lc.lcInOrgY);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_INEXTX, &lc.lcInExtX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_INEXTY, &lc.lcInExtY);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_OUTORGX, &lc.lcOutOrgX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_OUTORGY, &lc.lcOutOrgY);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_OUTEXTX, &lc.lcOutExtX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_OUTEXTY, &lc.lcOutExtY);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_SYSORGX, &lc.lcSysOrgX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_SYSORGY, &lc.lcSysOrgY);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_SYSEXTX, &lc.lcSysExtX);
|
||||
m_fpInfo(WTI_DEFSYSCTX, CTX_SYSEXTY, &lc.lcSysExtY);
|
||||
printf("WTI_DEFSYSCTX CTX_*\n");
|
||||
printContextRanges(lc);
|
||||
|
||||
for (unsigned int i = 0; i < m_numDevices; i++) {
|
||||
/* Print individual device system context. */
|
||||
m_fpInfo(WTI_DSCTXS + i, 0, &lc);
|
||||
printf("WTI_DSCTXS %u\n", i);
|
||||
printContextRanges(lc);
|
||||
|
||||
/* Print individual device system context, manually populated. */
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_INORGX, &lc.lcInOrgX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_INORGY, &lc.lcInOrgY);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_INEXTX, &lc.lcInExtX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_INEXTY, &lc.lcInExtY);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_OUTORGX, &lc.lcOutOrgX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_OUTORGY, &lc.lcOutOrgY);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_OUTEXTX, &lc.lcOutExtX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_OUTEXTY, &lc.lcOutExtY);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_SYSORGX, &lc.lcSysOrgX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_SYSORGY, &lc.lcSysOrgY);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_SYSEXTX, &lc.lcSysExtX);
|
||||
m_fpInfo(WTI_DSCTXS + i, CTX_SYSEXTY, &lc.lcSysExtY);
|
||||
printf("WTI_DSCTX %u CTX_*\n", i);
|
||||
printContextRanges(lc);
|
||||
|
||||
/* Print device axis. */
|
||||
AXIS axis_x, axis_y;
|
||||
m_fpInfo(WTI_DEVICES + i, DVC_X, &axis_x);
|
||||
m_fpInfo(WTI_DEVICES + i, DVC_Y, &axis_y);
|
||||
printf("WTI_DEVICES %u axis_x org: %d, axis_y org: %d axis_x ext: %d, axis_y ext: %d\n",
|
||||
i,
|
||||
axis_x.axMin,
|
||||
axis_y.axMin,
|
||||
axis_x.axMax - axis_x.axMin + 1,
|
||||
axis_y.axMax - axis_y.axMin + 1);
|
||||
}
|
||||
|
||||
/* Other stuff while we have a log-context. */
|
||||
printf("sysmode %d\n", lc.lcSysMode);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user