Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/app/CMakeLists.txt23
-rw-r--r--intern/cycles/app/cycles_alembic.cpp426
-rw-r--r--intern/cycles/app/cycles_alembic.h36
-rw-r--r--intern/cycles/app/cycles_standalone.cpp54
-rw-r--r--intern/cycles/app/cycles_xml.cpp25
-rw-r--r--intern/cycles/blender/CMakeLists.txt2
-rw-r--r--intern/cycles/blender/addon/properties.py25
-rw-r--r--intern/cycles/blender/addon/ui.py22
-rw-r--r--intern/cycles/blender/blender_curves.cpp717
-rw-r--r--intern/cycles/blender/blender_mesh.cpp90
-rw-r--r--intern/cycles/blender/blender_object.cpp99
-rw-r--r--intern/cycles/blender/blender_session.cpp26
-rw-r--r--intern/cycles/blender/blender_shader.cpp29
-rw-r--r--intern/cycles/blender/blender_sync.cpp2
-rw-r--r--intern/cycles/blender/blender_sync.h21
-rw-r--r--intern/cycles/blender/blender_texture.cpp116
-rw-r--r--intern/cycles/blender/blender_texture.h31
-rw-r--r--intern/cycles/blender/blender_util.h42
-rw-r--r--intern/cycles/bvh/bvh.cpp34
-rw-r--r--intern/cycles/bvh/bvh_params.h4
-rw-r--r--intern/cycles/cmake/external_libs.cmake2
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h64
-rw-r--r--intern/cycles/kernel/kernel_types.h3
-rw-r--r--intern/cycles/kernel/svm/svm.h6
-rw-r--r--intern/cycles/kernel/svm/svm_types.h8
-rw-r--r--intern/cycles/kernel/svm/svm_voxel.h61
-rw-r--r--intern/cycles/render/mesh.cpp15
-rw-r--r--intern/cycles/render/mesh.h5
-rw-r--r--intern/cycles/render/nodes.cpp112
-rw-r--r--intern/cycles/render/nodes.h23
-rw-r--r--intern/cycles/render/scene.cpp6
-rw-r--r--intern/cycles/render/scene.h7
-rw-r--r--intern/smoke/extern/smoke_API.h3
-rw-r--r--intern/smoke/intern/WTURBULENCE.cpp100
-rw-r--r--intern/smoke/intern/WTURBULENCE.h7
-rw-r--r--intern/smoke/intern/smoke_API.cpp11
37 files changed, 1930 insertions, 328 deletions
diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt
index b000266cac2..b9a2abf1c9a 100644
--- a/intern/cycles/app/CMakeLists.txt
+++ b/intern/cycles/app/CMakeLists.txt
@@ -96,6 +96,12 @@ macro(cycles_target_link_libraries target)
${CMAKE_DL_LIBS}
${PLATFORM_LINKLIBS}
)
+ if(WITH_ALEMBIC)
+ target_link_libraries(
+ ${target}
+ ${ALEMBIC_LIBRARIES}
+ )
+ endif()
endmacro()
# Application build targets
@@ -106,6 +112,23 @@ if(WITH_CYCLES_STANDALONE)
cycles_xml.cpp
cycles_xml.h
)
+
+ if(WITH_ALEMBIC)
+ list(APPEND SRC
+ cycles_alembic.cpp
+ cycles_alembic.h
+ )
+ add_definitions(-DWITH_ALEMBIC)
+ include_directories(
+ SYSTEM
+ ${ALEMBIC_INCLUDE_DIRS}
+ )
+ endif()
+
+ if(WITH_HDF5)
+ add_definitions(-DWITH_HDF5)
+ endif()
+
add_executable(cycles ${SRC})
cycles_target_link_libraries(cycles)
diff --git a/intern/cycles/app/cycles_alembic.cpp b/intern/cycles/app/cycles_alembic.cpp
new file mode 100644
index 00000000000..3a1e6a6bcaa
--- /dev/null
+++ b/intern/cycles/app/cycles_alembic.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright 2015 Blender Foundation
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+
+#include <sstream>
+#include <algorithm>
+#include <iterator>
+
+#include <Alembic/AbcCoreOgawa/ReadWrite.h>
+#ifdef WITH_HDF5
+#include <Alembic/AbcCoreHDF5/ReadWrite.h>
+#endif
+#include <Alembic/Abc/IArchive.h>
+#include <Alembic/Abc/IObject.h>
+#include <Alembic/Abc/ISampleSelector.h>
+#include <Alembic/Abc/ICompoundProperty.h>
+#include <Alembic/Abc/IScalarProperty.h>
+#include <Alembic/Abc/IArrayProperty.h>
+#include <Alembic/Abc/ArchiveInfo.h>
+#include <Alembic/AbcGeom/IPolyMesh.h>
+
+#include "camera.h"
+#include "film.h"
+#include "graph.h"
+#include "integrator.h"
+#include "light.h"
+#include "mesh.h"
+#include "nodes.h"
+#include "object.h"
+#include "shader.h"
+#include "scene.h"
+
+#include "subd_mesh.h"
+#include "subd_patch.h"
+#include "subd_split.h"
+
+#include "util_debug.h"
+#include "util_foreach.h"
+#include "util_path.h"
+#include "util_transform.h"
+#include "util_xml.h"
+
+#include "cycles_alembic.h"
+
+CCL_NAMESPACE_BEGIN
+
+using namespace Alembic;
+using namespace Abc;
+using namespace AbcGeom;
+
+#define ABC_SAFE_CALL_BEGIN \
+ try {
+
+#define ABC_SAFE_CALL_END \
+ } \
+ catch (Alembic::Util::Exception e) { \
+ printf("%s", e.what()); \
+ }
+
+
+/* File */
+
+static const std::string g_sep(";");
+
+static void visitProperties(std::stringstream &ss, ICompoundProperty, std::string &);
+
+template <class PROP>
+static void visitSimpleArrayProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
+{
+ std::string ptype = "ArrayProperty ";
+ size_t asize = 0;
+
+ AbcA::ArraySamplePtr samp;
+ index_t maxSamples = iProp.getNumSamples();
+ for (index_t i = 0 ; i < maxSamples; ++i) {
+ iProp.get(samp, ISampleSelector( i ));
+ asize = samp->size();
+ };
+
+ std::string mdstring = "interpretation=";
+ mdstring += iProp.getMetaData().get("interpretation");
+
+ std::stringstream dtype;
+ dtype << "datatype=";
+ dtype << iProp.getDataType();
+
+ std::stringstream asizestr;
+ asizestr << ";arraysize=";
+ asizestr << asize;
+
+ mdstring += g_sep;
+
+ mdstring += dtype.str();
+
+ mdstring += asizestr.str();
+
+ ss << iIndent << " " << ptype << "name=" << iProp.getName()
+ << g_sep << mdstring << g_sep << "numsamps="
+ << iProp.getNumSamples() << std::endl;
+}
+
+template <class PROP>
+static void visitSimpleScalarProperty(std::stringstream &ss, PROP iProp, const std::string &iIndent)
+{
+ std::string ptype = "ScalarProperty ";
+ size_t asize = 0;
+
+ const AbcA::DataType &dt = iProp.getDataType();
+ const Alembic::Util ::uint8_t extent = dt.getExtent();
+ Alembic::Util::Dimensions dims(extent);
+ AbcA::ArraySamplePtr samp = AbcA::AllocateArraySample( dt, dims );
+ index_t maxSamples = iProp.getNumSamples();
+ for (index_t i = 0 ; i < maxSamples; ++i) {
+ iProp.get(const_cast<void*>(samp->getData()), ISampleSelector( i ));
+ asize = samp->size();
+ };
+
+ std::string mdstring = "interpretation=";
+ mdstring += iProp.getMetaData().get("interpretation");
+
+ std::stringstream dtype;
+ dtype << "datatype=";
+ dtype << dt;
+
+ std::stringstream asizestr;
+ asizestr << ";arraysize=";
+ asizestr << asize;
+
+ mdstring += g_sep;
+
+ mdstring += dtype.str();
+
+ mdstring += asizestr.str();
+
+ ss << iIndent << " " << ptype << "name=" << iProp.getName()
+ << g_sep << mdstring << g_sep << "numsamps="
+ << iProp.getNumSamples() << std::endl;
+}
+
+static void visitCompoundProperty(std::stringstream &ss, ICompoundProperty iProp, std::string &ioIndent)
+{
+ std::string oldIndent = ioIndent;
+ ioIndent += " ";
+
+ std::string interp = "schema=";
+ interp += iProp.getMetaData().get("schema");
+
+ ss << ioIndent << "CompoundProperty " << "name=" << iProp.getName()
+ << g_sep << interp << std::endl;
+
+ visitProperties(ss, iProp, ioIndent);
+
+ ioIndent = oldIndent;
+}
+
+static void visitProperties(std::stringstream &ss, ICompoundProperty iParent, std::string &ioIndent )
+{
+ std::string oldIndent = ioIndent;
+ for (size_t i = 0 ; i < iParent.getNumProperties() ; i++) {
+ PropertyHeader header = iParent.getPropertyHeader(i);
+
+ if (header.isCompound()) {
+ visitCompoundProperty(ss, ICompoundProperty(iParent, header.getName()), ioIndent);
+ }
+ else if (header.isScalar()) {
+ visitSimpleScalarProperty(ss, IScalarProperty(iParent, header.getName()), ioIndent);
+ }
+ else {
+ assert(header.isArray());
+ visitSimpleArrayProperty(ss, IArrayProperty(iParent, header.getName()), ioIndent);
+ }
+ }
+
+ ioIndent = oldIndent;
+}
+
+static void visitObject(std::stringstream &ss, IObject iObj, std::string iIndent, AbcArchiveInfoLevel info_level)
+{
+ // Object has a name, a full name, some meta data,
+ // and then it has a compound property full of properties.
+ std::string path = iObj.getFullName();
+
+ if (iObj.isInstanceRoot()) {
+ if (path != "/") {
+ ss << "Object " << "name=" << path
+ << " [Instance " << iObj.instanceSourcePath() << "]"
+ << std::endl;
+ }
+ }
+ else if (iObj.isInstanceDescendant()) {
+ /* skip non-root instances to avoid repetition */
+ return;
+ }
+ else {
+ if (path != "/") {
+ ss << "Object " << "name=" << path << std::endl;
+ }
+
+ if (info_level >= ABC_INFO_PROPERTIES) {
+ // Get the properties.
+ ICompoundProperty props = iObj.getProperties();
+ visitProperties(ss, props, iIndent);
+ }
+
+ // now the child objects
+ for (size_t i = 0 ; i < iObj.getNumChildren() ; i++) {
+ visitObject(ss, IObject(iObj, iObj.getChildHeader(i).getName()), iIndent, info_level);
+ }
+ }
+}
+
+static std::string abc_archive_info(IArchive &archive, AbcArchiveInfoLevel info_level)
+{
+ std::stringstream ss;
+
+ ss << "Alembic Archive Info for "
+ << Alembic::AbcCoreAbstract::GetLibraryVersion()
+ << std::endl;;
+
+ std::string appName;
+ std::string libraryVersionString;
+ Alembic::Util::uint32_t libraryVersion;
+ std::string whenWritten;
+ std::string userDescription;
+ GetArchiveInfo(archive,
+ appName,
+ libraryVersionString,
+ libraryVersion,
+ whenWritten,
+ userDescription);
+
+ if (appName != "") {
+ ss << " file written by: " << appName << std::endl;
+ ss << " using Alembic : " << libraryVersionString << std::endl;
+ ss << " written on : " << whenWritten << std::endl;
+ ss << " user description : " << userDescription << std::endl;
+ ss << std::endl;
+ }
+ else {
+// ss << argv[1] << std::endl;
+ ss << " (file doesn't have any ArchiveInfo)"
+ << std::endl;
+ ss << std::endl;
+ }
+
+ if (info_level >= ABC_INFO_OBJECTS)
+ visitObject(ss, archive.getTop(), "", info_level);
+
+ return ss.str();
+}
+
+/* ========================================================================= */
+
+struct AbcReadState {
+ Scene *scene; /* scene pointer */
+ float time;
+ Transform tfm; /* current transform state */
+ bool smooth; /* smooth normal state */
+ int shader; /* current shader */
+ string base; /* base path to current file*/
+ float dicing_rate; /* current dicing rate */
+ Mesh::DisplacementMethod displacement_method;
+};
+
+static ISampleSelector get_sample_selector(const AbcReadState &state)
+{
+ return ISampleSelector(state.time, ISampleSelector::kFloorIndex);
+}
+
+static Mesh *add_mesh(Scene *scene, const Transform& tfm)
+{
+ /* create mesh */
+ Mesh *mesh = new Mesh();
+ scene->meshes.push_back(mesh);
+
+ /* create object*/
+ Object *object = new Object();
+ object->mesh = mesh;
+ object->tfm = tfm;
+ scene->objects.push_back(object);
+
+ return mesh;
+}
+
+static void read_mesh(const AbcReadState &state, IPolyMesh object)
+{
+ /* add mesh */
+ Mesh *mesh = add_mesh(state.scene, state.tfm);
+ mesh->used_shaders.push_back(state.shader);
+
+ /* read state */
+ int shader = state.shader;
+ bool smooth = state.smooth;
+
+ mesh->displacement_method = state.displacement_method;
+
+ ISampleSelector ss = get_sample_selector(state);
+ IPolyMeshSchema schema = object.getSchema();
+
+ IPolyMeshSchema::Sample sample;
+ schema.get(sample, ss);
+
+ int totverts = sample.getPositions()->size();
+ int totfaces = sample.getFaceCounts()->size();
+ const V3f *P = sample.getPositions()->get();
+ const int32_t *verts = sample.getFaceIndices()->get();
+ const int32_t *nverts = sample.getFaceCounts()->get();
+
+ /* create vertices */
+ mesh->verts.reserve(totverts);
+ for(int i = 0; i < totverts; i++) {
+ mesh->verts.push_back(make_float3(P[i].x, P[i].y, P[i].z));
+ }
+
+ /* create triangles */
+ int index_offset = 0;
+
+ for(int i = 0; i < totfaces; i++) {
+ int n = nverts[i];
+ /* XXX TODO only supports tris and quads atm,
+ * need a proper tessellation algorithm in cycles.
+ */
+ if (n > 4) {
+ printf("%d-sided face found, only triangles and quads are supported currently", n);
+ n = 4;
+ }
+
+ for(int j = 0; j < n-2; j++) {
+ int v0 = verts[index_offset];
+ int v1 = verts[index_offset + j + 1];
+ int v2 = verts[index_offset + j + 2];
+
+ assert(v0 < (int)totverts);
+ assert(v1 < (int)totverts);
+ assert(v2 < (int)totverts);
+
+ mesh->add_triangle(v0, v1, v2, shader, smooth);
+ }
+
+ index_offset += n;
+ }
+
+ /* temporary for test compatibility */
+ mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
+}
+
+static void read_object(const AbcReadState &state, IObject object)
+{
+ for (int i = 0; i < object.getNumChildren(); ++i) {
+ IObject child = object.getChild(i);
+ const MetaData &metadata = child.getMetaData();
+
+ if (IPolyMeshSchema::matches(metadata)) {
+ read_mesh(state, IPolyMesh(child, kWrapExisting));
+ }
+ else {
+ read_object(state, child);
+ }
+ }
+}
+
+static void read_archive(Scene *scene, IArchive archive, const char *filepath)
+{
+ AbcReadState state;
+
+ state.scene = scene;
+ state.time = 0.0f; // TODO
+ state.tfm = transform_identity();
+ state.shader = scene->default_surface;
+ state.smooth = false;
+ state.dicing_rate = 0.1f;
+ state.base = path_dirname(filepath);
+
+ read_object(state, archive.getTop());
+
+ scene->params.bvh_type = SceneParams::BVH_STATIC;
+}
+
+void abc_read_ogawa_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level)
+{
+ IArchive archive;
+ ABC_SAFE_CALL_BEGIN
+ archive = IArchive(AbcCoreOgawa::ReadArchive(), filepath, ErrorHandler::kThrowPolicy);
+ ABC_SAFE_CALL_END
+
+ if (archive) {
+ if (info_level >= ABC_INFO_BASIC)
+ printf("%s", abc_archive_info(archive, info_level).c_str());
+
+ read_archive(scene, archive, filepath);
+ }
+}
+
+void abc_read_hdf5_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level)
+{
+#ifdef WITH_HDF5
+ IArchive archive;
+ ABC_SAFE_CALL_BEGIN
+ archive = IArchive(AbcCoreHDF5::ReadArchive(), filepath, ErrorHandler::kThrowPolicy);
+ ABC_SAFE_CALL_END
+
+ if (archive) {
+ if (info_level >= ABC_INFO_BASIC)
+ printf("%s", abc_archive_info(archive, info_level).c_str());
+
+ read_archive(scene, archive, filepath);
+ }
+#endif
+}
+
+CCL_NAMESPACE_END
+
diff --git a/intern/cycles/app/cycles_alembic.h b/intern/cycles/app/cycles_alembic.h
new file mode 100644
index 00000000000..df17f8b8fbe
--- /dev/null
+++ b/intern/cycles/app/cycles_alembic.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Blender Foundation
+ *
+ * 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.
+ */
+
+#ifndef __CYCLES_ALEMBIC_H__
+#define __CYCLES_ALEMBIC_H__
+
+CCL_NAMESPACE_BEGIN
+
+class Scene;
+
+enum AbcArchiveInfoLevel {
+ ABC_INFO_NONE = 0,
+ ABC_INFO_BASIC,
+ ABC_INFO_OBJECTS,
+ ABC_INFO_PROPERTIES,
+};
+
+void abc_read_ogawa_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level = ABC_INFO_NONE);
+void abc_read_hdf5_file(Scene *scene, const char *filepath, AbcArchiveInfoLevel info_level = ABC_INFO_NONE);
+
+CCL_NAMESPACE_END
+
+#endif /* __CYCLES_XML_H__ */
diff --git a/intern/cycles/app/cycles_standalone.cpp b/intern/cycles/app/cycles_standalone.cpp
index 19986912375..8f39c5126f5 100644
--- a/intern/cycles/app/cycles_standalone.cpp
+++ b/intern/cycles/app/cycles_standalone.cpp
@@ -37,13 +37,23 @@
#endif
#include "cycles_xml.h"
+#ifdef WITH_ALEMBIC
+#include "cycles_alembic.h"
+#endif
CCL_NAMESPACE_BEGIN
+enum FileType {
+ FILETYPE_XML = 0,
+ FILETYPE_ABC_HDF5,
+ FILETYPE_ABC_OGAWA,
+};
+
struct Options {
Session *session;
Scene *scene;
string filepath;
+ FileType filetype;
int width, height;
SceneParams scene_params;
SessionParams session_params;
@@ -120,8 +130,22 @@ static void scene_init()
{
options.scene = new Scene(options.scene_params, options.session_params.device);
- /* Read XML */
- xml_read_file(options.scene, options.filepath.c_str());
+ /* Read file */
+ switch (options.filetype) {
+ case FILETYPE_XML:
+ xml_read_file(options.scene, options.filepath.c_str());
+ break;
+#ifdef WITH_ALEMBIC
+ case FILETYPE_ABC_OGAWA:
+ abc_read_ogawa_file(options.scene, options.filepath.c_str());
+ break;
+ case FILETYPE_ABC_HDF5:
+ abc_read_hdf5_file(options.scene, options.filepath.c_str());
+ break;
+#endif
+ default:
+ return;
+ }
/* Camera width/height override? */
if(!(options.width == 0 || options.height == 0)) {
@@ -335,6 +359,16 @@ static void options_parse(int argc, const char **argv)
/* shading system */
string ssname = "svm";
+ /* input file type */
+ string filetypes = "auto, xml";
+#ifdef WITH_ALEMBIC
+ filetypes += ", alembic_ogawa";
+#ifdef WITH_HDF5
+ filetypes += ", alembic_hdf5";
+#endif
+#endif
+ string filetype = "auto";
+
/* parse options */
ArgParse ap;
bool help = false, debug = false;
@@ -350,6 +384,7 @@ static void options_parse(int argc, const char **argv)
"--quiet", &options.quiet, "In background mode, don't print progress messages",
"--samples %d", &options.session_params.samples, "Number of samples to render",
"--output %s", &options.session_params.output_path, "File path to write output image",
+ "--filetype %s", &filetype, ("File type: " + filetypes).c_str(),
"--threads %d", &options.session_params.threads, "CPU Rendering Threads",
"--width %d", &options.width, "Window width in pixel",
"--height %d", &options.height, "Window height in pixel",
@@ -395,6 +430,21 @@ static void options_parse(int argc, const char **argv)
else if(ssname == "svm")
options.scene_params.shadingsystem = SHADINGSYSTEM_SVM;
+ if(filetype == "auto") {
+ string extension = options.filepath.substr(options.filepath.find_last_of(".") + 1);
+
+ if (extension == "xml")
+ options.filetype = FILETYPE_XML;
+ else if (extension == "abc")
+ options.filetype = FILETYPE_ABC_OGAWA;
+ }
+ else if(filetype == "xml")
+ options.filetype = FILETYPE_XML;
+ else if(filetype == "alembic_ogawa")
+ options.filetype = FILETYPE_ABC_OGAWA;
+ else if(filetype == "alembic_hdf5")
+ options.filetype = FILETYPE_ABC_HDF5;
+
#ifndef WITH_CYCLES_STANDALONE_GUI
options.session_params.background = true;
#endif
diff --git a/intern/cycles/app/cycles_xml.cpp b/intern/cycles/app/cycles_xml.cpp
index 53262b93dd0..06fc6a33953 100644
--- a/intern/cycles/app/cycles_xml.cpp
+++ b/intern/cycles/app/cycles_xml.cpp
@@ -42,6 +42,9 @@
#include "util_xml.h"
#include "cycles_xml.h"
+#ifdef WITH_ALEMBIC
+#include "cycles_alembic.h"
+#endif
CCL_NAMESPACE_BEGIN
@@ -1130,6 +1133,25 @@ static void xml_read_state(XMLReadState& state, pugi::xml_node node)
state.displacement_method = Mesh::DISPLACE_BOTH;
}
+/* Alembic */
+static void xml_read_alembic(const XMLReadState& state, pugi::xml_node node)
+{
+#ifdef WITH_ALEMBIC
+ string filepath;
+
+ if(xml_read_string(&filepath, node, "file")) {
+ filepath = path_join(state.base, filepath);
+
+ if(xml_equal_string(node, "type", "hdf5"))
+ abc_read_hdf5_file(state.scene, filepath.c_str(), ABC_INFO_BASIC);
+ else if(xml_equal_string(node, "type", "ogawa"))
+ abc_read_ogawa_file(state.scene, filepath.c_str(), ABC_INFO_BASIC);
+ else
+ abc_read_ogawa_file(state.scene, filepath.c_str(), ABC_INFO_BASIC); /* default */
+ }
+#endif
+}
+
/* Scene */
static void xml_read_include(const XMLReadState& state, const string& src);
@@ -1179,6 +1201,9 @@ static void xml_read_scene(const XMLReadState& state, pugi::xml_node scene_node)
if(xml_read_string(&src, node, "src"))
xml_read_include(state, src);
}
+ else if(string_iequals(node.name(), "alembic")) {
+ xml_read_alembic(state, node);
+ }
else
fprintf(stderr, "Unknown node \"%s\".\n", node.name());
}
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt
index fff9ed20bba..c6a2b919486 100644
--- a/intern/cycles/blender/CMakeLists.txt
+++ b/intern/cycles/blender/CMakeLists.txt
@@ -31,10 +31,12 @@ set(SRC
blender_session.cpp
blender_shader.cpp
blender_sync.cpp
+ blender_texture.cpp
CCL_api.h
blender_sync.h
blender_session.h
+ blender_texture.h
blender_util.h
)
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index 16a807b3af5..0daf6784798 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -463,6 +463,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
description="Use BVH spatial splits: longer builder time, faster render",
default=False,
)
+ cls.debug_use_triangle_storage = BoolProperty(
+ name="Use Triangle Storage",
+ description="use special storage with aligned triangle coordinates for faster "
+ "intesection check in expense of higher memory usage",
+ default=True,
+ )
cls.use_cache = BoolProperty(
name="Cache BVH",
description="Cache last built BVH to disk for faster re-render if no geometry changed",
@@ -511,6 +517,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
),
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow objects to be culled based on the camera frustum",
+ default=False,
+ )
+
+ cls.camera_cull_margin = FloatProperty(
+ name="Camera Cull Margin",
+ description="Margin for the camera space culling",
+ default=0.1,
+ min=0.0, max=5.0
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Scene.cycles
@@ -890,6 +909,12 @@ class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
default=1,
)
+ cls.use_camera_cull = BoolProperty(
+ name="Use Camera Cull",
+ description="Allow this object and it's duplicators to be culled by camera space culling",
+ default=False,
+ )
+
@classmethod
def unregister(cls):
del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 7fa71397271..fb6a3d76dec 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -322,6 +322,11 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
subsub.enabled = not rd.use_border
subsub.prop(rd, "use_save_buffers")
+ sub.prop(cscene, "use_camera_cull")
+ subsub = col.column()
+ subsub.active = cscene.use_camera_cull
+ subsub.prop(cscene, "camera_cull_margin")
+
col = split.column(align=True)
col.label(text="Viewport:")
@@ -339,6 +344,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
col.label(text="Acceleration structure:")
col.prop(cscene, "debug_use_spatial_splits")
+ col.prop(cscene, "debug_use_triangle_storage")
class CyclesRender_PT_layer_options(CyclesButtonsPanel, Panel):
@@ -678,8 +684,8 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
sub.prop(cob, "motion_steps", text="Steps")
-class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
- bl_label = "Ray Visibility"
+class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
+ bl_label = "Cycles Settings"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@@ -694,8 +700,10 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
layout = self.layout
ob = context.object
+ cob = ob.cycles
visibility = ob.cycles_visibility
+ layout.label(text="Ray Visibility:")
flow = layout.column_flow()
flow.prop(visibility, "camera")
@@ -707,6 +715,9 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
if ob.type != 'LAMP':
flow.prop(visibility, "shadow")
+ layout.label(text="Performance:")
+ layout.prop(cob, "use_camera_cull")
+
class CYCLES_OT_use_shading_nodes(Operator):
"""Enable nodes on a material, world or lamp"""
@@ -1216,7 +1227,8 @@ class CyclesTexture_PT_mapping(CyclesButtonsPanel, Panel):
@classmethod
def poll(cls, context):
node = context.texture_node
- return node and CyclesButtonsPanel.poll(context)
+ # TODO(sergey): perform a faster/nicer check?
+ return node and hasattr(node, 'texture_mapping') and CyclesButtonsPanel.poll(context)
def draw(self, context):
layout = self.layout
@@ -1440,7 +1452,8 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- rd = context.scene.render
+ scene = context.scene
+ rd = scene.render
layout.active = rd.use_simplify
split = layout.split()
@@ -1520,6 +1533,7 @@ def get_panels():
"DATA_PT_curve_texture_space",
"DATA_PT_mball_texture_space",
"DATA_PT_vertex_groups",
+ "DATA_PT_face_maps",
"DATA_PT_shape_keys",
"DATA_PT_uv_texture",
"DATA_PT_vertex_colors",
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp
index dba801fc4df..4ed0b910f35 100644
--- a/intern/cycles/blender/blender_curves.cpp
+++ b/intern/cycles/blender/blender_curves.cpp
@@ -37,15 +37,14 @@ void curveinterp_v3_v3v3v3v3(float3 *p, float3 *v1, float3 *v2, float3 *v3, floa
void interp_weights(float t, float data[4]);
float shaperadius(float shape, float root, float tip, float time);
void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyloc, float *time, ParticleCurveData *CData);
-bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num);
-bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num);
-bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background);
void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData);
void ExportCurveTrianglePlanes(Mesh *mesh, ParticleCurveData *CData,
float3 RotCam, bool is_ortho);
void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution);
void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata);
+void ExportCurveUV(Mesh *mesh, ParticleCurveData *CData, ustring name, bool active_render, int primitive, int vert_offset, int resol);
void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata);
+void ExportCurveVcol(Mesh *mesh, ParticleCurveData *CData, ustring name, int primitive, int vert_offset, int resol);
ParticleCurveData::ParticleCurveData()
{
@@ -119,206 +118,330 @@ void InterpolateKeySegments(int seg, int segno, int key, int curve, float3 *keyl
curveinterp_v3_v3v3v3v3(keyloc, &ckey_loc1, &ckey_loc2, &ckey_loc3, &ckey_loc4, t);
}
-bool ObtainCacheParticleData(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
+static void ObtainCacheParticleData(Mesh *mesh, BL::Object b_ob, BL::ParticleSystem b_psys, const Transform &itfm,
+ ParticleCurveData *CData, bool background)
{
- int curvenum = 0;
- int keyno = 0;
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+ int draw_step = background ? b_part.render_step() : b_part.draw_step();
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if(b_part.child_type() == 0)
+ totcurves += totparts;
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
+ if(totcurves == 0)
+ return;
- Transform tfm = get_transform(b_ob->matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
+ int ren_step = (1 << draw_step) + 1;
+ if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
+ ren_step += b_part.kink_extra_steps();
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+ int keyno = CData->curvekey_co.size();
+ int curvenum = CData->curve_keynum.size();
+
+ CData->psys_firstcurve.push_back(curvenum);
+ CData->psys_curvenum.push_back(totcurves);
+ CData->psys_shader.push_back(shader);
+
+ float radius = get_float(cpsys, "radius_scale") * 0.5f;
+
+ CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+ int pa_no = 0;
+ if(!(b_part.child_type() == 0))
+ pa_no = totparts;
+
+ int num_add = (totparts+totchild - pa_no);
+ CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
+ CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
+ CData->curve_length.reserve(CData->curve_length.size() + num_add);
+ CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
+ CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
+
+ for(; pa_no < totparts+totchild; pa_no++) {
+ int keynum = 0;
+ CData->curve_firstkey.push_back(keyno);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for(int step_no = 0; step_no < ren_step; step_no++) {
+ float nco[3];
+ b_psys.co_hair(b_ob, pa_no, step_no, nco);
+ float3 cKey = make_float3(nco[0], nco[1], nco[2]);
+ cKey = transform_point(&itfm, cKey);
+ if(step_no > 0) {
+ float step_length = len(cKey - pcKey);
+ if(step_length == 0.0f)
+ continue;
+ curve_length += step_length;
+ }
+ CData->curvekey_co.push_back(cKey);
+ CData->curvekey_time.push_back(curve_length);
+ pcKey = cKey;
+ keynum++;
+ }
+ keyno += keynum;
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
- int shader = mesh->used_shaders[mi];
- int draw_step = background ? b_part.render_step() : b_part.draw_step();
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0)
- totcurves += totparts;
+ CData->curve_keynum.push_back(keynum);
+ CData->curve_length.push_back(curve_length);
+ curvenum++;
+ }
+}
- if(totcurves == 0)
- continue;
+static void ObtainCacheParticleUV(Mesh * /*mesh*/, BL::Object /*b_ob*/, BL::Mesh b_mesh, BL::ParticleSystem b_psys, BL::ParticleSystemModifier b_psmd,
+ ParticleCurveData *CData, bool background, int uv_num)
+{
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if(b_part.child_type() == 0)
+ totcurves += totparts;
- int ren_step = (1 << draw_step) + 1;
- if(b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
- ren_step += b_part.kink_extra_steps();
+ if(totcurves == 0)
+ return;
- PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+ int pa_no = 0;
+ if(!(b_part.child_type() == 0))
+ pa_no = totparts;
- CData->psys_firstcurve.push_back(curvenum);
- CData->psys_curvenum.push_back(totcurves);
- CData->psys_shader.push_back(shader);
+ int num_add = (totparts+totchild - pa_no);
+ CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
- float radius = get_float(cpsys, "radius_scale") * 0.5f;
-
- CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
- CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
- CData->psys_shape.push_back(get_float(cpsys, "shape"));
- CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0))
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_firstkey.reserve(CData->curve_firstkey.size() + num_add);
- CData->curve_keynum.reserve(CData->curve_keynum.size() + num_add);
- CData->curve_length.reserve(CData->curve_length.size() + num_add);
- CData->curvekey_co.reserve(CData->curvekey_co.size() + num_add*ren_step);
- CData->curvekey_time.reserve(CData->curvekey_time.size() + num_add*ren_step);
-
- for(; pa_no < totparts+totchild; pa_no++) {
- int keynum = 0;
- CData->curve_firstkey.push_back(keyno);
-
- float curve_length = 0.0f;
- float3 pcKey;
- for(int step_no = 0; step_no < ren_step; step_no++) {
- float nco[3];
- b_psys.co_hair(*b_ob, pa_no, step_no, nco);
- float3 cKey = make_float3(nco[0], nco[1], nco[2]);
- cKey = transform_point(&itfm, cKey);
- if(step_no > 0) {
- float step_length = len(cKey - pcKey);
- if(step_length == 0.0f)
- continue;
- curve_length += step_length;
- }
- CData->curvekey_co.push_back(cKey);
- CData->curvekey_time.push_back(curve_length);
- pcKey = cKey;
- keynum++;
- }
- keyno += keynum;
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+ /* Add UVs */
+ BL::Mesh::tessface_uv_textures_iterator l;
+ b_mesh.tessface_uv_textures.begin(l);
- CData->curve_keynum.push_back(keynum);
- CData->curve_length.push_back(curve_length);
- curvenum++;
- }
- }
- }
- }
+ float3 uv = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh.tessface_uv_textures.length())
+ b_psys.uv_on_emitter(b_psmd, *b_pa, pa_no, uv_num, &uv.x);
+ CData->curve_uv.push_back(uv);
- return true;
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+ }
}
-bool ObtainCacheParticleUV(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num)
+static void ObtainCacheParticleVcol(Mesh * /*mesh*/, BL::Object /*b_ob*/, BL::Mesh b_mesh, BL::ParticleSystem b_psys, BL::ParticleSystemModifier b_psmd,
+ ParticleCurveData *CData, bool background, int vcol_num)
{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ int totparts = b_psys.particles.length();
+ int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
+ int totcurves = totchild;
+
+ if(b_part.child_type() == 0)
+ totcurves += totparts;
- CData->curve_uv.clear();
+ if(totcurves == 0)
+ return;
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ int pa_no = 0;
+ if(!(b_part.child_type() == 0))
+ pa_no = totparts;
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0)
- totcurves += totparts;
+ int num_add = (totparts+totchild - pa_no);
+ CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
- if(totcurves == 0)
- continue;
+ BL::ParticleSystem::particles_iterator b_pa;
+ b_psys.particles.begin(b_pa);
+ for(; pa_no < totparts+totchild; pa_no++) {
+ /* Add vertex colors */
+ BL::Mesh::tessface_vertex_colors_iterator l;
+ b_mesh.tessface_vertex_colors.begin(l);
- int pa_no = 0;
- if(!(b_part.child_type() == 0))
- pa_no = totparts;
+ float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
+ if(b_mesh.tessface_vertex_colors.length())
+ b_psys.mcol_on_emitter(b_psmd, *b_pa, pa_no, vcol_num, &vcol.x);
+ CData->curve_vcol.push_back(vcol);
- int num_add = (totparts+totchild - pa_no);
- CData->curve_uv.reserve(CData->curve_uv.size() + num_add);
+ if(pa_no < totparts && b_pa != b_psys.particles.end())
+ ++b_pa;
+ }
+}
+
+/* A little bit of templated code here to avoid much duplication for parent/child strands:
+ * Most attributes are the same for both types, but some are handled slightly differently.
+ * These attributes are handled by templated utility functions that automatically get selected by type.
+ */
+template <typename StrandsT>
+struct StrandsTraits;
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add UVs */
- BL::Mesh::tessface_uv_textures_iterator l;
- b_mesh->tessface_uv_textures.begin(l);
+template<>
+struct StrandsTraits<BL::Strands>
+{
+ typedef BL::StrandsCurve curve_t;
+ typedef BL::StrandsVertex vertex_t;
+
+ static float3 get_location(BL::Strands b_strands, int index)
+ {
+ float *co = (b_strands.has_motion_state())? b_strands.motion_state[index].location() : b_strands.vertices[index].location();
+ return make_float3(co[0], co[1], co[2]);
+ }
+ static float3 get_uv(BL::Strands /*b_strands*/, int /*index*/, int /*uv_num*/)
+ {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+ static float3 get_vcol(BL::Strands /*b_strands*/, int /*index*/, int /*vcol_num*/)
+ {
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+};
- float3 uv = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_uv_textures.length())
- b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.x);
- CData->curve_uv.push_back(uv);
+template<>
+struct StrandsTraits<BL::StrandsChildren>
+{
+ typedef BL::StrandsChildCurve curve_t;
+ typedef BL::StrandsChildVertex vertex_t;
+
+ static float3 get_location(BL::StrandsChildren b_strands, int index)
+ {
+ float *co = b_strands.vertices[index].location();
+ return make_float3(co[0], co[1], co[2]);
+ }
+ static float3 get_uv(BL::StrandsChildren b_strands, int index, int uv_num)
+ {
+ if (uv_num < b_strands.num_curve_uv_layers()) {
+ size_t offset = uv_num * b_strands.curves.length();
+ float *uv = b_strands.curve_uvs[offset + index].uv();
+ return make_float3(uv[0], uv[1], 0.0f);
+ }
+ else
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+ static float3 get_vcol(BL::StrandsChildren b_strands, int index, int vcol_num)
+ {
+ if (vcol_num < b_strands.num_curve_vcol_layers()) {
+ size_t offset = vcol_num * b_strands.curves.length();
+ float *vcol = b_strands.curve_vcols[offset + index].vcol();
+ return make_float3(vcol[0], vcol[1], vcol[2]);
+ }
+ else
+ return make_float3(0.0f, 0.0f, 0.0f);
+ }
+};
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
+template <typename StrandsT>
+static bool ObtainCacheStrandsData(Mesh *mesh, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem b_psys, StrandsT b_strands, const Transform &/*itfm*/,
+ ParticleCurveData *CData, bool /*background*/)
+{
+ typedef StrandsTraits<StrandsT> traits;
+ typedef typename traits::curve_t CurveT;
+
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+ PointerRNA cpsys = RNA_pointer_get(&b_part.ptr, "cycles");
+
+ int mi = clamp(b_part.material()-1, 0, mesh->used_shaders.size()-1);
+ int shader = mesh->used_shaders[mi];
+
+ int totcurves = b_strands.curves.length();
+ int totvert = b_strands.vertices.length();
+
+ int keyno = CData->curvekey_co.size();
+ int curvenum = CData->curve_keynum.size();
+
+ CData->psys_firstcurve.push_back(curvenum);
+ CData->psys_curvenum.push_back(totcurves);
+ CData->psys_shader.push_back(shader);
+
+ float radius = get_float(cpsys, "radius_scale") * 0.5f;
+
+ CData->psys_rootradius.push_back(radius * get_float(cpsys, "root_width"));
+ CData->psys_tipradius.push_back(radius * get_float(cpsys, "tip_width"));
+ CData->psys_shape.push_back(get_float(cpsys, "shape"));
+ CData->psys_closetip.push_back(get_boolean(cpsys, "use_closetip"));
+
+ CData->curve_firstkey.reserve(CData->curve_firstkey.size() + totcurves);
+ CData->curve_keynum.reserve(CData->curve_keynum.size() + totcurves);
+ CData->curve_length.reserve(CData->curve_length.size() + totcurves);
+ CData->curvekey_co.reserve(CData->curvekey_co.size() + totvert);
+ CData->curvekey_time.reserve(CData->curvekey_time.size() + totvert);
+
+ int icurve = 0;
+ int ivert = 0;
+ for(; icurve < totcurves; ++icurve) {
+ CurveT b_curve = b_strands.curves[icurve];
+ int numverts = b_curve.size();
+ int showverts = b_curve.render_size();
+ int usedverts = 0;
+ CData->curve_firstkey.push_back(keyno);
+
+ float curve_length = 0.0f;
+ float3 pcKey;
+ for(int cvert = 0; cvert < showverts; ++cvert) {
+ float3 cKey = traits::get_location(b_strands, ivert + cvert);
+
+ if(cvert > 0) {
+ float step_length = len(cKey - pcKey);
+ if(step_length == 0.0f)
+ continue;
+ curve_length += step_length;
}
+ CData->curvekey_co.push_back(cKey);
+ CData->curvekey_time.push_back(curve_length);
+ pcKey = cKey;
+ usedverts++;
}
- }
+ keyno += usedverts;
+ ivert += numverts;
+ CData->curve_keynum.push_back(usedverts);
+ CData->curve_length.push_back(curve_length);
+ curvenum++;
+ }
+
return true;
}
-bool ObtainCacheParticleVcol(Mesh *mesh, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num)
+template <typename StrandsT>
+static bool ObtainCacheStrandsUV(Mesh * /*mesh*/, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem /*b_psys*/, StrandsT b_strands,
+ ParticleCurveData *CData, bool /*background*/, int uv_num)
{
- if(!(mesh && b_mesh && b_ob && CData))
- return false;
-
- CData->curve_vcol.clear();
-
- BL::Object::modifiers_iterator b_mod;
- for(b_ob->modifiers.begin(b_mod); b_mod != b_ob->modifiers.end(); ++b_mod) {
- if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (background ? b_mod->show_render() : b_mod->show_viewport())) {
- BL::ParticleSystemModifier psmd((const PointerRNA)b_mod->ptr);
- BL::ParticleSystem b_psys((const PointerRNA)psmd.particle_system().ptr);
- BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
-
- if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
- int totparts = b_psys.particles.length();
- int totchild = background ? b_psys.child_particles.length() : (int)((float)b_psys.child_particles.length() * (float)b_part.draw_percentage() / 100.0f);
- int totcurves = totchild;
-
- if(b_part.child_type() == 0)
- totcurves += totparts;
-
- if(totcurves == 0)
- continue;
-
- int pa_no = 0;
- if(!(b_part.child_type() == 0))
- pa_no = totparts;
-
- int num_add = (totparts+totchild - pa_no);
- CData->curve_vcol.reserve(CData->curve_vcol.size() + num_add);
+ typedef StrandsTraits<StrandsT> traits;
+
+// BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
- BL::ParticleSystem::particles_iterator b_pa;
- b_psys.particles.begin(b_pa);
- for(; pa_no < totparts+totchild; pa_no++) {
- /* Add vertex colors */
- BL::Mesh::tessface_vertex_colors_iterator l;
- b_mesh->tessface_vertex_colors.begin(l);
+ int totcurves = b_strands.curves.length();
- float3 vcol = make_float3(0.0f, 0.0f, 0.0f);
- if(b_mesh->tessface_vertex_colors.length())
- b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
- CData->curve_vcol.push_back(vcol);
+ CData->curve_uv.reserve(CData->curve_uv.size() + totcurves);
- if(pa_no < totparts && b_pa != b_psys.particles.end())
- ++b_pa;
- }
- }
- }
+ int icurve = 0;
+ for(; icurve < totcurves; ++icurve) {
+ CData->curve_uv.push_back(traits::get_uv(b_strands, icurve, uv_num));
}
+
+ return true;
+}
+template <typename StrandsT>
+static bool ObtainCacheStrandsVcol(Mesh * /*mesh*/, BL::Scene /*b_scene*/, BL::Object /*b_parent*/, BL::DupliObject /*b_dupli_ob*/, BL::ParticleSystem /*b_psys*/, StrandsT b_strands,
+ ParticleCurveData *CData, bool /*background*/, int vcol_num)
+{
+ typedef StrandsTraits<StrandsT> traits;
+
+// BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ int totcurves = b_strands.curves.length();
+
+ CData->curve_vcol.reserve(CData->curve_vcol.size() + totcurves);
+
+ int icurve = 0;
+ for(; icurve < totcurves; ++icurve) {
+ CData->curve_vcol.push_back(traits::get_vcol(b_strands, icurve, vcol_num));
+ }
+
return true;
}
@@ -750,6 +873,39 @@ void ExportCurveTriangleUV(ParticleCurveData *CData, int vert_offset, int resol,
}
}
+void ExportCurveUV(Mesh *mesh, ParticleCurveData *CData, ustring name, bool active_render, int primitive, int vert_offset, int resol)
+{
+ AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
+ Attribute *attr_uv;
+
+ if(primitive == CURVE_TRIANGLES) {
+ if(active_render)
+ attr_uv = mesh->attributes.add(std, name);
+ else
+ attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
+
+ float3 *uv = attr_uv->data_float3();
+
+ ExportCurveTriangleUV(CData, vert_offset, resol, uv);
+ }
+ else {
+ if(active_render)
+ attr_uv = mesh->curve_attributes.add(std, name);
+ else
+ attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
+
+ float3 *uv = attr_uv->data_float3();
+
+ if(uv) {
+ size_t i = 0;
+
+ for(size_t curve = 0; curve < CData->curve_uv.size(); curve++)
+ if(!(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f))
+ uv[i++] = CData->curve_uv[curve];
+ }
+ }
+}
+
void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int resol, uchar4 *cdata)
{
if(cdata == NULL)
@@ -782,6 +938,31 @@ void ExportCurveTriangleVcol(ParticleCurveData *CData, int vert_offset, int reso
}
}
+void ExportCurveVcol(Mesh *mesh, ParticleCurveData *CData, ustring name, int primitive, int vert_offset, int resol)
+{
+ if(primitive == CURVE_TRIANGLES) {
+ Attribute *attr_vcol = mesh->attributes.add(name, TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
+
+ uchar4 *cdata = attr_vcol->data_uchar4();
+
+ ExportCurveTriangleVcol(CData, vert_offset, resol, cdata);
+ }
+ else {
+ Attribute *attr_vcol = mesh->curve_attributes.add(name, TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
+
+ float3 *fdata = attr_vcol->data_float3();
+
+ if(fdata) {
+ size_t i = 0;
+
+ for(size_t curve = 0; curve < CData->curve_vcol.size(); curve++)
+ if(!(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f))
+ fdata[i++] = color_srgb_to_scene_linear(CData->curve_vcol[curve]);
+ }
+ }
+}
+
+
/* Hair Curve Sync */
void BlenderSync::sync_curve_settings()
@@ -856,8 +1037,61 @@ void BlenderSync::sync_curve_settings()
curve_system_manager->tag_update(scene);
}
-void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index)
+struct CurvesPSysData {
+ CurvesPSysData(BL::ParticleSystemModifier b_psmd=PointerRNA_NULL, BL::ParticleSystem b_psys=PointerRNA_NULL,
+ BL::Strands b_strands=PointerRNA_NULL, BL::StrandsChildren b_strands_children=PointerRNA_NULL) :
+ b_psmd(b_psmd), b_psys(b_psys), b_strands(b_strands), b_strands_children(b_strands_children)
+ {}
+
+ BL::ParticleSystemModifier b_psmd;
+ BL::ParticleSystem b_psys;
+ BL::Strands b_strands;
+ BL::StrandsChildren b_strands_children;
+};
+
+static void curves_get_psys_data(std::vector<CurvesPSysData> &b_psys_list, BL::Scene b_scene, BL::Object b_ob, BL::Object b_parent, BL::DupliObject b_dupli_ob, bool preview)
+{
+ BL::Object::modifiers_iterator b_mod;
+ for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) {
+ if((b_mod->type() == b_mod->type_PARTICLE_SYSTEM) && (preview ? b_mod->show_viewport() : b_mod->show_render())) {
+ BL::ParticleSystemModifier b_psmd((const PointerRNA)b_mod->ptr);
+ BL::ParticleSystem b_psys((const PointerRNA)b_psmd.particle_system().ptr);
+ BL::ParticleSettings b_part((const PointerRNA)b_psys.settings().ptr);
+
+ if((b_part.render_type() == BL::ParticleSettings::render_type_PATH) && (b_part.type() == BL::ParticleSettings::type_HAIR)) {
+ int settings = preview ? 1 : 2;
+
+ BL::StrandsChildren b_strands_children = PointerRNA_NULL;
+ BL::Strands b_strands = PointerRNA_NULL;
+
+ if (b_dupli_ob && b_parent) {
+ b_strands_children = b_dupli_ob.strands_children_new(b_scene, b_parent, b_psys, settings);
+ if (!b_strands_children)
+ b_strands = b_dupli_ob.strands_new(b_scene, b_parent, b_psys, settings);
+ }
+
+ b_psys_list.push_back(CurvesPSysData(b_psmd, b_psys, b_strands, b_strands_children));
+ }
+ }
+ }
+}
+
+static void curves_free_psys_data(std::vector<CurvesPSysData> &b_psys_list, BL::DupliObject b_dupli_ob)
+{
+ /* free temporary strands data */
+ for (int i = 0; i < b_psys_list.size(); ++i) {
+ CurvesPSysData &psys_data = b_psys_list[i];
+ if (psys_data.b_strands)
+ b_dupli_ob.strands_free(psys_data.b_strands);
+ if (psys_data.b_strands_children)
+ b_dupli_ob.strands_children_free(psys_data.b_strands_children);
+ }
+}
+
+void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_parent, bool motion, int time_index, BL::DupliObject b_dupli_ob)
{
+ BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
+
if(!motion) {
/* Clear stored curve data */
mesh->curve_keys.clear();
@@ -888,27 +1122,46 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
if(!preview)
set_resolution(&b_ob, &b_scene, true);
- ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_quick_inverse(tfm);
+
+ /* obtain camera parameters */
+ float3 RotCam;
+ Camera *camera = scene->camera;
+ if(camera->type == CAMERA_ORTHOGRAPHIC) {
+ Transform &ctfm = camera->matrix;
+ RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
+ }
+ else {
+ Transform &ctfm = camera->matrix;
+ RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
+ }
+ bool is_ortho_camera = camera->type == CAMERA_ORTHOGRAPHIC;
+
+ std::vector<CurvesPSysData> b_psys_list;
+ curves_get_psys_data(b_psys_list, b_scene, b_ob, b_parent, b_dupli_ob, preview);
+
+ for (int i = 0; i < b_psys_list.size(); ++i) {
+ CurvesPSysData &psys_data = b_psys_list[i];
+ if (psys_data.b_strands_children)
+ /* use child strands cache */
+ ObtainCacheStrandsData(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children,
+ itfm, &CData, !preview);
+ else if (psys_data.b_strands)
+ /* use parent strands cache */
+ ObtainCacheStrandsData(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands,
+ itfm, &CData, !preview);
+ else {
+ /* use object data */
+ ObtainCacheParticleData(mesh, b_ob, psys_data.b_psys,
+ itfm, &CData, !preview);
+ }
+ }
/* add hair geometry to mesh */
if(primitive == CURVE_TRIANGLES) {
if(triangle_method == CURVE_CAMERA_TRIANGLES) {
- /* obtain camera parameters */
- float3 RotCam;
- Camera *camera = scene->camera;
- Transform &ctfm = camera->matrix;
- if(camera->type == CAMERA_ORTHOGRAPHIC) {
- RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
- }
- else {
- Transform tfm = get_transform(b_ob.matrix_world());
- Transform itfm = transform_quick_inverse(tfm);
- RotCam = transform_point(&itfm, make_float3(ctfm.x.w,
- ctfm.y.w,
- ctfm.z.w));
- }
- bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
- ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
+ ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho_camera);
}
else {
ExportCurveTriangleGeometry(mesh, &CData, resolution);
@@ -955,33 +1208,31 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
int vcol_num = 0;
for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l, vcol_num++) {
+ ustring name = ustring(l->name().c_str());
+
if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
continue;
- ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);
-
- if(primitive == CURVE_TRIANGLES) {
- Attribute *attr_vcol = mesh->attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);
-
- uchar4 *cdata = attr_vcol->data_uchar4();
-
- ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
- }
- else {
- Attribute *attr_vcol = mesh->curve_attributes.add(
- ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);
-
- float3 *fdata = attr_vcol->data_float3();
-
- if(fdata) {
- size_t i = 0;
-
- for(size_t curve = 0; curve < CData.curve_vcol.size(); curve++)
- if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
- fdata[i++] = color_srgb_to_scene_linear(CData.curve_vcol[curve]);
+ CData.curve_vcol.clear();
+
+ for (int i = 0; i < b_psys_list.size(); ++i) {
+ CurvesPSysData &psys_data = b_psys_list[i];
+ if (psys_data.b_strands_children)
+ /* use child strands cache */
+ ObtainCacheStrandsVcol(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children,
+ &CData, !preview, vcol_num);
+ else if (psys_data.b_strands)
+ /* use parent strands cache */
+ ObtainCacheStrandsVcol(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands,
+ &CData, !preview, vcol_num);
+ else {
+ /* use object data */
+ ObtainCacheParticleVcol(mesh, b_ob, b_mesh, psys_data.b_psys, psys_data.b_psmd,
+ &CData, !preview, vcol_num);
}
}
+
+ ExportCurveVcol(mesh, &CData, name, primitive, tri_num * 3, used_res);
}
}
@@ -992,45 +1243,37 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool
for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l, uv_num++) {
bool active_render = l->active_render();
- AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
ustring name = ustring(l->name().c_str());
/* UV map */
- if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
- Attribute *attr_uv;
-
- ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);
-
- if(primitive == CURVE_TRIANGLES) {
- if(active_render)
- attr_uv = mesh->attributes.add(std, name);
- else
- attr_uv = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);
-
- float3 *uv = attr_uv->data_float3();
-
- ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
- }
+ if(!(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, ATTR_STD_UV))))
+ continue;
+
+ CData.curve_uv.clear();
+
+ for (int i = 0; i < b_psys_list.size(); ++i) {
+ CurvesPSysData &psys_data = b_psys_list[i];
+ if (psys_data.b_strands_children)
+ /* use child strands cache */
+ ObtainCacheStrandsUV(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands_children,
+ &CData, !preview, uv_num);
+ else if (psys_data.b_strands)
+ /* use parent strands cache */
+ ObtainCacheStrandsUV(mesh, b_scene, b_parent, b_dupli_ob, psys_data.b_psys, psys_data.b_strands,
+ &CData, !preview, uv_num);
else {
- if(active_render)
- attr_uv = mesh->curve_attributes.add(std, name);
- else
- attr_uv = mesh->curve_attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE);
-
- float3 *uv = attr_uv->data_float3();
-
- if(uv) {
- size_t i = 0;
-
- for(size_t curve = 0; curve < CData.curve_uv.size(); curve++)
- if(!(CData.curve_keynum[curve] <= 1 || CData.curve_length[curve] == 0.0f))
- uv[i++] = CData.curve_uv[curve];
- }
+ /* use object data */
+ ObtainCacheParticleUV(mesh, b_ob, b_mesh, psys_data.b_psys, psys_data.b_psmd,
+ &CData, !preview, uv_num);
}
}
+
+ ExportCurveUV(mesh, &CData, name, active_render, primitive, tri_num * 3, used_res);
}
}
+ curves_free_psys_data(b_psys_list, b_dupli_ob);
+
if(!preview)
set_resolution(&b_ob, &b_scene, false);
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index d88ebb854d2..ea69bc7a636 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -422,6 +422,52 @@ static void attr_create_pointiness(Scene *scene,
}
}
+/* Create vertex custom attributes. */
+static void attr_create_vertex_properties(Scene *scene,
+ Mesh *mesh,
+ BL::Mesh b_mesh)
+{
+ {
+ BL::Mesh::vertex_layers_float_iterator l;
+ for(b_mesh.vertex_layers_float.begin(l); l != b_mesh.vertex_layers_float.end(); ++l) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+
+ BL::MeshVertexFloatPropertyLayer::data_iterator d;
+ float *data = attr->data_float();
+ size_t i = 0;
+
+ for(l->data.begin(d); d != l->data.end(); ++d, ++i) {
+ *data = d->value();
+ data += 1;
+ }
+ }
+ }
+
+ {
+ BL::Mesh::vertex_layers_int_iterator l;
+ for(b_mesh.vertex_layers_int.begin(l); l != b_mesh.vertex_layers_int.end(); ++l) {
+ if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
+ continue;
+
+ Attribute *attr = mesh->attributes.add(
+ ustring(l->name().c_str()), TypeDesc::TypeFloat, ATTR_ELEMENT_VERTEX);
+
+ BL::MeshVertexIntPropertyLayer::data_iterator d;
+ float *data = attr->data_float();
+ size_t i = 0;
+
+ for(l->data.begin(d); d != l->data.end(); ++d, ++i) {
+ *data = (float)d->value();
+ data += 1;
+ }
+ }
+ }
+}
+
/* Create Mesh */
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
@@ -528,6 +574,7 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
*/
attr_create_vertex_color(scene, mesh, b_mesh, nverts);
attr_create_uv_map(scene, mesh, b_mesh, nverts);
+ attr_create_vertex_properties(scene, mesh, b_mesh);
/* for volume objects, create a matrix to transform from object space to
* mesh texture space. this does not work with deformations but that can
@@ -587,8 +634,10 @@ static void create_subd_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, PointerR
/* Sync */
-Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris)
+Mesh *BlenderSync::sync_mesh(BL::Object b_parent, bool object_updated, bool hide_tris, BL::DupliObject b_dupli_ob)
{
+ BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
+
/* When viewport display is not needed during render we can force some
* caches to be releases from blender side in order to reduce peak memory
* footprint during synchronization process.
@@ -599,7 +648,6 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
/* test if we can instance or if the object is modified */
BL::ID b_ob_data = b_ob.data();
- BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
BL::Material material_override = render_layer.material_override;
/* find shader indices */
@@ -630,7 +678,28 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
}
Mesh *mesh;
- if(!mesh_map.sync(&mesh, key)) {
+ bool need_update;
+ BL::CacheLibrary b_cachelib = b_parent.cache_library();
+ const BL::CacheLibrary::eval_mode_enum dupli_eval_mode =
+ preview ? BL::CacheLibrary::eval_mode_REALTIME
+ : BL::CacheLibrary::eval_mode_RENDER;
+ bool use_dupli_override = b_dupli_ob && b_cachelib &&
+ ((b_cachelib.eval_mode() & dupli_eval_mode) != 0) &&
+ (b_cachelib.source_mode() == BL::CacheLibrary::source_mode_CACHE ||
+ b_cachelib.display_mode() == BL::CacheLibrary::display_mode_RESULT);
+ if (use_dupli_override) {
+ /* if a dupli override (cached data) is used, identify the mesh by object and parent together,
+ * so that individual per-dupli overrides are possible.
+ */
+ MeshKey key = MeshKey(b_parent, b_ob);
+ need_update = mesh_map.sync(&mesh, b_ob, b_parent, key);
+ }
+ else {
+ BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob_data;
+ need_update = mesh_map.sync(&mesh, key);
+ }
+
+ if(!need_update) {
/* if transform was applied to mesh, need full update */
if(object_updated && mesh->transform_applied);
/* test if shaders changed, these can be object level so mesh
@@ -681,7 +750,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
b_ob.update_from_editmode();
bool need_undeformed = mesh->need_attribute(scene, ATTR_STD_GENERATED);
- BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
+ BL::Mesh b_mesh = (use_dupli_override)?
+ dupli_to_mesh(b_data, b_scene, b_parent, b_dupli_ob, !preview, need_undeformed):
+ object_to_mesh(b_data, b_ob, b_scene, true, !preview, need_undeformed);
if(b_mesh) {
if(render_layer.use_surfaces && !hide_tris) {
@@ -694,7 +765,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
}
if(render_layer.use_hair)
- sync_curves(mesh, b_mesh, b_ob, false);
+ sync_curves(mesh, b_mesh, b_parent, false, 0, b_dupli_ob);
if(can_free_caches) {
b_ob.cache_release();
@@ -740,8 +811,9 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri
return mesh;
}
-void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time)
+void BlenderSync::sync_mesh_motion(BL::Object b_parent, Object *object, float motion_time, BL::DupliObject b_dupli_ob)
{
+ BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
/* ensure we only sync instanced meshes once */
Mesh *mesh = object->mesh;
@@ -800,7 +872,9 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
if(ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
/* get derived mesh */
- b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false);
+ b_mesh = (b_dupli_ob && b_parent)?
+ dupli_to_mesh(b_data, b_scene, b_parent, b_dupli_ob, !preview, false):
+ object_to_mesh(b_data, b_ob, b_scene, true, !preview, false);
}
if(!b_mesh) {
@@ -890,7 +964,7 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
/* hair motion */
if(numkeys)
- sync_curves(mesh, b_mesh, b_ob, true, time_index);
+ sync_curves(mesh, b_mesh, b_parent, true, time_index, b_dupli_ob);
/* free derived mesh */
b_data.meshes.remove(b_mesh);
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index bcc366732df..e999945e955 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -234,8 +234,53 @@ void BlenderSync::sync_background_light(bool use_portal)
/* Object */
-Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob,
- Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal)
+static bool object_boundbox_clip(Scene *scene,
+ BL::Object b_ob,
+ Transform& tfm,
+ float margin)
+{
+ Camera *cam = scene->camera;
+ Transform& worldtondc = cam->worldtondc;
+ BL::Array<float, 24> boundbox = b_ob.bound_box();
+ float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ bool all_behind = true;
+ for(int i = 0; i < 8; ++i) {
+ float3 p = make_float3(boundbox[3 * i + 0],
+ boundbox[3 * i + 1],
+ boundbox[3 * i + 2]);
+ p = transform_point(&tfm, p);
+ p = transform_point(&worldtondc, p);
+ if(p.z >= -margin) {
+ all_behind = false;
+ }
+ p /= p.z;
+ bb_min = min(bb_min, p);
+ bb_max = max(bb_max, p);
+ }
+ if(!all_behind) {
+ if(bb_min.x >= 1.0f + margin ||
+ bb_min.y >= 1.0f + margin ||
+ bb_max.x <= -margin ||
+ bb_max.y <= -margin)
+ {
+ return true;
+ }
+ return false;
+ }
+ return true;
+}
+
+Object *BlenderSync::sync_object(BL::Object b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::DupliObject b_dupli_ob,
+ Transform& tfm,
+ uint layer_flag,
+ float motion_time,
+ bool hide_tris,
+ bool use_camera_cull,
+ float camera_cull_margin,
+ bool *use_portal)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
bool motion = motion_time != 0.0f;
@@ -253,6 +298,11 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
if(!object_is_mesh(b_ob))
return NULL;
+ /* Perform camera space culling. */
+ if(use_camera_cull && object_boundbox_clip(scene, b_ob, tfm, camera_cull_margin)) {
+ return NULL;
+ }
+
/* key to lookup object */
ObjectKey key(b_parent, persistent_id, b_ob);
Object *object;
@@ -277,7 +327,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
/* mesh deformation */
if(object->mesh)
- sync_mesh_motion(b_ob, object, motion_time);
+ sync_mesh_motion(b_parent, object, motion_time, b_dupli_ob);
}
return object;
@@ -292,7 +342,10 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
/* mesh sync */
- object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
+ if (b_dupli_ob)
+ object->mesh = sync_mesh(b_parent, object_updated, hide_tris, b_dupli_ob);
+ else
+ object->mesh = sync_mesh(b_ob, object_updated, hide_tris);
/* special case not tracked by object update flags */
@@ -478,6 +531,15 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
mesh_motion_synced.clear();
}
+ PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+ bool allow_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
+ !b_scene.render().use_multiview() &&
+ get_boolean(cscene, "use_camera_cull");
+ float camera_cull_margin = 0.0f;
+ if(allow_camera_cull) {
+ camera_cull_margin = get_float(cscene, "camera_cull_margin");
+ }
+
/* object loop */
BL::Scene::object_bases_iterator b_base;
BL::Scene b_sce = b_scene;
@@ -500,6 +562,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
if(!hide) {
progress.set_sync_status("Synchronizing object", b_ob.name());
+ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+ bool use_camera_cull = allow_camera_cull && get_boolean(cobject, "use_camera_cull");
+ if(use_camera_cull) {
+ /* Need to have proper projection matrix. */
+ scene->camera->update();
+ }
if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) {
/* dupli objects */
b_ob.dupli_list_create(b_scene, dupli_settings);
@@ -519,7 +587,16 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id();
/* sync object and mesh or light data */
- Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris, &use_portal);
+ Object *object = sync_object(b_ob,
+ persistent_id.data,
+ *b_dup,
+ tfm,
+ ob_layer,
+ motion_time,
+ hide_tris,
+ use_camera_cull,
+ camera_cull_margin,
+ &use_portal);
/* sync possible particle data, note particle_id
* starts counting at 1, first is dummy particle */
@@ -539,7 +616,17 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
if(!object_render_hide(b_ob, true, true, hide_tris)) {
/* object itself */
Transform tfm = get_transform(b_ob.matrix_world());
- sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris, &use_portal);
+
+ sync_object(b_ob,
+ NULL,
+ PointerRNA_NULL,
+ tfm,
+ ob_layer,
+ motion_time,
+ hide_tris,
+ use_camera_cull,
+ camera_cull_margin,
+ &use_portal);
}
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index bb345e2b3cf..379ac8c8fa5 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -100,7 +100,8 @@ void BlenderSession::create_session()
start_resize_time = 0.0;
/* create scene */
- scene = new Scene(scene_params, session_params.device);
+ bool free_data_after_update = background && !scene_params.persistent_data;
+ scene = new Scene(scene_params, session_params.device, free_data_after_update);
/* setup callbacks for builtin image support */
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7);
@@ -1001,6 +1002,18 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti
is_float = true;
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ channels = 4;
+ width = height = depth = b_point_density_node.resolution();
+ is_float = true;
+ }
+ }
}
bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels)
@@ -1143,6 +1156,17 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void
fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
}
+ else {
+ /* TODO(sergey): Check we're indeed in shader node tree. */
+ PointerRNA ptr;
+ RNA_pointer_create(NULL, &RNA_Node, builtin_data, &ptr);
+ BL::Node b_node(ptr);
+ if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ int length;
+ b_point_density_node.calc_point_density(b_scene, &length, &pixels);
+ }
+ }
return false;
}
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index d3b01fbf1d4..9f48600161d 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -22,6 +22,7 @@
#include "scene.h"
#include "shader.h"
+#include "blender_texture.h"
#include "blender_sync.h"
#include "blender_util.h"
@@ -736,6 +737,34 @@ static ShaderNode *add_node(Scene *scene,
uvm->from_dupli = b_uvmap_node.from_dupli();
node = uvm;
}
+ else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
+ BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
+ PointDensityTextureNode *point_density = new PointDensityTextureNode();
+ point_density->filename = b_point_density_node.name();
+ point_density->space =
+ PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
+ point_density->interpolation =
+ (InterpolationType)b_point_density_node.interpolation();
+ point_density->builtin_data = b_point_density_node.ptr.data;
+
+ /* Transformation form world space to texture space. */
+ BL::Object b_ob(b_point_density_node.object());
+ if(b_ob) {
+ float3 loc, size;
+ point_density_texture_space(b_point_density_node, loc, size);
+ point_density->tfm =
+ transform_translate(-loc) * transform_scale(size) *
+ transform_inverse(get_transform(b_ob.matrix_world()));
+ }
+
+ /* TODO(sergey): Use more proper update flag. */
+ if(true) {
+ scene->image_manager->tag_reload_image(point_density->filename,
+ point_density->builtin_data,
+ point_density->interpolation);
+ }
+ node = point_density;
+ }
if(node)
graph->add(node);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index c5fb7925306..87e2932d6b1 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -435,6 +435,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background, bo
params.use_qbvh = false;
}
+ params.use_bvh_triangle_storage = RNA_boolean_get(&cscene, "debug_use_triangle_storage");
+
return params;
}
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 89d93e19e9f..ef279a4fe63 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -83,13 +83,22 @@ private:
void sync_curve_settings();
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
- Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris);
- void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0);
- Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob,
- Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal);
+ Mesh *sync_mesh(BL::Object b_parent, bool object_updated, bool hide_tris, BL::DupliObject b_dupli_ob = PointerRNA_NULL);
+ void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_parent, bool motion, int time_index = 0, BL::DupliObject b_dupli_ob = PointerRNA_NULL);
+ Object *sync_object(BL::Object b_parent,
+ int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
+ BL::DupliObject b_dupli_ob,
+ Transform& tfm,
+ uint layer_flag,
+ float motion_time,
+ bool hide_tris,
+ bool use_camera_cull,
+ float camera_cull_margin,
+ bool *use_portal);
void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal);
void sync_background_light(bool use_portal);
- void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time);
+ void sync_mesh_motion(BL::Object b_parent, Object *object, float motion_time, BL::DupliObject b_dupli_ob = PointerRNA_NULL);
+
void sync_camera_motion(BL::Object b_ob, float motion_time);
/* particles */
@@ -111,7 +120,7 @@ private:
id_map<void*, Shader> shader_map;
id_map<ObjectKey, Object> object_map;
- id_map<void*, Mesh> mesh_map;
+ id_map<MeshKey, Mesh> mesh_map;
id_map<ObjectKey, Light> light_map;
id_map<ParticleSystemKey, ParticleSystem> particle_system_map;
set<Mesh*> mesh_synced;
diff --git a/intern/cycles/blender/blender_texture.cpp b/intern/cycles/blender/blender_texture.cpp
new file mode 100644
index 00000000000..cb4dd1792d0
--- /dev/null
+++ b/intern/cycles/blender/blender_texture.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * 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.
+ */
+
+#include "blender_texture.h"
+
+CCL_NAMESPACE_BEGIN
+
+namespace {
+
+/* Point density helpers. */
+
+static void density_texture_space_invert(float3& loc,
+ float3& size)
+{
+ if(size.x != 0.0f) size.x = 0.5f/size.x;
+ if(size.y != 0.0f) size.y = 0.5f/size.y;
+ if(size.z != 0.0f) size.z = 0.5f/size.z;
+
+ loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);
+}
+
+static void density_object_texture_space(BL::Object b_ob,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_ob.type() == BL::Object::type_MESH) {
+ BL::Mesh b_mesh(b_ob.data());
+ loc = get_float3(b_mesh.texspace_location());
+ size = get_float3(b_mesh.texspace_size());
+ }
+ else {
+ /* TODO(sergey): Not supported currently. */
+ }
+ /* Adjust texture space to include density points on the boundaries. */
+ size = size + make_float3(radius, radius, radius);
+ density_texture_space_invert(loc, size);
+}
+
+static void density_particle_system_texture_space(
+ BL::Object b_ob,
+ BL::ParticleSystem b_particle_system,
+ float radius,
+ float3& loc,
+ float3& size)
+{
+ if(b_particle_system.settings().type() == BL::ParticleSettings::type_HAIR) {
+ /* TODO(sergey): Not supported currently. */
+ return;
+ }
+ Transform tfm = get_transform(b_ob.matrix_world());
+ Transform itfm = transform_inverse(tfm);
+ float3 min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+ max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+ float3 particle_size = make_float3(radius, radius, radius);
+ for(int i = 0; i < b_particle_system.particles.length(); ++i) {
+ BL::Particle particle = b_particle_system.particles[i];
+ float3 location = get_float3(particle.location());
+ location = transform_point(&itfm, location);
+ min = ccl::min(min, location - particle_size);
+ max = ccl::max(max, location + particle_size);
+ }
+ /* Calculate texture space from the particle bounds. */
+ loc = (min + max) * 0.5f;
+ size = (max - min) * 0.5f;
+ density_texture_space_invert(loc, size);
+}
+
+} /* namespace */
+
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size)
+{
+ /* Fallback values. */
+ loc = make_float3(0.0f, 0.0f, 0.0f);
+ size = make_float3(0.0f, 0.0f, 0.0f);
+ BL::Object b_ob(b_point_density_node.object());
+ if(!b_ob) {
+ return;
+ }
+ if(b_point_density_node.point_source() ==
+ BL::ShaderNodeTexPointDensity::point_source_PARTICLE_SYSTEM)
+ {
+ BL::ParticleSystem b_particle_system(
+ b_point_density_node.particle_system());
+ if(b_particle_system) {
+ density_particle_system_texture_space(b_ob,
+ b_particle_system,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+ }
+ else {
+ density_object_texture_space(b_ob,
+ b_point_density_node.radius(),
+ loc,
+ size);
+ }
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/blender/blender_texture.h b/intern/cycles/blender/blender_texture.h
new file mode 100644
index 00000000000..74fbca02a9e
--- /dev/null
+++ b/intern/cycles/blender/blender_texture.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * 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.
+ */
+
+#ifndef __BLENDER_TEXTURE_H__
+#define __BLENDER_TEXTURE_H__
+
+#include <stdlib.h>
+#include "blender_sync.h"
+
+CCL_NAMESPACE_BEGIN
+
+void point_density_texture_space(BL::ShaderNodeTexPointDensity b_point_density_node,
+ float3& loc,
+ float3& size);
+
+CCL_NAMESPACE_END
+
+#endif /* __BLENDER_TEXTURE_H__ */
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index cb50680160c..3199afedf3c 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -52,6 +52,18 @@ static inline BL::Mesh object_to_mesh(BL::BlendData data, BL::Object object, BL:
return me;
}
+static inline BL::Mesh dupli_to_mesh(BL::BlendData data, BL::Scene scene, BL::Object parent, BL::DupliObject dob, bool render, bool calc_undeformed)
+{
+ BL::Mesh me = data.meshes.new_from_dupli(scene, parent, dob, (render)? 2: 1, false, calc_undeformed);
+ if ((bool)me) {
+ if (me.use_auto_smooth()) {
+ me.calc_normals_split();
+ }
+ me.calc_tessface(true);
+ }
+ return me;
+}
+
static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
{
for(int i = 0; i < size; i++) {
@@ -568,6 +580,36 @@ struct ObjectKey {
}
};
+/* Mesh Key */
+
+struct MeshKey {
+ void *parent;
+ void *mesh;
+
+ MeshKey(void *mesh_)
+ : parent(NULL), mesh(mesh_)
+ {
+ }
+
+ MeshKey(void *parent_, void *mesh_)
+ : parent(parent_), mesh(mesh_)
+ {
+ }
+
+ bool operator<(const MeshKey& k) const
+ {
+ if(mesh < k.mesh) {
+ return true;
+ }
+ else if(mesh == k.mesh) {
+ return parent < k.parent;
+ return true;
+ }
+
+ return false;
+ }
+};
+
/* Particle System Key */
struct ParticleSystemKey {
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index 0d9412a5712..ff435b751ad 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -285,28 +285,34 @@ void BVH::pack_triangle(int idx, float4 woop[3])
void BVH::pack_primitives()
{
- int nsize = TRI_NODE_SIZE;
+ const int nsize = TRI_NODE_SIZE;
+ const bool use_triangle_storage = params.use_triangle_storage;
size_t tidx_size = pack.prim_index.size();
pack.tri_woop.clear();
- pack.tri_woop.resize(tidx_size * nsize);
+ if (use_triangle_storage) {
+ pack.tri_woop.resize(tidx_size * nsize);
+ }
+ else {
+ pack.tri_woop.resize(0);
+ }
pack.prim_visibility.clear();
pack.prim_visibility.resize(tidx_size);
for(unsigned int i = 0; i < tidx_size; i++) {
if(pack.prim_index[i] != -1) {
- float4 woop[3];
-
- if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
- pack_triangle(i, woop);
- }
- else {
- /* Avoid use of uninitialized memory. */
- memset(&woop, 0, sizeof(woop));
+ if(use_triangle_storage) {
+ float4 woop[3];
+ if(pack.prim_type[i] & PRIMITIVE_TRIANGLE) {
+ pack_triangle(i, woop);
+ }
+ else {
+ /* Avoid use of uninitialized memory. */
+ memset(&woop, 0, sizeof(woop));
+ }
+ memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
}
- memcpy(&pack.tri_woop[i * nsize], woop, sizeof(float4)*3);
-
int tob = pack.prim_object[i];
Object *ob = objects[tob];
pack.prim_visibility[i] = ob->visibility;
@@ -315,7 +321,9 @@ void BVH::pack_primitives()
pack.prim_visibility[i] |= PATH_RAY_CURVE;
}
else {
- memset(&pack.tri_woop[i * nsize], 0, sizeof(float4)*3);
+ if(use_triangle_storage) {
+ memset(&pack.tri_woop[i * nsize], 0, sizeof(float4)*3);
+ }
pack.prim_visibility[i] = 0;
}
}
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index af8d8eeb3ee..892fd906e77 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -49,6 +49,9 @@ public:
/* QBVH */
bool use_qbvh;
+ /* Use pre-aligned tringle storage for faster lookup. */
+ bool use_triangle_storage;
+
/* fixed parameters */
enum {
MAX_DEPTH = 64,
@@ -73,6 +76,7 @@ public:
top_level = false;
use_cache = false;
use_qbvh = false;
+ use_triangle_storage = true;
}
/* SAH costs */
diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake
index d7c59f42a5e..13196e2ba6b 100644
--- a/intern/cycles/cmake/external_libs.cmake
+++ b/intern/cycles/cmake/external_libs.cmake
@@ -30,7 +30,7 @@ if(NOT CYCLES_STANDALONE_REPOSITORY)
set(GLEW_INCLUDE_DIR "${GLEW_INCLUDE_PATH}")
endif()
-if(WITH_CYCLES_STANDALONE AND WITH_CYCLES_STANDALONE_GUI)
+if(WITH_CYCLES_STANDALONE)
set(CYCLES_APP_GLEW_LIBRARY ${BLENDER_GLEW_LIBRARIES})
endif()
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 89dd3542ef6..b6c6e502c95 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -124,6 +124,7 @@ set(SRC_SVM_HEADERS
svm/svm_value.h
svm/svm_vector_transform.h
svm/svm_voronoi.h
+ svm/svm_voxel.h
svm/svm_wave.h
)
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index 220169f56d3..d6e4abc8267 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -110,9 +110,19 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
const float Sz = isect_precalc->Sz;
/* Calculate vertices relative to ray origin. */
- const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ float4 tri_a, tri_b, tri_c;
+ if (kernel_data.bvh.use_tri_storage) {
+ tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
+ tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
+ tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ }
+ else {
+ const int prim = kernel_tex_fetch(__prim_index, triAddr);
+ const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x));
+ tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y));
+ tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z));
+ }
const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
@@ -203,9 +213,19 @@ ccl_device_inline void triangle_intersect_subsurface(
const float Sz = isect_precalc->Sz;
/* Calculate vertices relative to ray origin. */
- const float4 tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ float4 tri_a, tri_b, tri_c;
+ if (kernel_data.bvh.use_tri_storage) {
+ tri_a = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0);
+ tri_b = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1);
+ tri_c = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2);
+ }
+ else {
+ const int prim = kernel_tex_fetch(__prim_index, triAddr);
+ const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x));
+ tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y));
+ tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z));
+ }
const float3 A = make_float3(tri_a.x - P.x, tri_a.y - P.y, tri_a.z - P.z);
const float3 B = make_float3(tri_b.x - P.x, tri_b.y - P.y, tri_b.z - P.z);
const float3 C = make_float3(tri_c.x - P.x, tri_c.y - P.y, tri_c.z - P.z);
@@ -318,9 +338,19 @@ ccl_device_inline float3 triangle_refine(KernelGlobals *kg,
P = P + D*t;
- const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ float4 tri_a, tri_b, tri_c;
+ if (kernel_data.bvh.use_tri_storage) {
+ tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
+ tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1);
+ tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ }
+ else {
+ const int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x));
+ tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y));
+ tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z));
+ }
float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
@@ -375,9 +405,19 @@ ccl_device_inline float3 triangle_refine_subsurface(KernelGlobals *kg,
P = P + D*t;
- const float4 tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0),
- tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1),
- tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ float4 tri_a, tri_b, tri_c;
+ if (kernel_data.bvh.use_tri_storage) {
+ tri_a = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+0);
+ tri_b = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+1);
+ tri_c = kernel_tex_fetch(__tri_woop, isect->prim*TRI_NODE_SIZE+2);
+ }
+ else {
+ const int prim = kernel_tex_fetch(__prim_index, isect->prim);
+ const float4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
+ tri_a = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x));
+ tri_b = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y));
+ tri_c = kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z));
+ }
float3 edge1 = make_float3(tri_a.x - tri_c.x, tri_a.y - tri_c.y, tri_a.z - tri_c.z);
float3 edge2 = make_float3(tri_b.x - tri_c.x, tri_b.y - tri_c.y, tri_b.z - tri_c.z);
float3 tvec = make_float3(P.x - tri_c.x, P.y - tri_c.y, P.z - tri_c.z);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 54b78dec54d..fbdeeed1216 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -950,7 +950,8 @@ typedef struct KernelBVH {
int have_curves;
int have_instancing;
int use_qbvh;
- int pad1, pad2;
+ int use_tri_storage;
+ int pad1;
} KernelBVH;
typedef enum CurveFlag {
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index e5e25eb6ca8..db83d2ec024 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -179,6 +179,7 @@ CCL_NAMESPACE_END
#include "svm_checker.h"
#include "svm_brick.h"
#include "svm_vector_transform.h"
+#include "svm_voxel.h"
CCL_NAMESPACE_BEGIN
@@ -434,7 +435,10 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, Shade
break;
case NODE_NORMAL_MAP:
svm_node_normal_map(kg, sd, stack, node);
- break;
+ break;
+ case NODE_TEX_VOXEL:
+ svm_node_tex_voxel(kg, sd, stack, node, &offset);
+ break;
case NODE_END:
default:
return;
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index 4f2117a605b..52f9bec02ef 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -119,7 +119,8 @@ typedef enum NodeType {
NODE_TANGENT,
NODE_NORMAL_MAP,
NODE_HAIR_INFO,
- NODE_UVMAP
+ NODE_UVMAP,
+ NODE_TEX_VOXEL,
} NodeType;
typedef enum NodeAttributeType {
@@ -364,6 +365,11 @@ typedef enum NodeBumpOffset {
NODE_BUMP_OFFSET_DY,
} NodeBumpOffset;
+typedef enum NodeTexVoxelSpace {
+ NODE_TEX_VOXEL_SPACE_OBJECT = 0,
+ NODE_TEX_VOXEL_SPACE_WORLD = 1,
+} NodeTexVoxelSpace;
+
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
diff --git a/intern/cycles/kernel/svm/svm_voxel.h b/intern/cycles/kernel/svm/svm_voxel.h
new file mode 100644
index 00000000000..4838926503e
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_voxel.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011-2015 Blender Foundation
+ *
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device void svm_node_tex_voxel(KernelGlobals *kg,
+ ShaderData *sd,
+ float *stack,
+ uint4 node,
+ int *offset)
+{
+ int id = node.y;
+ uint co_offset, density_out_offset, color_out_offset, space;
+ decode_node_uchar4(node.z, &co_offset, &density_out_offset, &color_out_offset, &space);
+ float3 co = stack_load_float3(stack, co_offset);
+ if(space == NODE_TEX_VOXEL_SPACE_OBJECT) {
+ co = volume_normalized_position(kg, sd, co);
+ }
+ else {
+ kernel_assert(space == NODE_TEX_VOXEL_SPACE_WORLD);
+ Transform tfm;
+ tfm.x = read_node_float(kg, offset);
+ tfm.y = read_node_float(kg, offset);
+ tfm.z = read_node_float(kg, offset);
+ tfm.w = read_node_float(kg, offset);
+ co = transform_point(&tfm, co);
+ }
+ if(co.x < 0.0f || co.y < 0.0f || co.z < 0.0f ||
+ co.x > 1.0f || co.y > 1.0f || co.z > 1.0f)
+ {
+ if (stack_valid(density_out_offset))
+ stack_store_float(stack, density_out_offset, 0.0f);
+ if (stack_valid(color_out_offset))
+ stack_store_float3(stack, color_out_offset, make_float3(0.0f, 0.0f, 0.0f));
+ return;
+ }
+#ifdef __KERNEL_GPU__
+ float4 r = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+#else
+ float4 r = kernel_tex_image_interp_3d(id, co.x, co.y, co.z);
+#endif
+ if (stack_valid(density_out_offset))
+ stack_store_float(stack, density_out_offset, r.w);
+ if (stack_valid(color_out_offset))
+ stack_store_float3(stack, color_out_offset, make_float3(r.x, r.y, r.z));
+}
+
+CCL_NAMESPACE_END
diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp
index 19ca159d03f..884186c5914 100644
--- a/intern/cycles/render/mesh.cpp
+++ b/intern/cycles/render/mesh.cpp
@@ -515,6 +515,7 @@ void Mesh::compute_bvh(SceneParams *params, Progress *progress, int n, int total
BVHParams bparams;
bparams.use_cache = params->use_bvh_cache;
bparams.use_spatial_split = params->use_bvh_spatial_split;
+ bparams.use_triangle_storage = params->use_bvh_triangle_storage;
bparams.use_qbvh = params->use_qbvh;
delete bvh;
@@ -554,9 +555,10 @@ bool Mesh::has_motion_blur() const
/* Mesh Manager */
-MeshManager::MeshManager()
+MeshManager::MeshManager(const bool free_data_after_update_)
{
bvh = NULL;
+ free_data_after_update = free_data_after_update_;
need_update = true;
need_flags_update = true;
}
@@ -1085,6 +1087,7 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
bparams.use_qbvh = scene->params.use_qbvh;
bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
bparams.use_cache = scene->params.use_bvh_cache;
+ bparams.use_triangle_storage = scene->params.use_bvh_triangle_storage;
delete bvh;
bvh = BVH::create(bparams, scene->objects);
@@ -1132,6 +1135,7 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
dscene->data.bvh.root = pack.root_index;
dscene->data.bvh.use_qbvh = scene->params.use_qbvh;
+ dscene->data.bvh.use_tri_storage = scene->params.use_bvh_triangle_storage? 1: 0;
}
void MeshManager::device_update_flags(Device * /*device*/,
@@ -1313,6 +1317,15 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen
device_update_bvh(device, dscene, scene, progress);
+ if(free_data_after_update) {
+ foreach(Object *object, scene->objects) {
+ if(object->mesh->bvh != NULL) {
+ delete object->mesh->bvh;
+ object->mesh->bvh = NULL;
+ }
+ }
+ }
+
need_update = false;
}
diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h
index 76c186a3feb..887ef65004e 100644
--- a/intern/cycles/render/mesh.h
+++ b/intern/cycles/render/mesh.h
@@ -152,7 +152,10 @@ public:
bool need_update;
bool need_flags_update;
- MeshManager();
+ /* Free memory used by BVH after device update. */
+ bool free_data_after_update;
+
+ MeshManager(const bool free_data_after_update);
~MeshManager();
bool displace(Device *device, DeviceScene *dscene, Scene *scene, Mesh *mesh, Progress& progress);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 430c059d686..f799e2682eb 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -1297,6 +1297,118 @@ void BrickTextureNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_brick_texture");
}
+/* Point Density Texture */
+
+static ShaderEnum point_density_space_init()
+{
+ ShaderEnum enm;
+
+ enm.insert("Object", NODE_TEX_VOXEL_SPACE_OBJECT);
+ enm.insert("World", NODE_TEX_VOXEL_SPACE_WORLD);
+
+ return enm;
+}
+
+ShaderEnum PointDensityTextureNode::space_enum = point_density_space_init();
+
+PointDensityTextureNode::PointDensityTextureNode()
+: ShaderNode("point_density")
+{
+ image_manager = NULL;
+ slot = -1;
+ filename = "";
+ space = ustring("Object");
+ builtin_data = NULL;
+ interpolation = INTERPOLATION_LINEAR;
+
+ tfm = transform_identity();
+
+ add_input("Vector", SHADER_SOCKET_POINT, ShaderInput::POSITION);
+ add_output("Density", SHADER_SOCKET_FLOAT);
+ add_output("Color", SHADER_SOCKET_COLOR);
+}
+
+PointDensityTextureNode::~PointDensityTextureNode()
+{
+ if(image_manager)
+ image_manager->remove_image(filename, builtin_data, interpolation);
+}
+
+ShaderNode *PointDensityTextureNode::clone() const
+{
+ PointDensityTextureNode *node = new PointDensityTextureNode(*this);
+ node->image_manager = NULL;
+ node->slot = -1;
+ return node;
+}
+
+void PointDensityTextureNode::attributes(Shader *shader,
+ AttributeRequestSet *attributes)
+{
+ if(shader->has_volume)
+ attributes->add(ATTR_STD_GENERATED_TRANSFORM);
+
+ ShaderNode::attributes(shader, attributes);
+}
+
+void PointDensityTextureNode::compile(SVMCompiler& compiler)
+{
+ ShaderInput *vector_in = input("Vector");
+ ShaderOutput *density_out = output("Density");
+ ShaderOutput *color_out = output("Color");
+
+ bool use_density = !density_out->links.empty();
+ bool use_color = !color_out->links.empty();
+
+ image_manager = compiler.image_manager;
+
+ if (use_density || use_color) {
+ if (use_density)
+ compiler.stack_assign(density_out);
+ if (use_color)
+ compiler.stack_assign(color_out);
+
+ if(slot == -1) {
+ bool is_float, is_linear;
+ slot = image_manager->add_image(filename, builtin_data,
+ false, 0,
+ is_float, is_linear,
+ interpolation,
+ true);
+ }
+
+ if(slot != -1) {
+ compiler.stack_assign(vector_in);
+ compiler.add_node(NODE_TEX_VOXEL,
+ slot,
+ compiler.encode_uchar4(vector_in->stack_offset,
+ density_out->stack_offset,
+ color_out->stack_offset,
+ space_enum[space]));
+ if(space == "World") {
+ compiler.add_node(tfm.x);
+ compiler.add_node(tfm.y);
+ compiler.add_node(tfm.z);
+ compiler.add_node(tfm.w);
+ }
+ }
+ else {
+ compiler.add_node(NODE_VALUE_F,
+ __float_as_int(0.0f),
+ density_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, color_out->stack_offset);
+ compiler.add_node(NODE_VALUE_V, make_float3(TEX_IMAGE_MISSING_R,
+ TEX_IMAGE_MISSING_G,
+ TEX_IMAGE_MISSING_B));
+ }
+ }
+}
+
+void PointDensityTextureNode::compile(OSLCompiler& /*compiler*/)
+{
+ /* TODO(sergey): To be supported. */
+}
+
/* Normal */
NormalNode::NormalNode()
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index ac7bbaf3547..56d21716f3b 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -196,6 +196,29 @@ public:
int offset_frequency, squash_frequency;
};
+class PointDensityTextureNode : public ShaderNode {
+public:
+ SHADER_NODE_NO_CLONE_CLASS(PointDensityTextureNode)
+
+ ~PointDensityTextureNode();
+ ShaderNode *clone() const;
+ void attributes(Shader *shader, AttributeRequestSet *attributes);
+
+ bool has_spatial_varying() { return true; }
+ bool has_object_dependency() { return true; }
+
+ ImageManager *image_manager;
+ int slot;
+ string filename;
+ ustring space;
+ void *builtin_data;
+ InterpolationType interpolation;
+
+ Transform tfm;
+
+ static ShaderEnum space_enum;
+};
+
class MappingNode : public ShaderNode {
public:
SHADER_NODE_CLASS(MappingNode)
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index 19d715d834b..d0237919f89 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -43,7 +43,9 @@
CCL_NAMESPACE_BEGIN
-Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
+Scene::Scene(const SceneParams& params_,
+ const DeviceInfo& device_info_,
+ const bool free_data_after_update)
: params(params_)
{
device = NULL;
@@ -54,7 +56,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
film = new Film();
background = new Background();
light_manager = new LightManager();
- mesh_manager = new MeshManager();
+ mesh_manager = new MeshManager(free_data_after_update);
object_manager = new ObjectManager();
integrator = new Integrator();
image_manager = new ImageManager();
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 851e5ac0b72..f4980b3e0d3 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -128,6 +128,7 @@ public:
enum BVHType { BVH_DYNAMIC, BVH_STATIC } bvh_type;
bool use_bvh_cache;
bool use_bvh_spatial_split;
+ bool use_bvh_triangle_storage;
bool use_qbvh;
bool persistent_data;
@@ -137,6 +138,7 @@ public:
bvh_type = BVH_DYNAMIC;
use_bvh_cache = false;
use_bvh_spatial_split = false;
+ use_bvh_triangle_storage = true;
use_qbvh = false;
persistent_data = false;
}
@@ -146,6 +148,7 @@ public:
&& bvh_type == params.bvh_type
&& use_bvh_cache == params.use_bvh_cache
&& use_bvh_spatial_split == params.use_bvh_spatial_split
+ && use_bvh_triangle_storage == params.use_bvh_triangle_storage
&& use_qbvh == params.use_qbvh
&& persistent_data == params.persistent_data); }
};
@@ -194,7 +197,9 @@ public:
/* mutex must be locked manually by callers */
thread_mutex mutex;
- Scene(const SceneParams& params, const DeviceInfo& device_info);
+ Scene(const SceneParams& params,
+ const DeviceInfo& device_info,
+ const bool free_data_after_update = false);
~Scene();
void device_update(Device *device, Progress& progress);
diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h
index 08dbded176e..8fa7daaad79 100644
--- a/intern/smoke/extern/smoke_API.h
+++ b/intern/smoke/extern/smoke_API.h
@@ -74,7 +74,7 @@ size_t smoke_get_index2d(int x, int max_x, int y);
void smoke_dissolve(struct FLUID_3D *fluid, int speed, int log);
// wavelet turbulence functions
-struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors);
+struct WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors, int use_sim);
void smoke_turbulence_free(struct WTURBULENCE *wt);
void smoke_turbulence_step(struct WTURBULENCE *wt, struct FLUID_3D *fluid);
@@ -109,6 +109,7 @@ int smoke_has_colors(struct FLUID_3D *fluid);
int smoke_turbulence_has_fuel(struct WTURBULENCE *wt);
int smoke_turbulence_has_colors(struct WTURBULENCE *wt);
+void smoke_ensure_simulation(struct FLUID_3D *fluid, struct WTURBULENCE *wt);
void smoke_ensure_heat(struct FLUID_3D *fluid);
void smoke_ensure_fire(struct FLUID_3D *fluid, struct WTURBULENCE *wt);
void smoke_ensure_colors(struct FLUID_3D *fluid, struct WTURBULENCE *wt, float init_r, float init_g, float init_b);
diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp
index 3d712d2124a..2260057c0d2 100644
--- a/intern/smoke/intern/WTURBULENCE.cpp
+++ b/intern/smoke/intern/WTURBULENCE.cpp
@@ -51,8 +51,10 @@ static const float persistence = 0.56123f;
//////////////////////////////////////////////////////////////////////
// constructor
//////////////////////////////////////////////////////////////////////
-WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors)
+WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors, int init_sim)
{
+ _need_sim_data = init_sim != 0;
+
// if noise magnitude is below this threshold, its contribution
// is negilgible, so stop evaluating new octaves
_cullingThreshold = 1e-3;
@@ -87,11 +89,14 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
// allocate high resolution density field
_totalStepsBig = 0;
_densityBig = new float[_totalCellsBig];
- _densityBigOld = new float[_totalCellsBig];
-
- for(int i = 0; i < _totalCellsBig; i++) {
- _densityBig[i] =
- _densityBigOld[i] = 0.;
+ memset(_densityBig, 0, sizeof(*_densityBig) * _totalCellsBig);
+
+ if (_need_sim_data) {
+ _densityBigOld = new float[_totalCellsBig];
+ memset(_densityBigOld, 0, sizeof(*_densityBigOld) * _totalCellsBig);
+ }
+ else {
+ _densityBigOld = NULL;
}
/* fire */
@@ -112,7 +117,6 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
_tcU = new float[_totalCellsSm];
_tcV = new float[_totalCellsSm];
_tcW = new float[_totalCellsSm];
- _tcTemp = new float[_totalCellsSm];
// map all
const float dx = 1.0f/(float)(_resSm[0]);
@@ -126,29 +130,72 @@ WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int no
_tcU[index] = x*dx;
_tcV[index] = y*dy;
_tcW[index] = z*dz;
- _tcTemp[index] = 0.;
}
+ if (_need_sim_data) {
+ _tcTemp = new float[_totalCellsSm];
+ memset(_tcTemp, 0, sizeof(*_tcTemp) * _totalCellsSm);
+ }
+ else {
+ _tcTemp = NULL;
+ }
+
// noise tiles
_noiseTile = new float[noiseTileSize * noiseTileSize * noiseTileSize];
setNoise(noisetype, noisefile_path);
}
+void WTURBULENCE::initSimulation()
+{
+ if (_need_sim_data) {
+ return;
+ }
+
+ if(_densityBigOld == NULL) {
+ _densityBigOld = new float[_totalCellsBig];
+ memset(_densityBigOld, 0, sizeof(*_densityBigOld) * _totalCellsBig);
+ }
+
+ if (_tcTemp == NULL) {
+ _tcTemp = new float[_totalCellsSm];
+ memset(_tcTemp, 0, sizeof(*_tcTemp) * _totalCellsSm);
+ }
+
+ if (_fuelBig != NULL) {
+ if (_fuelBigOld == NULL) {
+ _fuelBigOld = new float[_totalCellsBig];
+ _reactBigOld = new float[_totalCellsBig];
+ memset(_fuelBigOld, 0, sizeof(*_fuelBigOld) * _totalCellsBig);
+ memset(_reactBigOld, 0, sizeof(*_reactBigOld) * _totalCellsBig);
+ }
+ }
+
+ if (_color_rBig != NULL) {
+ if (_color_rBigOld == NULL) {
+ _color_rBigOld = new float[_totalCellsBig];
+ _color_gBigOld = new float[_totalCellsBig];
+ _color_bBigOld = new float[_totalCellsBig];
+ memset(_color_rBigOld, 0, sizeof(*_color_rBigOld) * _totalCellsBig);
+ memset(_color_gBigOld, 0, sizeof(*_color_gBigOld) * _totalCellsBig);
+ memset(_color_bBigOld, 0, sizeof(*_color_bBigOld) * _totalCellsBig);
+ }
+ }
+}
+
void WTURBULENCE::initFire()
{
if (!_fuelBig) {
_flameBig = new float[_totalCellsBig];
_fuelBig = new float[_totalCellsBig];
- _fuelBigOld = new float[_totalCellsBig];
_reactBig = new float[_totalCellsBig];
- _reactBigOld = new float[_totalCellsBig];
-
- for(int i = 0; i < _totalCellsBig; i++) {
- _flameBig[i] =
- _fuelBig[i] =
- _fuelBigOld[i] = 0.;
- _reactBig[i] =
- _reactBigOld[i] = 0.;
+ memset(_flameBig, 0, sizeof(*_flameBig) * _totalCellsBig);
+ memset(_fuelBig, 0, sizeof(*_fuelBig) * _totalCellsBig);
+ memset(_reactBig, 0, sizeof(*_reactBig) * _totalCellsBig);
+ if (_need_sim_data) {
+ _fuelBigOld = new float[_totalCellsBig];
+ _reactBigOld = new float[_totalCellsBig];
+ memset(_fuelBigOld, 0, sizeof(*_fuelBigOld) * _totalCellsBig);
+ memset(_reactBigOld, 0, sizeof(*_reactBigOld) * _totalCellsBig);
}
}
}
@@ -157,19 +204,20 @@ void WTURBULENCE::initColors(float init_r, float init_g, float init_b)
{
if (!_color_rBig) {
_color_rBig = new float[_totalCellsBig];
- _color_rBigOld = new float[_totalCellsBig];
_color_gBig = new float[_totalCellsBig];
- _color_gBigOld = new float[_totalCellsBig];
_color_bBig = new float[_totalCellsBig];
- _color_bBigOld = new float[_totalCellsBig];
-
for(int i = 0; i < _totalCellsBig; i++) {
_color_rBig[i] = _densityBig[i] * init_r;
- _color_rBigOld[i] = 0.0f;
_color_gBig[i] = _densityBig[i] * init_g;
- _color_gBigOld[i] = 0.0f;
_color_bBig[i] = _densityBig[i] * init_b;
- _color_bBigOld[i] = 0.0f;
+ }
+ if (_need_sim_data) {
+ _color_rBigOld = new float[_totalCellsBig];
+ _color_gBigOld = new float[_totalCellsBig];
+ _color_bBigOld = new float[_totalCellsBig];
+ memset(_color_rBigOld, 0, sizeof(*_color_rBigOld) * _totalCellsBig);
+ memset(_color_gBigOld, 0, sizeof(*_color_gBigOld) * _totalCellsBig);
+ memset(_color_bBigOld, 0, sizeof(*_color_bBigOld) * _totalCellsBig);
}
}
}
@@ -179,7 +227,7 @@ void WTURBULENCE::initColors(float init_r, float init_g, float init_b)
//////////////////////////////////////////////////////////////////////
WTURBULENCE::~WTURBULENCE() {
delete[] _densityBig;
- delete[] _densityBigOld;
+ if (_densityBigOld) delete[] _densityBigOld;
if (_flameBig) delete[] _flameBig;
if (_fuelBig) delete[] _fuelBig;
if (_fuelBigOld) delete[] _fuelBigOld;
@@ -196,7 +244,7 @@ WTURBULENCE::~WTURBULENCE() {
delete[] _tcU;
delete[] _tcV;
delete[] _tcW;
- delete[] _tcTemp;
+ if (_tcTemp) delete[] _tcTemp;
delete[] _noiseTile;
}
diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h
index 36635325f62..fbc3e9eb8ba 100644
--- a/intern/smoke/intern/WTURBULENCE.h
+++ b/intern/smoke/intern/WTURBULENCE.h
@@ -36,11 +36,14 @@ struct WTURBULENCE
{
public:
// both config files can be NULL, altCfg might override values from noiseCfg
- WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors);
+ WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype, const char *noisefile_path, int init_fire, int init_colors, int init_sim);
/// destructor
virtual ~WTURBULENCE();
+ // Ensure data needed for simulation is allocated
+ void initSimulation();
+
void initFire();
void initColors(float init_r, float init_g, float init_b);
@@ -144,6 +147,8 @@ struct WTURBULENCE
void computeEigenvalues(float *_eigMin, float *_eigMax);
void decomposeEnergy(float *energy, float *_highFreqEnergy);
+
+ bool _need_sim_data;
};
#endif // WTURBULENCE_H
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index d79aaf76d56..28b39531b91 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -44,10 +44,10 @@ extern "C" FLUID_3D *smoke_init(int *res, float dx, float dtdef, int use_heat, i
return fluid;
}
-extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors)
+extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype, const char *noisefile_path, int use_fire, int use_colors, int use_sim)
{
if (amplify)
- return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, noisefile_path, use_fire, use_colors);
+ return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype, noisefile_path, use_fire, use_colors, use_sim);
else
return NULL;
}
@@ -480,6 +480,13 @@ extern "C" int smoke_turbulence_has_colors(WTURBULENCE *wt)
}
/* additional field initialization */
+extern "C" void smoke_ensure_simulation(FLUID_3D * /*fluid*/, WTURBULENCE *wt)
+{
+ if (wt) {
+ wt->initSimulation();
+ }
+}
+
extern "C" void smoke_ensure_heat(FLUID_3D *fluid)
{
if (fluid) {