提交 9772673e 编写于 作者: M Matt Pharr

Initial commit for public release.

上级
*~
.#*
#*#
src/build
.DS_Store
.ipynb_checkpoints/
build/
[submodule "src/ext/zlib"]
path = src/ext/zlib
url = https://github.com/mitsuba-renderer/zlib
[submodule "src/ext/ptex"]
path = src/ext/ptex
url = https://github.com/wdas/ptex.git
[submodule "src/ext/double-conversion"]
path = src/ext/double-conversion
url = https://github.com/mmp/double-conversion
[submodule "src/ext/stb"]
path = src/ext/stb
url = https://github.com/nothings/stb.git
[submodule "src/ext/openexr"]
path = src/ext/openexr
url = https://github.com/mmp/openexr.git
branch = zlibstatic-export-workaround
[submodule "src/ext/filesystem"]
path = src/ext/filesystem
url = https://github.com/wjakob/filesystem.git
此差异已折叠。
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
pbrt, Version 4 (Early Release)
===============================
This is an early release of pbrt-v4, the rendering system that will be
described in the (eventually) forthcoming fourth edition of *Physically
Based Rendering: From Theory to Implementation*. (We hope to have an
online version of the book posted late in 2020 and printed books available
in Spring 2021.)
We are making this code available for hardy adventurers; it's not yet
extensively documented, but if you're familiar with previous versions of
pbrt, you should be able to make your away around it. Our hope is that the
system will be useful to some people in its current form and that any bugs
in the current implementation might be found now, allowing us to correct
them before the book is final.
A number of scenes for pbrt-v4 are [available in a git repository](TODO).
Features
--------
pbrt-v4 represents a substantial update to the previous version of pbrt-v3.
Major changes include:
* Spectral rendering
* Rendering computations are always performed using
point-sampled spectra; the use of RGB color is limited to the scene
description (e.g., image texture maps), and final image output.
* Modernized volumetric scattering
* An all-new `VolPathIntegrator` based on the null-scattering path
integral formulation of [Miller et
al. 2019](https://cs.dartmouth.edu/~wjarosz/publications/miller19null.html)
has been added.
* Tighter majorants are used for null-scattering with the `GridDensityMedium`
via a separate low-resolution grid of majorants.
* Emissive volumes are now supported.
* Support for rendering on GPUs is available on systems that have CUDA and OptiX.
* The GPU path provides all of the functionality of the CPU-based
`VolPathIntegrator`, including volumetric scattering, subsurface
scattering, all of pbrt's cameras, samplers, shapes, lights, materials
and BxDFs, etc.
* Performance is substantially faster than rendering on the CPU.
* New BxDFs and Materials
* The provided BxDFs and Materials have been redesigned to be more
closely tied to physical scattering processes, along the lines of
Mitsuba's materials. (Among other things, the kitchen-sink UberMaterial
is now gone.)
* Measured BRDFs are now represented using [Dupuy and Jakob's
approach](https://rgl.epfl.ch/publications/Dupuy2018Adaptive).
* Scattering from layered materials is accurately simulated using Monte
Carlo random walks (after [Guo et al. 2018](https://shuangz.com/projects/layered-sa18/).)
* A variety of light sampling improvements have been implemented.
* "Many-light" sampling is available via light BVHs ([Conty and Kulla 2018](http://aconty.com/pdf/many-lights-hpg2018.pdf)).
* Solid angle sampling is used for triangle
([Arvo1995](https://dl.acm.org/doi/10.1145/218380.218500)) and
quadrilateral ([Ureña et al. 2013](https://www.arnoldrenderer.com/research/egsr2013_spherical_rectangle.pdf))
light sources.
* A single ray is now traced for both indirect lighting and BSDF-sampled direct-lighting.
* Warp product sampling is used for approximate cosine-weighted solid angle
sampling ([Hart et al. 2019](https://onlinelibrary.wiley.com/doi/abs/10.1111/cgf.14060)).
* An implementation of Bitterli et al's environment light [portal sampling](https://benedikt-bitterli.me/pmems.html)
technique is included.
* And also...
* Various improvements have been made to the `Sampler` classes, including
better randomization and a new sampler that implements pmj02bn sampling ([Christensen et
al. 2018](https://graphics.pixar.com/library/ProgressiveMultiJitteredSampling/)).
* A new `GBufferFilm` that provides position, normal, albedo, etc., at
each pixel is now available. (This is particularly useful for denoising and ML training.)
* Path regularization (optionally).
* A bilinear patch primitive has been added ([Reshetov 2019](https://link.springer.com/chapter/10.1007/978-1-4842-4427-2_8)).
* Accurate modeling of film response in cameras and photometric lighting controls thanks to a contribution from Anders Langlands and Luca Fascione.
* Various improvements to ray--shape intersection precision.
* Most of the low-level sampling code has been factored out into
stand-alone functions for easier reuse. Also, functions that invert
many sampling techniques are provided.
* Unit tests have been substantially increased.
We have also made a refactoring pass throughout the entire system, cleaning
up various APIs and data types to improve both readability and usability.
Finally, pbrt-v4 can work together with the
[tev](https://github.com/Tom94/tev) image viewer to display the image as
it's being rendered. As of recent versions, *tev* can display images
provided to it via a network socket; by default, it listens to port 14158,
though this can be changed via its ``--hostname`` command-line option. If
you have an instance of *tev* running, you can run pbrt like:
```bash
$ pbrt --display-server localhost:14158 scene.pbrt
```
In that case, the image will be progressively displayed as it renders.
Building the code
-----------------
As before, pbrt uses git submodules for a number of third-party libraries
that it depends on. Therefore, be sure to use the `--recursive` flag when
cloning the repository:
```bash
$ git clone --recursive https://github.com/mmp/pbrt-v4.git
```
If you accidentally clone pbrt without using ``--recursive`` (or to update
the pbrt source tree after a new submodule has been added, run the
following command to also fetch the dependencies:
```bash
$ git submodule update --init --recursive
```
pbrt uses [cmake](http://www.cmake.org/) for its build system. Note that a
release build is the default; provide `-DCMAKE_BUILD_TYPE=Debug` to cmake
for a debug build.
pbrt should build on any system that has C++ compiler with support for
C++17. We welcome PRs that make it build on more systems.
Bug Reports and PRs
-------------------
Please use the [pbrt-v4 github issue
tracker](https://github.com/mmp/pbrt-v4/issues) to report bugs in pbrt-v4.
(We have pre-populated it with a number of issues corresponding to known
bugs in the initial release.)
We are always happy to receive pull requests that fix bugs, including any
bugs you find yourself or open issues in the issue tracker.
Note, however, that in the interests of finishing the book in a finite
amount of time, the functionality of pbrt-v4 is basically fixed at this
point. We therefore will not be merging PRs that make major changes to the
system's operation or structure (but feel free to keep them in your own
forks!). Also, don't bother sending PRs for anything marked "TODO" or
"FIXME" in the source code; we'll take care of those as we finish polishing
things up.
Updating pbrt-v3 scenes
-----------------------
There are a variety of changes to the input file format and, as noted
above, the new format is not yet documented. However, pbrt-v4 partially
makes up for that by providing an automatic upgrade mechanism:
```bash
$ pbrt --upgrade old.pbrt > new.pbrt
```
Most scene files can be automatically updated. In some cases manual
intervention is required; an error message will be printed in this case.
The environment map parameterization has also changed (from equi-rect to an
equi-area mapping); you can upgrade environment maps using
```bash
$ imgtool makeenv old.exr --outfile new.exr
```
Using pbrt on the GPU
---------------------
To run on the GPU, pbrt requires:
* C++17 support on the GPU, including kernel launch with C++ lambdas.
* Unified memory so that the CPU can allocate and initialize data
structures for code that runs on the GPU.
* An API for ray-object intersections on the GPU.
These requirements are effectively what makes it possible to bring pbrt to
the GPU with limited changes to the core system. As a practical matter,
these capabilities are only available via CUDA and OptiX on NVIDIA GPUs
today, though we'd be happy to see pbrt running on any other GPUs that
provide those capabilities.
pbrt's GPU path specifically requires CUDA 11.0 and OptiX 7.1. The build
scripts will automatically attempt to find a CUDA compiler, looking in the
usual places; the cmake output will indicate whether it was successful. It
is necessary to set the cmake `PBRT_OPTIX7_PATH` configuration option to
point at an OptiX 7.1 install.
Even when compiled with GPU support, pbrt uses the CPU by default unless
the `--gpu` command-line option is given. Note that when rendering with
the GPU, the `--spp` command-line flag can be helpful to easily crank up
the number of samples per pixel. Also, it's extra fun to use *tev* to watch
rendering progress.
To denoise images using the OptiX denoiser, set the scene's "Film" type to
be "gbuffer" when rendering and use EXR for the image format; a "deep"
image will be generated with auxilary channels like albedo and normal that
are useful for the denoiser. The resulting EXR can be denoised using
```bash
$ imgtool denoise-optix noisy.exr --outfile denoised.exr
```
pbrt-v4 makes use of the following third-party libraries and data. Thanks
to all of the developers who have made these available!
* [double-conversion](https://github.com/google/double-conversion)
* [filesystem](https://github.com/wjakob/filesystem)
* [googletest](https://github.com/google/googletest)
* [lodepng](https://lodev.org/lodepng/)
* [OpenEXR](http:://www.openexr.com)
* [Ptex](http://ptex.us/)
* [rply](http://w3.impa.br/~diego/software/rply/)
* [skymodel](https://cgg.mff.cuni.cz/projects/SkylightModelling/)
* [stb](https://github.com/nothings/stb)
* [tinyobjloader](https://github.com/tinyobjloader/tinyobjloader)
* [zlib](https://zlib.net/)
Thanks also to Anders Langlands, who provided the Sensor implementation
used in the film model and Syoyo Fujita for the cyhair converter.
pbrt-v4 also includes spectral data from the following sources:
* Glass refractive index tables from https://refractiveindex.info, public
domain CC0.
* Camera sensor measurement data from https://github.com/ampas/rawtoaces,
Copyright © 2017 Academy of Motion Picture Arts and Sciences.
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
# Clang 3.2+ use this version. The no-omit-frame-pointer option is optional.
"-g -fsanitize=address -fno-omit-frame-pointer"
"-g -fsanitize=address"
# Older deprecated flag for ASan
"-g -faddress-sanitizer"
)
if (SANITIZE_ADDRESS AND (SANITIZE_THREAD OR SANITIZE_MEMORY))
message(FATAL_ERROR "AddressSanitizer is not compatible with "
"ThreadSanitizer or MemorySanitizer.")
endif ()
include(sanitize-helpers)
if (SANITIZE_ADDRESS)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "AddressSanitizer"
"ASan")
find_program(ASan_WRAPPER "asan-wrapper" PATHS ${CMAKE_MODULE_PATH})
mark_as_advanced(ASan_WRAPPER)
endif ()
function (add_sanitize_address TARGET)
if (NOT SANITIZE_ADDRESS)
return()
endif ()
saitizer_add_flags(${TARGET} "AddressSanitizer" "ASan")
endfunction ()
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=memory"
)
include(sanitize-helpers)
if (SANITIZE_MEMORY)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for Linux systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for 64bit systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE)
else ()
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer"
"MSan")
endif ()
endif ()
function (add_sanitize_memory TARGET)
if (NOT SANITIZE_MEMORY)
return()
endif ()
saitizer_add_flags(${TARGET} "MemorySanitizer" "MSan")
endfunction ()
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
# If any of the used compiler is a GNU compiler, add a second option to static
# link against the sanitizers.
option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off)
set(FIND_QUIETLY_FLAG "")
if (DEFINED Sanitizers_FIND_QUIETLY)
set(FIND_QUIETLY_FLAG "QUIET")
endif ()
find_package(ASan ${FIND_QUIETLY_FLAG})
find_package(TSan ${FIND_QUIETLY_FLAG})
find_package(MSan ${FIND_QUIETLY_FLAG})
find_package(UBSan ${FIND_QUIETLY_FLAG})
function(sanitizer_add_blacklist_file FILE)
if(NOT IS_ABSOLUTE ${FILE})
set(FILE "${CMAKE_CURRENT_SOURCE_DIR}/${FILE}")
endif()
get_filename_component(FILE "${FILE}" REALPATH)
sanitizer_check_compiler_flags("-fsanitize-blacklist=${FILE}"
"SanitizerBlacklist" "SanBlist")
endfunction()
function(add_sanitizers ...)
foreach (TARGET ${ARGV})
add_sanitize_address(${TARGET})
add_sanitize_thread(${TARGET})
add_sanitize_memory(${TARGET})
add_sanitize_undefined(${TARGET})
endforeach ()
endfunction(add_sanitizers)
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=thread"
)
# ThreadSanitizer is not compatible with MemorySanitizer.
if (SANITIZE_THREAD AND SANITIZE_MEMORY)
message(FATAL_ERROR "ThreadSanitizer is not compatible with "
"MemorySanitizer.")
endif ()
include(sanitize-helpers)
if (SANITIZE_THREAD)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for Linux systems only.")
set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for 64bit systems only.")
set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE)
else ()
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer"
"TSan")
endif ()
endif ()
function (add_sanitize_thread TARGET)
if (NOT SANITIZE_THREAD)
return()
endif ()
saitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan")
endfunction ()
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
option(SANITIZE_UNDEFINED
"Enable UndefinedBehaviorSanitizer for sanitized targets." Off)
set(FLAG_CANDIDATES
"-g -fsanitize=undefined"
)
include(sanitize-helpers)
if (SANITIZE_UNDEFINED)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}"
"UndefinedBehaviorSanitizer" "UBSan")
endif ()
function (add_sanitize_undefined TARGET)
if (NOT SANITIZE_UNDEFINED)
return()
endif ()
saitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan")
endfunction ()
#!/bin/sh
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
# This script is a wrapper for AddressSanitizer. In some special cases you need
# to preload AddressSanitizer to avoid error messages - e.g. if you're
# preloading another library to your application. At the moment this script will
# only do something, if we're running on a Linux platform. OSX might not be
# affected.
# Exit immediately, if platform is not Linux.
if [ "$(uname)" != "Linux" ]
then
exec $@
fi
# Get the used libasan of the application ($1). If a libasan was found, it will
# be prepended to LD_PRELOAD.
libasan=$(ldd $1 | grep libasan | sed "s/^[[:space:]]//" | cut -d' ' -f1)
if [ -n "$libasan" ]
then
if [ -n "$LD_PRELOAD" ]
then
export LD_PRELOAD="$libasan:$LD_PRELOAD"
else
export LD_PRELOAD="$libasan"
fi
fi
# Execute the application.
exec $@
// https://wagonhelm.github.io/articles/2018-03/detecting-cuda-capability-with-cmake
// Justin Francis
#include <stdio.h>
int main(int argc, char **argv){
cudaDeviceProp dP;
float min_cc = 5.0; // TODO: figure out what this should be.
int rc = cudaGetDeviceProperties(&dP, 0);
if(rc != cudaSuccess) {
cudaError_t error = cudaGetLastError();
printf("CUDA error: %s", cudaGetErrorString(error));
return rc; /* Failure */
}
if((dP.major+(dP.minor/10)) < min_cc) {
printf("Min Compute Capability of %2.1f required: %d.%d found\n Not Building CUDA Code",
min_cc, dP.major, dP.minor);
return 1; /* Failure */
} else {
printf("sm_%d%d", dP.major, dP.minor);
return 0; /* Success */
}
}
# The MIT License (MIT)
#
# Copyright (c)
# 2013 Matthew Arsenault
# 2015-2016 RWTH Aachen University, Federal Republic of Germany
#
# 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.
# Helper function to get the language of a source file.
function (sanitizer_lang_of_source FILE RETURN_VAR)
get_filename_component(FILE_EXT "${FILE}" EXT)
string(TOLOWER "${FILE_EXT}" FILE_EXT)
string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT)
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP)
if (NOT ${TEMP} EQUAL -1)
set(${RETURN_VAR} "${LANG}" PARENT_SCOPE)
return()
endif ()
endforeach()
set(${RETURN_VAR} "" PARENT_SCOPE)
endfunction ()
# Helper function to get compilers used by a target.
function (sanitizer_target_compilers TARGET RETURN_VAR)
# Check if all sources for target use the same compiler. If a target uses
# e.g. C and Fortran mixed and uses different compilers (e.g. clang and
# gfortran) this can trigger huge problems, because different compilers may
# use different implementations for sanitizers.
set(BUFFER "")
get_target_property(TSOURCES ${TARGET} SOURCES)
foreach (FILE ${TSOURCES})
# If expression was found, FILE is a generator-expression for an object
# library. Object libraries will be ignored.
string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE})
if ("${_file}" STREQUAL "")
sanitizer_lang_of_source(${FILE} LANG)
if (LANG)
list(APPEND BUFFER ${CMAKE_${LANG}_COMPILER_ID})
endif ()
endif ()
endforeach ()
list(REMOVE_DUPLICATES BUFFER)
set(${RETURN_VAR} "${BUFFER}" PARENT_SCOPE)
endfunction ()
# Helper function to check compiler flags for language compiler.
function (sanitizer_check_compiler_flag FLAG LANG VARIABLE)
if (${LANG} STREQUAL "C")
include(CheckCCompilerFlag)
check_c_compiler_flag("${FLAG}" ${VARIABLE})
elseif (${LANG} STREQUAL "CXX")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("${FLAG}" ${VARIABLE})
elseif (${LANG} STREQUAL "Fortran")
# CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible
# with older Cmake versions, we will check if this module is present
# before we use it. Otherwise we will define Fortran coverage support as
# not available.
include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED)
if (INCLUDED)
check_fortran_compiler_flag("${FLAG}" ${VARIABLE})
elseif (NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Performing Test ${VARIABLE}")
message(STATUS "Performing Test ${VARIABLE}"
" - Failed (Check not supported)")
endif ()
endif()
endfunction ()
# Helper function to test compiler flags.
function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Sanitizer flags are not dependend on language, but the used compiler.
# So instead of searching flags foreach language, search flags foreach
# compiler used.
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})
if (NOT DEFINED ${PREFIX}_${COMPILER}_FLAGS)
foreach (FLAG ${FLAG_CANDIDATES})
if(NOT CMAKE_REQUIRED_QUIET)
message(STATUS "Try ${COMPILER} ${NAME} flag = [${FLAG}]")
endif()
set(CMAKE_REQUIRED_FLAGS "${FLAG}")
unset(${PREFIX}_FLAG_DETECTED CACHE)
sanitizer_check_compiler_flag("${FLAG}" ${LANG}
${PREFIX}_FLAG_DETECTED)
if (${PREFIX}_FLAG_DETECTED)
# If compiler is a GNU compiler, search for static flag, if
# SANITIZE_LINK_STATIC is enabled.
if (SANITIZE_LINK_STATIC AND (${COMPILER} STREQUAL "GNU"))
string(TOLOWER ${PREFIX} PREFIX_lower)
sanitizer_check_compiler_flag(
"-static-lib${PREFIX_lower}" ${LANG}
${PREFIX}_STATIC_FLAG_DETECTED)
if (${PREFIX}_STATIC_FLAG_DETECTED)
set(FLAG "-static-lib${PREFIX_lower} ${FLAG}")
endif ()
endif ()
set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING
"${NAME} flags for ${COMPILER} compiler.")
mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
break()
endif ()
endforeach ()
if (NOT ${PREFIX}_FLAG_DETECTED)
set(${PREFIX}_${COMPILER}_FLAGS "" CACHE STRING
"${NAME} flags for ${COMPILER} compiler.")
mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
endif ()
endif ()
endforeach ()
endfunction ()
# Helper to assign sanitizer flags for TARGET.
function (saitizer_add_flags TARGET NAME PREFIX)
# Get list of compilers used by target and check, if target can be checked
# by sanitizer.
sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if (NUM_COMPILERS GREATER 1)
message(WARNING "${NAME} disabled for target ${TARGET} because it will "
"be compiled by different compilers.")
return()
elseif ((NUM_COMPILERS EQUAL 0) OR
("${${PREFIX}_${TARGET_COMPILER}_FLAGS}" STREQUAL ""))
message(WARNING "${NAME} disabled for target ${TARGET} because there is"
" no sanitizer available for target sources.")
return()
endif()
# Set compile- and link-flags for target.
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY COMPILE_FLAGS " ${SanBlist_${TARGET_COMPILER}_FLAGS}")
set_property(TARGET ${TARGET} APPEND_STRING
PROPERTY LINK_FLAGS " ${${PREFIX}_${TARGET_COMPILER}_FLAGS}")
endfunction ()
此差异已折叠。
enum
{
DLG_PBRT = 60000,
IDS_PBRT,
IDC_PBRT_START,
IDC_PBRT_LOG,
IDC_PBRT_EXE,
IDC_PBRT_MODE,
IDC_PBRT_MODE_EXPORT,
IDC_PBRT_MODE_EXPORT_AND_RENDER,
IDC_PBRT_MODE_RENDER,
IDC_PBRT_SAMPLES,
IDC_PBRT_ABORT,
IDC_BUTTON_GROUP,
IDC_PBRT_LOGLEVEL,
IDC_PBRT_LOGLEVEL_DEBUG,
IDC_PBRT_LOGLEVEL_INFO,
IDC_PBRT_LOGLEVEL_WARNING,
IDC_PBRT_LOGLEVEL_ERROR,
IDC_PBRT_INTENSITY,
IDS_PBRT_START = 60100,
IDS_PBRT_ABORT,
};
// C4D-DialogResource
DIALOG DLG_PBRT
{
NAME IDS_PBRT;
SCALE_V; SCALE_H;
GROUP
{
SCALE_V; SCALE_H;
COLUMNS 1;
GROUP
{
SCALE_H;
COLUMNS 2;
BORDERSIZE 4, 4, 4, 4;
STATICTEXT 0 { NAME IDS_PBRT_MODE; ALIGN_LEFT; }
COMBOBOX IDC_PBRT_MODE
{
//SIZE 100;
SCALE_H;
CHILDS
{
IDC_PBRT_MODE_EXPORT_AND_RENDER, IDS_PBRT_MODE_EXPORT_AND_RENDER;
IDC_PBRT_MODE_EXPORT, IDS_PBRT_MODE_EXPORT;
IDC_PBRT_MODE_RENDER, IDS_PBRT_MODE_RENDER;
}
}
STATICTEXT 0 { NAME IDS_PBRT_EXE; ALIGN_LEFT; }
FILENAME IDC_PBRT_EXE { SCALE_H; }
STATICTEXT 0 { NAME IDS_PBRT_SAMPLES; ALIGN_LEFT; }
EDITNUMBERARROWS IDC_PBRT_SAMPLES { SCALE_H; }
STATICTEXT 0 { NAME IDS_PBRT_INTENSITY; ALIGN_LEFT; }
EDITNUMBERARROWS IDC_PBRT_INTENSITY { SCALE_H; }
STATICTEXT 0 { NAME IDS_PBRT_LOGLEVEL; ALIGN_LEFT; }
COMBOBOX IDC_PBRT_LOGLEVEL
{
SCALE_H;
CHILDS
{
IDC_PBRT_LOGLEVEL_DEBUG, IDS_PBRT_LOGLEVEL_DEBUG;
IDC_PBRT_LOGLEVEL_INFO, IDS_PBRT_LOGLEVEL_INFO;
IDC_PBRT_LOGLEVEL_WARNING, IDS_PBRT_LOGLEVEL_WARNING;
IDC_PBRT_LOGLEVEL_ERROR, IDS_PBRT_LOGLEVEL_ERROR;
}
}
STATICTEXT 0 { }
GROUP IDC_BUTTON_GROUP
{
SCALE_H;
COLUMNS 1;
}
}
TREEVIEW IDC_PBRT_LOG { HAS_HEADER; ALTERNATE_BG; FIXED_LAYOUT; RESIZE_HEADER; SCALE_V; SCALE_H; BORDER; }
}
}
\ No newline at end of file
// C4D-StringResource
// Identifier Text
STRINGTABLE
{
IDS_PBRT_START "Start";
IDS_PBRT_ABORT "Abort";
}
// C4D-DialogResource
DIALOGSTRINGS DLG_PBRT
{
IDS_PBRT "Export to PBRT";
IDS_PBRT_EXE "Renderer";
IDS_PBRT_MODE "Mode";
IDS_PBRT_MODE_EXPORT "Export";
IDS_PBRT_MODE_EXPORT_AND_RENDER "Export and Render";
IDS_PBRT_MODE_RENDER "Render";
IDS_PBRT_SAMPLES "Samples";
IDS_PBRT_INTENSITY "Light Intensity";
IDS_PBRT_LOGLEVEL "Logging Level";
IDS_PBRT_LOGLEVEL_DEBUG "Debug";
IDS_PBRT_LOGLEVEL_INFO "Info";
IDS_PBRT_LOGLEVEL_WARNING "Warning";
IDS_PBRT_LOGLEVEL_ERROR "Error";
}
# PBRT Exporter for Cinema 4D
## Compatibility
This version of the PBRT Exporter for Cinema 4D has been tested with PBRT v3 and Cinema 4D R16. It will probably also work with earlier and later Cinema 4D versions. It will definitely not work with different versions than PBRT v3.
## Installation
To install the exporter, just copy the 'PBRT Export' folder into the plugins folder of your Cinema 4D Installation. It will then show up in the Plugins menu the next time you start Cinema 4D.
## Operation
Choosing 'Export to PBRT...' from the Plugins menu will open the export dialog. The export mode controls where PBRT files are written and whether the renderer is started. The 'Render' mode will export the scene to a temporary location, start pbrt and open the resulting image in the Picture Viewer once the rendering is done. 'Export' will ask you for a location the pbrt scene should be written to. 'Export and Render' will ask you where the scene should be written and will start a rendering. For 'Render' and 'Export and Render' is important to let the plugin know where your pbrt executable is located. This can be specified using the 'Renderer' input field. 'Samples' allows you to specify the number of Samples per Pixel to be used. 'Light Intensity' lets you globally scale the intensity of all exported light sources in the scene. During export, a detailed log is created. The 'Logging Level' lets you choose how much detail you want to see in the log window at the bottom of the export dialog.
By default, the 'directlighting' integrator is used. When a Global Illumination effect is added to the regular Cinema 4D render settings, the 'path' integrator is used instead.
## Supported Features
- Omni and Distant Light sources are exported
- The Physical Sky object will have appropriate light sources added and the background is baked into an environment texture and added as infinite light.
- All geometric objects that create polygons are exported.
- The plugin attempts to move basic material attributes (base color, specularity, bump). Furthermore it detects translucency setups using the Backlight shader and attempts to translate those.
## Copyright
This plugin has been created by Burak Kahraman and Timm Dapper of Laubwerk GmbH (www.laubwerk.com). It is distributed under the same license as the rest of the PBRT repository.
cmake_minimum_required (VERSION 3.12)
###########################################################################
# stb
set (STB_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/stb PARENT_SCOPE)
###########################################################################
# filesystem
set (FILESYSTEM_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/filesystem PARENT_SCOPE)
###########################################################################
# zlib
find_package (ZLIB)
if (NOT ZLIB_FOUND)
# Build zlib
set (ZLIB_BUILD_STATIC_LIBS ON CACHE BOOL " " FORCE)
set (ZLIB_BUILD_SHARED_LIBS OFF CACHE BOOL " " FORCE)
add_subdirectory (zlib)
set (ZLIB_LIBRARIES zlibstatic)
set (ZLIB_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/zlib ${CMAKE_CURRENT_BINARY_DIR}/zlib)
# try to make openexr happy about this...
set (ZLIB_LIBRARY zlibstatic)
set (ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlib ${CMAKE_CURRENT_BINARY_DIR}/zlib)
set (ZLIB_FOUND TRUE)
set_property (TARGET zlibstatic PROPERTY FOLDER "ext")
add_library (ZLIB::ZLIB ALIAS zlibstatic)
include_directories(${ZLIB_INCLUDE_DIRS}) # yuck, but so openexr/ptex can find zlib.h...
endif ()
set (ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS} PARENT_SCOPE)
set (ZLIB_LIBRARIES ${ZLIB_LIBARIES} PARENT_SCOPE)
###########################################################################
# OpenEXR
set (ILMBASE_NAMESPACE_VERSIONING OFF CACHE BOOL " " FORCE)
set (OPENEXR_NAMESPACE_VERSIONING OFF CACHE BOOL " " FORCE)
set (OPENEXR_BUILD_SHARED_LIBS OFF CACHE BOOL " " FORCE)
set (ILMBASE_BUILD_SHARED_LIBS OFF CACHE BOOL " " FORCE)
set (PYILMBASE_ENABLE OFF CACHE BOOL " " FORCE)
set (OPENEXR_BUILD_UTILS OFF CACHE BOOL " " FORCE)
add_subdirectory (openexr)
set_property (TARGET IexMath IlmThread Half
Iex Imath IlmImf HalfTest IexTest
IlmImfExamples IlmImfTest IlmImfUtil IlmImfUtilTest ImathTest
PROPERTY FOLDER "ext/OpenEXR")
set (OPENEXR_INCLUDE
${CMAKE_CURRENT_SOURCE_DIR}/openexr/IlmBase/Imath
${CMAKE_CURRENT_SOURCE_DIR}/openexr/IlmBase/Half
${CMAKE_CURRENT_SOURCE_DIR}/openexr/IlmBase/Iex
${CMAKE_CURRENT_SOURCE_DIR}/openexr/OpenEXR/IlmImf
${CMAKE_CURRENT_BINARY_DIR}/openexr/IlmBase/config
${CMAKE_CURRENT_BINARY_DIR}/openexr/OpenEXR/config
PARENT_SCOPE
)
if (WIN32)
set (OPENEXR_LIBS OpenEXR::IlmImf IlmBase::Imath IlmBase::Half ${ZLIB_LIBRARY} PARENT_SCOPE)
else ()
set (OPENEXR_LIBS OpenEXR::IlmImf IlmBase::Imath IlmBase::Half PARENT_SCOPE)
endif ()
###########################################################################
# ptex
set (PTEX_BUILD_SHARED_LIBS OFF CACHE BOOL " " FORCE)
set (CMAKE_MACOSX_RPATH 1)
if (WIN32)
add_definitions (/D PTEX_STATIC)
endif ()
add_subdirectory (ptex)
set_property (TARGET Ptex_static ptxinfo halftest ftest rtest wtest PROPERTY FOLDER "ext/ptex")
set (PTEX_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/ptex/src/ptex PARENT_SCOPE)
###########################################################################
# double-conversion
add_subdirectory (double-conversion)
set (DOUBLE_CONVERSION_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/double-conversion PARENT_SCOPE)
set_property (TARGET double-conversion cctest PROPERTY FOLDER "ext")
Subproject commit cc1f75a114aca8d2af69f73a5a959aecbab0e87a
Subproject commit f45da753728cde9b1c380b343e41c8b1ca6498d7
此差异已折叠。
此差异已折叠。
// Copyright 2006, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h>
#include <gtest/gtest.h>
#include <glog/logging.h>
GTEST_API_ int main(int argc, char **argv) {
google::InitGoogleLogging(argv[0]);
FLAGS_stderrthreshold = 1; // Warning and above.
printf("Running main() from gtest_main.cc\n");
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
此差异已折叠。
此差异已折叠。
Subproject commit 5cfb5dab6dfada731586b0281bdb15ee75e26782
Subproject commit 77b387406028d0dd6fea76d59d51e17aafe53358
此差异已折叠。
#if defined(_MSC_VER)
#ifndef NOMINMAX
#define NOMINMAX
#endif
#endif
#ifndef PBRT_EXT_RPLY_H
#define PBRT_EXT_RPLY_H
// ext/rply.h*
/* ----------------------------------------------------------------------
* RPly library, read/write PLY files
* Diego Nehab, IMPA
* http://www.impa.br/~diego/software/rply
*
* This library is distributed under the MIT License. See notice
* at the end of this file.
* ---------------------------------------------------------------------- */
#define RPLY_VERSION "RPly 1.1.3"
#define RPLY_COPYRIGHT "Copyright (C) 2003-2013 Diego Nehab"
#define RPLY_AUTHORS "Diego Nehab"
/* ----------------------------------------------------------------------
* Types
* ---------------------------------------------------------------------- */
/* structures are opaque */
typedef struct t_ply_ *p_ply;
typedef struct t_ply_element_ *p_ply_element;
typedef struct t_ply_property_ *p_ply_property;
typedef struct t_ply_argument_ *p_ply_argument;
/* ply format mode type */
typedef enum e_ply_storage_mode_ {
PLY_BIG_ENDIAN,
PLY_LITTLE_ENDIAN,
PLY_ASCII,
PLY_DEFAULT /* has to be the last in enum */
} e_ply_storage_mode; /* order matches ply_storage_mode_list */
/* ply data type */
typedef enum e_ply_type {
PLY_INT8,
PLY_UINT8,
PLY_INT16,
PLY_UINT16,
PLY_INT32,
PLY_UIN32,
PLY_FLOAT32,
PLY_FLOAT64,
PLY_CHAR,
PLY_UCHAR,
PLY_SHORT,
PLY_USHORT,
PLY_INT,
PLY_UINT,
PLY_FLOAT,
PLY_DOUBLE,
PLY_LIST /* has to be the last in enum */
} e_ply_type; /* order matches ply_type_list */
/* ----------------------------------------------------------------------
* Error callback prototype
*
* message: error message
* ply: handle returned by ply_open or ply_create
* ---------------------------------------------------------------------- */
typedef void (*p_ply_error_cb)(p_ply ply, const char *message);
/* ----------------------------------------------------------------------
* Gets user data from within an error callback
*
* ply: handle returned by ply_open or ply_create
* idata,pdata: contextual information set in ply_open or ply_create
* ---------------------------------------------------------------------- */
int ply_get_ply_user_data(p_ply ply, void **pdata, long *idata);
/* ----------------------------------------------------------------------
* Opens a PLY file for reading (fails if file is not a PLY file)
*
* name: file name
* error_cb: error callback function
* idata,pdata: contextual information available to users
*
* Returns 1 if successful, 0 otherwise
* ---------------------------------------------------------------------- */
p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata,
void *pdata);
/* ----------------------------------------------------------------------
* Reads and parses the header of a PLY file returned by ply_open
*
* ply: handle returned by ply_open
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_read_header(p_ply ply);
/* ----------------------------------------------------------------------
* Property reading callback prototype
*
* argument: parameters for property being processed when callback is called
*
* Returns 1 if should continue processing file, 0 if should abort.
* ---------------------------------------------------------------------- */
typedef int (*p_ply_read_cb)(p_ply_argument argument);
/* ----------------------------------------------------------------------
* Sets up callbacks for property reading after header was parsed
*
* ply: handle returned by ply_open
* element_name: element where property is
* property_name: property to associate element with
* read_cb: function to be called for each property value
* pdata/idata: user data that will be passed to callback
*
* Returns 0 if no element or no property in element, returns the
* number of element instances otherwise.
* ---------------------------------------------------------------------- */
long ply_set_read_cb(p_ply ply, const char *element_name,
const char *property_name, p_ply_read_cb read_cb,
void *pdata, long idata);
/* ----------------------------------------------------------------------
* Returns information about the element originating a callback
*
* argument: handle to argument
* element: receives a the element handle (if non-null)
* instance_index: receives the index of the current element instance
* (if non-null)
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_get_argument_element(p_ply_argument argument, p_ply_element *element,
long *instance_index);
/* ----------------------------------------------------------------------
* Returns information about the property originating a callback
*
* argument: handle to argument
* property: receives the property handle (if non-null)
* length: receives the number of values in this property (if non-null)
* value_index: receives the index of current property value (if non-null)
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_get_argument_property(p_ply_argument argument, p_ply_property *property,
long *length, long *value_index);
/* ----------------------------------------------------------------------
* Returns user data associated with callback
*
* pdata: receives a copy of user custom data pointer (if non-null)
* idata: receives a copy of user custom data integer (if non-null)
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_get_argument_user_data(p_ply_argument argument, void **pdata,
long *idata);
/* ----------------------------------------------------------------------
* Returns the value associated with a callback
*
* argument: handle to argument
*
* Returns the current data item
* ---------------------------------------------------------------------- */
double ply_get_argument_value(p_ply_argument argument);
/* ----------------------------------------------------------------------
* Reads all elements and properties calling the callbacks defined with
* calls to ply_set_read_cb
*
* ply: handle returned by ply_open
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_read(p_ply ply);
/* ----------------------------------------------------------------------
* Iterates over all elements by returning the next element.
* Call with NULL to return handle to first element.
*
* ply: handle returned by ply_open
* last: handle of last element returned (NULL for first element)
*
* Returns element if successfull or NULL if no more elements
* ---------------------------------------------------------------------- */
p_ply_element ply_get_next_element(p_ply ply, p_ply_element last);
/* ----------------------------------------------------------------------
* Iterates over all comments by returning the next comment.
* Call with NULL to return pointer to first comment.
*
* ply: handle returned by ply_open
* last: pointer to last comment returned (NULL for first comment)
*
* Returns comment if successfull or NULL if no more comments
* ---------------------------------------------------------------------- */
const char *ply_get_next_comment(p_ply ply, const char *last);
/* ----------------------------------------------------------------------
* Iterates over all obj_infos by returning the next obj_info.
* Call with NULL to return pointer to first obj_info.
*
* ply: handle returned by ply_open
* last: pointer to last obj_info returned (NULL for first obj_info)
*
* Returns obj_info if successfull or NULL if no more obj_infos
* ---------------------------------------------------------------------- */
const char *ply_get_next_obj_info(p_ply ply, const char *last);
/* ----------------------------------------------------------------------
* Returns information about an element
*
* element: element of interest
* name: receives a pointer to internal copy of element name (if non-null)
* ninstances: receives the number of instances of this element (if non-null)
*
* Returns 1 if successfull or 0 otherwise
* ---------------------------------------------------------------------- */
int ply_get_element_info(p_ply_element element, const char **name,
long *ninstances);
/* ----------------------------------------------------------------------
* Iterates over all properties by returning the next property.
* Call with NULL to return handle to first property.
*
* element: handle of element with the properties of interest
* last: handle of last property returned (NULL for first property)
*
* Returns element if successfull or NULL if no more properties
* ---------------------------------------------------------------------- */
p_ply_property ply_get_next_property(p_ply_element element,
p_ply_property last);
/* ----------------------------------------------------------------------
* Returns information about a property
*
* property: handle to property of interest
* name: receives a pointer to internal copy of property name (if non-null)
* type: receives the property type (if non-null)
* length_type: for list properties, receives the scalar type of
* the length field (if non-null)
* value_type: for list properties, receives the scalar type of the value
* fields (if non-null)
*
* Returns 1 if successfull or 0 otherwise
* ---------------------------------------------------------------------- */
int ply_get_property_info(p_ply_property property, const char **name,
e_ply_type *type, e_ply_type *length_type,
e_ply_type *value_type);
/* ----------------------------------------------------------------------
* Creates new PLY file
*
* name: file name
* storage_mode: file format mode
*
* Returns handle to PLY file if successfull, NULL otherwise
* ---------------------------------------------------------------------- */
p_ply ply_create(const char *name, e_ply_storage_mode storage_mode,
p_ply_error_cb error_cb, long idata, void *pdata);
/* ----------------------------------------------------------------------
* Adds a new element to the PLY file created by ply_create
*
* ply: handle returned by ply_create
* name: name of new element
* ninstances: number of element of this time in file
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_element(p_ply ply, const char *name, long ninstances);
/* ----------------------------------------------------------------------
* Adds a new property to the last element added by ply_add_element
*
* ply: handle returned by ply_create
* name: name of new property
* type: property type
* length_type: scalar type of length field of a list property
* value_type: scalar type of value fields of a list property
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_property(p_ply ply, const char *name, e_ply_type type,
e_ply_type length_type, e_ply_type value_type);
/* ----------------------------------------------------------------------
* Adds a new list property to the last element added by ply_add_element
*
* ply: handle returned by ply_create
* name: name of new property
* length_type: scalar type of length field of a list property
* value_type: scalar type of value fields of a list property
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_list_property(p_ply ply, const char *name, e_ply_type length_type,
e_ply_type value_type);
/* ----------------------------------------------------------------------
* Adds a new property to the last element added by ply_add_element
*
* ply: handle returned by ply_create
* name: name of new property
* type: property type
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type);
/* ----------------------------------------------------------------------
* Adds a new comment item
*
* ply: handle returned by ply_create
* comment: pointer to string with comment text
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_comment(p_ply ply, const char *comment);
/* ----------------------------------------------------------------------
* Adds a new obj_info item
*
* ply: handle returned by ply_create
* comment: pointer to string with obj_info data
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_add_obj_info(p_ply ply, const char *obj_info);
/* ----------------------------------------------------------------------
* Writes the PLY file header after all element and properties have been
* defined by calls to ply_add_element and ply_add_property
*
* ply: handle returned by ply_create
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_write_header(p_ply ply);
/* ----------------------------------------------------------------------
* Writes one property value, in the order they should be written to the
* file. For each element type, write all elements of that type in order.
* For each element, write all its properties in order. For scalar
* properties, just write the value. For list properties, write the length
* and then each of the values.
*
* ply: handle returned by ply_create
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_write(p_ply ply, double value);
/* ----------------------------------------------------------------------
* Closes a PLY file handle. Releases all memory used by handle
*
* ply: handle to be closed.
*
* Returns 1 if successfull, 0 otherwise
* ---------------------------------------------------------------------- */
int ply_close(p_ply ply);
/* ----------------------------------------------------------------------
* Copyright (C) 2003-2011 Diego Nehab. All rights reserved.
*
* 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.
* ---------------------------------------------------------------------- */
#endif // PBRT_EXT_RPLY_H
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Subproject commit b42009b3b9d4ca35bc703f5310eedc74f584be58
Subproject commit 54d591eabf9fe0e84c725638f8d5d8d202a093fa
BasedOnStyle: Google
AccessModifierOffset: -2
IndentCaseLabels: false
PointerBindsToType: false
Standard: Cpp11
IndentWidth: 4
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AlwaysBreakBeforeMultilineStrings: false
IncludeBlocks: Preserve
AllowAllConstructorInitializersOnNextLine: true
MaxEmptyLinesToKeep: 1
ColumnLimit: 90
// pbrt is Copyright(c) 1998-2020 Matt Pharr, Wenzel Jakob, and Greg Humphreys.
// The pbrt source code is licensed under the Apache License, Version 2.0.
// SPDX: Apache-2.0
#ifndef PBRT_BASE_SHAPE_H
#define PBRT_BASE_SHAPE_H
#include <pbrt/pbrt.h>
#include <pbrt/util/buffercache.h>
#include <pbrt/util/float.h>
#include <pbrt/util/taggedptr.h>
#include <pbrt/util/vecmath.h>
#include <string>
namespace pbrt {
// Shape Declarations
class Triangle;
class BilinearPatch;
class Curve;
class Sphere;
class Cylinder;
class Disk;
struct ShapeSample;
struct ShapeIntersection;
class ShapeSampleContext;
// ShapeHandle Definition
class ShapeHandle
: public TaggedPointer<Triangle, BilinearPatch, Curve, Sphere, Cylinder, Disk> {
public:
// Shape Interface
using TaggedPointer::TaggedPointer;
static pstd::vector<ShapeHandle> Create(const std::string &name,
const Transform *renderFromObject,
const Transform *objectFromRender,
bool reverseOrientation,
const ParameterDictionary &parameters,
const FileLoc *loc, Allocator alloc);
std::string ToString() const;
PBRT_CPU_GPU inline Bounds3f Bounds() const;
PBRT_CPU_GPU inline DirectionCone NormalBounds() const;
PBRT_CPU_GPU inline pstd::optional<ShapeIntersection> Intersect(
const Ray &ray, Float tMax = Infinity) const;
PBRT_CPU_GPU inline bool IntersectP(const Ray &ray, Float tMax = Infinity) const;
PBRT_CPU_GPU inline Float Area() const;
PBRT_CPU_GPU inline pstd::optional<ShapeSample> Sample(const Point2f &u) const;
PBRT_CPU_GPU inline Float PDF(const Interaction &) const;
PBRT_CPU_GPU inline pstd::optional<ShapeSample> Sample(const ShapeSampleContext &ctx,
const Point2f &u) const;
PBRT_CPU_GPU inline Float PDF(const ShapeSampleContext &ctx,
const Vector3f &wi) const;
private:
// ShapeHandle Private Members
friend class TriangleMesh;
friend class BilinearPatchMesh;
static BufferCache<int> *indexBufferCache;
static BufferCache<Point3f> *pBufferCache;
static BufferCache<Normal3f> *nBufferCache;
static BufferCache<Point2f> *uvBufferCache;
static BufferCache<Vector3f> *sBufferCache;
static BufferCache<int> *faceIndexBufferCache;
};
} // namespace pbrt
#endif // PBRT_BASE_SHAPE_H
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
// pbrt is Copyright(c) 1998-2020 Matt Pharr, Wenzel Jakob, and Greg Humphreys.
// The pbrt source code is licensed under the Apache License, Version 2.0.
// SPDX: Apache-2.0
#include <pbrt/bsdf.h>
#include <pbrt/util/spectrum.h>
namespace pbrt {
std::string BSDFSample::ToString() const {
return StringPrintf("[ BSDFSample f: %s wi: %s pdf: %s flags: %s ]", f, wi, pdf,
flags);
}
// BSDF Method Definitions
std::string BSDF::ToString() const {
return StringPrintf("[ BSDF eta: %f bxdf: %s shadingFrame: %s ng: %s ]", eta, bxdf,
shadingFrame, ng);
}
} // namespace pbrt
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册