Merged changes in the trunk up to revision 43748.

Conflicts resolved:
source/blender/editors/include/UI_resources.h
This commit is contained in:
2012-01-29 12:00:04 +00:00
231 changed files with 4605 additions and 1276 deletions

View File

@@ -1,6 +1,6 @@
""" """
Basic Physics Constraint Basic Physics Constraint
++++++++++++++++++++++ ++++++++++++++++++++++++
Example of how to create a hinge Physics Constraint between two objects. Example of how to create a hinge Physics Constraint between two objects.
""" """
from bge import logic from bge import logic

View File

@@ -1,6 +1,6 @@
""" """
Texture replacement Texture Replacement
++++++++++++++++++++++ +++++++++++++++++++
Example of how to replace a texture in game with an external image. Example of how to replace a texture in game with an external image.
createTexture() and removeTexture() are to be called from a module Python createTexture() and removeTexture() are to be called from a module Python
Controller. Controller.

View File

@@ -1,6 +1,6 @@
""" """
Basic Video Playback Basic Video Playback
++++++++++++++++++++++ ++++++++++++++++++++
Example of how to replace a texture in game with a video. It needs to run everyframe Example of how to replace a texture in game with a video. It needs to run everyframe
""" """
import bge import bge

View File

@@ -5,6 +5,11 @@ Physics Constraints (bge.constraints)
.. module:: bge.constraints .. module:: bge.constraints
.. literalinclude:: ../examples/bge.constraints.py .. literalinclude:: ../examples/bge.constraints.py
:language: rest
:lines: 2-4
.. literalinclude:: ../examples/bge.constraints.py
:lines: 6-
.. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]]) .. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]])

View File

@@ -77,6 +77,14 @@ Functions
:rtype: integer :rtype: integer
.. function:: setWindowSize(width, height)
Set the width and height of the window (in pixels). This also works for fullscreen applications.
:type width: integer
:type height: integer
.. function:: makeScreenshot(filename) .. function:: makeScreenshot(filename)
Writes a screenshot to the given filename. Writes a screenshot to the given filename.

View File

@@ -37,8 +37,18 @@ When the texture object is deleted, the new texture is deleted and the old textu
.. module:: bge.texture .. module:: bge.texture
.. literalinclude:: ../examples/bge.texture.py .. literalinclude:: ../examples/bge.texture.py
:language: rest
:lines: 2-4
.. literalinclude:: ../examples/bge.texture.py
:lines: 6-
.. literalinclude:: ../examples/bge.texture.1.py .. literalinclude:: ../examples/bge.texture.1.py
:language: rest
:lines: 2-6
.. literalinclude:: ../examples/bge.texture.1.py
:lines: 8-
.. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0]) .. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0])

View File

@@ -66,6 +66,12 @@ Game Types (bge.types)
:type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...} :type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
.. attribute:: active_events
A dictionary containing the status of only the active keyboard events or keys. (read-only).
:type: dictionary {:ref:`keycode<keyboard-keys>`::ref:`status<input-status>`, ...}
.. class:: SCA_PythonMouse(PyObjectPlus) .. class:: SCA_PythonMouse(PyObjectPlus)
The current mouse. The current mouse.
@@ -75,6 +81,12 @@ Game Types (bge.types)
a dictionary containing the status of each mouse event. (read-only). a dictionary containing the status of each mouse event. (read-only).
:type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...} :type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
.. attribute:: active_events
a dictionary containing the status of only the active mouse events. (read-only).
:type: dictionary {:ref:`keycode<mouse-keys>`::ref:`status<input-status>`, ...}
.. attribute:: position .. attribute:: position
@@ -942,7 +954,7 @@ Game Types (bge.types)
.. deprecated:: use :data:`localPosition` and :data:`worldPosition`. .. deprecated:: use :data:`localPosition` and :data:`worldPosition`.
:type: :class:`mathurils.Vector` :type: :class:`mathutils.Vector`
.. attribute:: orientation .. attribute:: orientation
@@ -980,7 +992,7 @@ Game Types (bge.types)
.. attribute:: worldScale .. attribute:: worldScale
The object's world scaling factor. Read-only. [sx, sy, sz] The object's world scaling factor. [sx, sy, sz]
:type: :class:`mathutils.Vector` :type: :class:`mathutils.Vector`
@@ -995,6 +1007,18 @@ Game Types (bge.types)
The object's world position. [x, y, z] The object's world position. [x, y, z]
:type: :class:`mathutils.Vector` :type: :class:`mathutils.Vector`
.. attribute:: localTransform
The object's local space transform matrix. 4x4 Matrix.
:type: :class:`mathutils.Matrix`
.. attribute:: worldTransform
The object's world space transform matrix. 4x4 Matrix.
:type: :class:`mathutils.Matrix`
.. attribute:: localLinearVelocity .. attribute:: localLinearVelocity

View File

@@ -2,14 +2,14 @@
/* src/config.h.in. Generated from configure.ac by autoheader. */ /* src/config.h.in. Generated from configure.ac by autoheader. */
/* Namespace for Google classes */ /* Namespace for Google classes */
#ifdef __APPLE__ #if defined(__APPLE__)
#include "config_mac.h" #include "config_mac.h"
#elif __FreeBSD__ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include "config_freebsd.h" #include "config_freebsd.h"
#elif __MINGW32__ #elif defined(__MINGW32__)
#include "windows/config.h" #include "windows/config.h"
#elif __GNUC__ #elif defined(__linux__)
#include "config_linux.h" #include "config_linux.h"
#elif _MSC_VER #elif defined(_MSC_VER)
#include "windows/config.h" #include "windows/config.h"
#endif #endif

View File

@@ -133,8 +133,10 @@
/* How to access the PC from a struct ucontext */ /* How to access the PC from a struct ucontext */
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) #if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__)
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP] #define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP]
#else #elif defined(_M_IX86) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
#define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_EIP] #define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_EIP]
#else
#undef PC_FROM_UCONTEXT
#endif #endif
/* Define to necessary symbol if this constant uses a non-standard name on /* Define to necessary symbol if this constant uses a non-standard name on

View File

@@ -8,6 +8,7 @@ incs += ' ../../source/blender/blenlib'
defs = [] defs = []
if not env['WITH_BF_CARVE']: if not env['WITH_BF_CARVE']:
import os
sources = env.Glob('intern/*.cpp') sources = env.Glob('intern/*.cpp')
sources.remove('intern' + os.sep + 'BOP_CarveInterface.cpp') sources.remove('intern' + os.sep + 'BOP_CarveInterface.cpp')
else: else:

View File

@@ -15,12 +15,13 @@
* along with this program; if not, write to the Free Software Foundation, * along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * The Original Code is Copyright (C) 2010 by the Blender Foundation.
* All rights reserved. * All rights reserved.
* *
* The Original Code is: all of this file. * The Original Code is: all of this file.
* *
* Contributor(s): none yet. * Contributor(s): Ken Hughes,
* Sergey Sharybin.
* *
* ***** END GPL LICENSE BLOCK ***** * ***** END GPL LICENSE BLOCK *****
*/ */
@@ -36,6 +37,9 @@
#include <carve/interpolator.hpp> #include <carve/interpolator.hpp>
#include <carve/rescale.hpp> #include <carve/rescale.hpp>
#include <iostream>
using namespace carve::mesh;
typedef unsigned int uint; typedef unsigned int uint;
#define MAX(x,y) ((x)>(y)?(x):(y)) #define MAX(x,y) ((x)>(y)?(x):(y))
@@ -61,10 +65,168 @@ static int isFacePlanar(CSG_IFace &face, std::vector<carve::geom3d::Vector> &ver
return 1; return 1;
} }
static carve::mesh::MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor& face_it, static MeshSet<3> *Carve_meshSetFromMeshes(std::vector<MeshSet<3>::mesh_t*> &meshes)
CSG_VertexIteratorDescriptor& vertex_it, {
carve::interpolate::FaceAttr<uint> &oface_num, std::vector<MeshSet<3>::mesh_t*> new_meshes;
uint &num_origfaces )
std::vector<MeshSet<3>::mesh_t*>::iterator it = meshes.begin();
for(; it!=meshes.end(); it++) {
MeshSet<3>::mesh_t *mesh = *it;
MeshSet<3>::mesh_t *new_mesh = new MeshSet<3>::mesh_t(mesh->faces);
new_meshes.push_back(new_mesh);
}
return new MeshSet<3>(new_meshes);
}
static void Carve_getIntersectedOperandMeshes(std::vector<MeshSet<3>::mesh_t*> &meshes,
std::vector<MeshSet<3>::aabb_t> &precomputedAABB,
MeshSet<3>::aabb_t &otherAABB,
std::vector<MeshSet<3>::mesh_t*> &operandMeshes)
{
std::vector<MeshSet<3>::mesh_t*>::iterator it = meshes.begin();
std::vector<MeshSet<3>::aabb_t>::iterator aabb_it = precomputedAABB.begin();
std::vector<MeshSet<3>::aabb_t> usedAABB;
while(it != meshes.end()) {
MeshSet<3>::mesh_t *mesh = *it;
MeshSet<3>::aabb_t aabb = mesh->getAABB();
bool isIntersect = false;
std::vector<MeshSet<3>::aabb_t>::iterator used_it = usedAABB.begin();
for(; used_it!=usedAABB.end(); used_it++) {
MeshSet<3>::aabb_t usedAABB = *used_it;
if(usedAABB.intersects(aabb) && usedAABB.intersects(otherAABB)) {
isIntersect = true;
break;
}
}
if(!isIntersect) {
operandMeshes.push_back(mesh);
usedAABB.push_back(aabb);
it = meshes.erase(it);
aabb_it = precomputedAABB.erase(aabb_it);
}
else {
it++;
aabb_it++;
}
}
}
static MeshSet<3> *Carve_getIntersectedOperand(std::vector<MeshSet<3>::mesh_t*> &meshes,
std::vector<MeshSet<3>::aabb_t> &precomputedAABB,
MeshSet<3>::aabb_t &otherAABB)
{
std::vector<MeshSet<3>::mesh_t*> operandMeshes;
Carve_getIntersectedOperandMeshes(meshes, precomputedAABB, otherAABB, operandMeshes);
return Carve_meshSetFromMeshes(operandMeshes);
}
static MeshSet<3> *Carve_unionIntersectingMeshes(MeshSet<3> *poly,
std::vector<MeshSet<3>::aabb_t> &precomputedAABB,
MeshSet<3>::aabb_t &otherAABB,
carve::interpolate::FaceAttr<uint> &oface_num)
{
if(poly->meshes.size()<=1)
return poly;
carve::csg::CSG csg;
oface_num.installHooks(csg);
csg.hooks.registerHook(new carve::csg::CarveTriangulator, carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
std::vector<MeshSet<3>::mesh_t*> orig_meshes =
std::vector<MeshSet<3>::mesh_t*>(poly->meshes.begin(), poly->meshes.end());
MeshSet<3> *left = Carve_getIntersectedOperand(orig_meshes, precomputedAABB, otherAABB);
while(orig_meshes.size()) {
MeshSet<3> *right = Carve_getIntersectedOperand(orig_meshes, precomputedAABB, otherAABB);
try {
if(left->meshes.size()==0) {
delete left;
left = right;
}
else {
MeshSet<3> *result = csg.compute(left, right, carve::csg::CSG::UNION, NULL, carve::csg::CSG::CLASSIFY_EDGE);
delete left;
delete right;
left = result;
}
}
catch(carve::exception e) {
std::cerr << "CSG failed, exception " << e.str() << std::endl;
delete right;
}
catch(...) {
delete left;
delete right;
throw "Unknown error in Carve library";
}
}
return left;
}
static MeshSet<3>::aabb_t Carve_computeAABB(MeshSet<3> *poly,
std::vector<MeshSet<3>::aabb_t> &precomputedAABB)
{
MeshSet<3>::aabb_t overallAABB;
std::vector<MeshSet<3>::mesh_t*>::iterator it = poly->meshes.begin();
for(; it!=poly->meshes.end(); it++) {
MeshSet<3>::aabb_t aabb;
MeshSet<3>::mesh_t *mesh = *it;
aabb = mesh->getAABB();
precomputedAABB.push_back(aabb);
overallAABB.unionAABB(aabb);
}
return overallAABB;
}
static void Carve_prepareOperands(MeshSet<3> **left_r, MeshSet<3> **right_r,
carve::interpolate::FaceAttr<uint> &oface_num)
{
MeshSet<3> *left, *right;
std::vector<MeshSet<3>::aabb_t> left_precomputedAABB;
std::vector<MeshSet<3>::aabb_t> right_precomputedAABB;
MeshSet<3>::aabb_t leftAABB = Carve_computeAABB(*left_r, left_precomputedAABB);
MeshSet<3>::aabb_t rightAABB = Carve_computeAABB(*right_r, right_precomputedAABB);
left = Carve_unionIntersectingMeshes(*left_r, left_precomputedAABB, rightAABB, oface_num);
right = Carve_unionIntersectingMeshes(*right_r, right_precomputedAABB, leftAABB, oface_num);
if(left != *left_r)
delete *left_r;
if(right != *right_r)
delete *right_r;
*left_r = left;
*right_r = right;
}
static MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor &face_it,
CSG_VertexIteratorDescriptor &vertex_it,
carve::interpolate::FaceAttr<uint> &oface_num,
uint &num_origfaces)
{ {
CSG_IVertex vertex; CSG_IVertex vertex;
std::vector<carve::geom3d::Vector> vertices; std::vector<carve::geom3d::Vector> vertices;
@@ -126,12 +288,12 @@ static carve::mesh::MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor& face_i
} }
} }
carve::mesh::MeshSet<3> *poly = new carve::mesh::MeshSet<3> (vertices, numfaces, f); MeshSet<3> *poly = new MeshSet<3> (vertices, numfaces, f);
uint i; uint i;
carve::mesh::MeshSet<3>::face_iter face_iter = poly->faceBegin(); MeshSet<3>::face_iter face_iter = poly->faceBegin();
for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) { for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) {
carve::mesh::MeshSet<3>::face_t *face = *face_iter; MeshSet<3>::face_t *face = *face_iter;
oface_num.setAttribute(face, forig[i]); oface_num.setAttribute(face, forig[i]);
} }
@@ -139,8 +301,8 @@ static carve::mesh::MeshSet<3> *Carve_addMesh(CSG_FaceIteratorDescriptor& face_i
} }
// check whether two faces share an edge, and if so merge them // check whether two faces share an edge, and if so merge them
static uint quadMerge(std::map<carve::mesh::MeshSet<3>::vertex_t*, uint> *vertexToIndex_map, static uint quadMerge(std::map<MeshSet<3>::vertex_t*, uint> *vertexToIndex_map,
carve::mesh::MeshSet<3>::face_t *f1, carve::mesh::MeshSet<3>::face_t *f2, MeshSet<3>::face_t *f1, MeshSet<3>::face_t *f2,
uint v, uint quad[4]) uint v, uint quad[4])
{ {
uint current, n1, p1, n2, p2; uint current, n1, p1, n2, p2;
@@ -188,23 +350,23 @@ static uint quadMerge(std::map<carve::mesh::MeshSet<3>::vertex_t*, uint> *vertex
return 0; return 0;
} }
static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::interpolate::FaceAttr<uint> &oface_num, static BSP_CSGMesh *Carve_exportMesh(MeshSet<3>* &poly, carve::interpolate::FaceAttr<uint> &oface_num,
uint num_origfaces) uint num_origfaces)
{ {
uint i; uint i;
BSP_CSGMesh* outputMesh = BSP_CSGMesh::New(); BSP_CSGMesh *outputMesh = BSP_CSGMesh::New();
if (outputMesh == NULL) if (outputMesh == NULL)
return NULL; return NULL;
std::vector<BSP_MVertex>* vertices = new std::vector<BSP_MVertex>; std::vector<BSP_MVertex> *vertices = new std::vector<BSP_MVertex>;
outputMesh->SetVertices(vertices); outputMesh->SetVertices(vertices);
std::map<carve::mesh::MeshSet<3>::vertex_t*, uint> vertexToIndex_map; std::map<MeshSet<3>::vertex_t*, uint> vertexToIndex_map;
std::vector<carve::mesh::MeshSet<3>::vertex_t>::iterator it = poly->vertex_storage.begin(); std::vector<MeshSet<3>::vertex_t>::iterator it = poly->vertex_storage.begin();
for (i = 0; it != poly->vertex_storage.end(); ++i, ++it) { for (i = 0; it != poly->vertex_storage.end(); ++i, ++it) {
carve::mesh::MeshSet<3>::vertex_t *vertex = &(*it); MeshSet<3>::vertex_t *vertex = &(*it);
vertexToIndex_map[vertex] = i; vertexToIndex_map[vertex] = i;
} }
@@ -217,13 +379,13 @@ static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::inte
} }
// build vectors of faces for each original face and each vertex // build vectors of faces for each original face and each vertex
std::vector< std::vector<uint> > vi(poly->vertex_storage.size()); std::vector<std::vector<uint> > vi(poly->vertex_storage.size());
std::vector< std::vector<uint> > ofaces(num_origfaces); std::vector<std::vector<uint> > ofaces(num_origfaces);
carve::mesh::MeshSet<3>::face_iter face_iter = poly->faceBegin(); MeshSet<3>::face_iter face_iter = poly->faceBegin();
for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) { for (i = 0; face_iter != poly->faceEnd(); ++face_iter, ++i) {
carve::mesh::MeshSet<3>::face_t *f = *face_iter; MeshSet<3>::face_t *f = *face_iter;
ofaces[oface_num.getAttribute(f)].push_back(i); ofaces[oface_num.getAttribute(f)].push_back(i);
carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
for (; edge_iter != f->end(); ++edge_iter) { for (; edge_iter != f->end(); ++edge_iter) {
int index = vertexToIndex_map[edge_iter->vert]; int index = vertexToIndex_map[edge_iter->vert];
vi[index].push_back(i); vi[index].push_back(i);
@@ -242,7 +404,7 @@ static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::inte
uint findex = fl.back(); uint findex = fl.back();
fl.pop_back(); fl.pop_back();
carve::mesh::MeshSet<3>::face_t *f = *(poly->faceBegin() + findex); MeshSet<3>::face_t *f = *(poly->faceBegin() + findex);
// add all information except vertices to the output mesh // add all information except vertices to the output mesh
outputMesh->FaceSet().push_back(BSP_MFace()); outputMesh->FaceSet().push_back(BSP_MFace());
@@ -256,7 +418,7 @@ static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::inte
// the original face // the original face
uint result = 0; uint result = 0;
carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
for (; edge_iter != f->end(); ++edge_iter) { for (; edge_iter != f->end(); ++edge_iter) {
int v = vertexToIndex_map[edge_iter->vert]; int v = vertexToIndex_map[edge_iter->vert];
for (uint pos2=0; !result && pos2 < vi[v].size();pos2++) { for (uint pos2=0; !result && pos2 < vi[v].size();pos2++) {
@@ -266,7 +428,7 @@ static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::inte
if (findex == otherf) if (findex == otherf)
continue; continue;
carve::mesh::MeshSet<3>::face_t *f2 = *(poly->faceBegin() + otherf); MeshSet<3>::face_t *f2 = *(poly->faceBegin() + otherf);
// if other face doesn't have the same original face, // if other face doesn't have the same original face,
// ignore it also // ignore it also
@@ -302,7 +464,7 @@ static BSP_CSGMesh* Carve_exportMesh(carve::mesh::MeshSet<3>* &poly, carve::inte
outFace.m_verts.push_back(quadverts[2]); outFace.m_verts.push_back(quadverts[2]);
outFace.m_verts.push_back(quadverts[3]); outFace.m_verts.push_back(quadverts[3]);
} else { } else {
carve::mesh::MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin(); MeshSet<3>::face_t::edge_iter_t edge_iter = f->begin();
for (; edge_iter != f->end(); ++edge_iter) { for (; edge_iter != f->end(); ++edge_iter) {
//int index = ofacevert_num.getAttribute(f, edge_iter.idx()); //int index = ofacevert_num.getAttribute(f, edge_iter.idx());
int index = vertexToIndex_map[edge_iter->vert]; int index = vertexToIndex_map[edge_iter->vert];
@@ -337,7 +499,7 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
CSG_VertexIteratorDescriptor obBVertices) CSG_VertexIteratorDescriptor obBVertices)
{ {
carve::csg::CSG::OP op; carve::csg::CSG::OP op;
carve::mesh::MeshSet<3> *left, *right, *output; MeshSet<3> *left, *right, *output = NULL;
carve::csg::CSG csg; carve::csg::CSG csg;
carve::geom3d::Vector min, max; carve::geom3d::Vector min, max;
carve::interpolate::FaceAttr<uint> oface_num; carve::interpolate::FaceAttr<uint> oface_num;
@@ -360,6 +522,19 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
left = Carve_addMesh(obAFaces, obAVertices, oface_num, num_origfaces ); left = Carve_addMesh(obAFaces, obAVertices, oface_num, num_origfaces );
right = Carve_addMesh(obBFaces, obBVertices, oface_num, num_origfaces ); right = Carve_addMesh(obBFaces, obBVertices, oface_num, num_origfaces );
Carve_prepareOperands(&left, &right, oface_num);
if(left->meshes.size() == 0 || right->meshes.size()==0) {
// normally sohuldn't happen (zero-faces objects are handled by modifier itself), but
// unioning intersecting meshes which doesn't have consistent normals might lead to
// empty result which wouldn't work here
delete left;
delete right;
return BOP_ERROR;
}
min.x = max.x = left->vertex_storage[0].v.x; min.x = max.x = left->vertex_storage[0].v.x;
min.y = max.y = left->vertex_storage[0].v.y; min.y = max.y = left->vertex_storage[0].v.y;
min.z = max.z = left->vertex_storage[0].v.z; min.z = max.z = left->vertex_storage[0].v.z;
@@ -390,13 +565,29 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
csg.hooks.registerHook(new carve::csg::CarveTriangulator, carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT); csg.hooks.registerHook(new carve::csg::CarveTriangulator, carve::csg::CSG::Hooks::PROCESS_OUTPUT_FACE_BIT);
oface_num.installHooks(csg); oface_num.installHooks(csg);
output = csg.compute( left, right, op, NULL, carve::csg::CSG::CLASSIFY_EDGE);
try {
output = csg.compute(left, right, op, NULL, carve::csg::CSG::CLASSIFY_EDGE);
}
catch(carve::exception e) {
std::cerr << "CSG failed, exception " << e.str() << std::endl;
}
catch(...) {
delete left;
delete right;
throw "Unknown error in Carve library";
}
delete left; delete left;
delete right; delete right;
if(!output)
return BOP_ERROR;
output->transform(rev_r); output->transform(rev_r);
*outputMesh = Carve_exportMesh( output, oface_num, num_origfaces); *outputMesh = Carve_exportMesh(output, oface_num, num_origfaces);
delete output; delete output;
return BOP_OK; return BOP_OK;

View File

@@ -462,6 +462,9 @@ static void xml_read_shader_graph(const XMLReadState& state, Shader *shader, pug
else if(string_iequals(node.name(), "gamma")) { else if(string_iequals(node.name(), "gamma")) {
snode = new GammaNode(); snode = new GammaNode();
} }
else if(string_iequals(node.name(), "brightness")) {
snode = new BrightContrastNode();
}
else if(string_iequals(node.name(), "combine_rgb")) { else if(string_iequals(node.name(), "combine_rgb")) {
snode = new CombineRGBNode(); snode = new CombineRGBNode();
} }

View File

@@ -183,6 +183,38 @@ class CyclesRender_PT_layers(CyclesButtonsPanel, Panel):
layout.separator() layout.separator()
split = layout.split()
col = split.column()
col.label(text="Passes:")
col.prop(rl, "use_pass_combined")
col.prop(rl, "use_pass_z")
col.prop(rl, "use_pass_normal")
col.prop(rl, "use_pass_object_index")
col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_emit")
col.prop(rl, "use_pass_environment")
col = split.column()
col.label()
col.label(text="Diffuse:")
row = col.row(align=True)
row.prop(rl, "use_pass_diffuse_direct", text="Direct", toggle=True)
row.prop(rl, "use_pass_diffuse_indirect", text="Indirect", toggle=True)
row.prop(rl, "use_pass_diffuse_color", text="Color", toggle=True)
col.label(text="Glossy:")
row = col.row(align=True)
row.prop(rl, "use_pass_glossy_direct", text="Direct", toggle=True)
row.prop(rl, "use_pass_glossy_indirect", text="Indirect", toggle=True)
row.prop(rl, "use_pass_glossy_color", text="Color", toggle=True)
col.label(text="Transmission:")
row = col.row(align=True)
row.prop(rl, "use_pass_transmission_direct", text="Direct", toggle=True)
row.prop(rl, "use_pass_transmission_indirect", text="Indirect", toggle=True)
row.prop(rl, "use_pass_transmission_color", text="Color", toggle=True)
layout.separator()
rl = rd.layers[0] rl = rd.layers[0]
layout.prop(rl, "material_override", text="Material") layout.prop(rl, "material_override", text="Material")
@@ -241,7 +273,7 @@ class CyclesCamera_PT_dof(CyclesButtonsPanel, Panel):
class Cycles_PT_context_material(CyclesButtonsPanel, Panel): class Cycles_PT_context_material(CyclesButtonsPanel, Panel):
bl_label = "Surface" bl_label = ""
bl_context = "material" bl_context = "material"
bl_options = {'HIDE_HEADER'} bl_options = {'HIDE_HEADER'}
@@ -337,16 +369,13 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
ob = context.object ob = context.object
visibility = ob.cycles_visibility visibility = ob.cycles_visibility
split = layout.split() flow = layout.column_flow()
col = split.column() flow.prop(visibility, "camera")
col.prop(visibility, "camera") flow.prop(visibility, "diffuse")
col.prop(visibility, "diffuse") flow.prop(visibility, "glossy")
col.prop(visibility, "glossy") flow.prop(visibility, "transmission")
flow.prop(visibility, "shadow")
col = split.column()
col.prop(visibility, "transmission")
col.prop(visibility, "shadow")
def find_node(material, nodetype): def find_node(material, nodetype):
@@ -473,17 +502,13 @@ class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
world = context.world world = context.world
cworld = world.cycles cworld = world.cycles
split = layout.split() col = layout.column()
col = split.column()
col.prop(cworld, "sample_as_light") col.prop(cworld, "sample_as_light")
row = col.row() row = col.row()
row.active = cworld.sample_as_light row.active = cworld.sample_as_light
row.prop(cworld, "sample_map_resolution") row.prop(cworld, "sample_map_resolution")
col = split.column()
col.label()
class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel): class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
bl_label = "Volume" bl_label = "Volume"
@@ -617,14 +642,9 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
col.template_ID(user, "texture", new="texture.new") col.template_ID(user, "texture", new="texture.new")
if tex: if tex:
row = split.row() split = layout.split(percentage=0.2)
row.prop(tex, "use_nodes", icon="NODETREE", text="") split.label(text="Type:")
row.label() split.prop(tex, "type", text="")
if not tex.use_nodes:
split = layout.split(percentage=0.2)
split.label(text="Type:")
split.prop(tex, "type", text="")
class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel): class CyclesTexture_PT_nodes(CyclesButtonsPanel, Panel):

View File

@@ -159,24 +159,26 @@ void BlenderSync::sync_background_light()
{ {
BL::World b_world = b_scene.world(); BL::World b_world = b_scene.world();
PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); if(b_world) {
bool sample_as_light = get_boolean(cworld, "sample_as_light"); PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
bool sample_as_light = get_boolean(cworld, "sample_as_light");
if(sample_as_light) { if(sample_as_light) {
/* test if we need to sync */ /* test if we need to sync */
Light *light; Light *light;
ObjectKey key(b_world, 0, b_world); ObjectKey key(b_world, 0, b_world);
if(light_map.sync(&light, b_world, b_world, key) || if(light_map.sync(&light, b_world, b_world, key) ||
world_recalc || world_recalc ||
b_world.ptr.data != world_map) b_world.ptr.data != world_map)
{ {
light->type = LIGHT_BACKGROUND; light->type = LIGHT_BACKGROUND;
light->map_resolution = get_int(cworld, "sample_map_resolution"); light->map_resolution = get_int(cworld, "sample_map_resolution");
light->shader = scene->default_background; light->shader = scene->default_background;
light->tag_update(scene); light->tag_update(scene);
light_map.set_recalc(b_world); light_map.set_recalc(b_world);
}
} }
} }
@@ -212,6 +214,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
/* object sync */ /* object sync */
if(object_updated || (object->mesh && object->mesh->need_update)) { if(object_updated || (object->mesh && object->mesh->need_update)) {
object->name = b_ob.name().c_str(); object->name = b_ob.name().c_str();
object->pass_id = b_ob.pass_index();
object->tfm = tfm; object->tfm = tfm;
/* visibility flags for both parent */ /* visibility flags for both parent */

View File

@@ -116,9 +116,68 @@ void BlenderSession::free_session()
delete session; delete session;
} }
static PassType get_pass_type(BL::RenderPass b_pass)
{
switch(b_pass.type()) {
case BL::RenderPass::type_COMBINED:
return PASS_COMBINED;
case BL::RenderPass::type_Z:
return PASS_DEPTH;
case BL::RenderPass::type_NORMAL:
return PASS_NORMAL;
case BL::RenderPass::type_OBJECT_INDEX:
return PASS_OBJECT_ID;
case BL::RenderPass::type_UV:
return PASS_UV;
case BL::RenderPass::type_MATERIAL_INDEX:
return PASS_MATERIAL_ID;
case BL::RenderPass::type_DIFFUSE_DIRECT:
return PASS_DIFFUSE_DIRECT;
case BL::RenderPass::type_GLOSSY_DIRECT:
return PASS_GLOSSY_DIRECT;
case BL::RenderPass::type_TRANSMISSION_DIRECT:
return PASS_TRANSMISSION_DIRECT;
case BL::RenderPass::type_DIFFUSE_INDIRECT:
return PASS_DIFFUSE_INDIRECT;
case BL::RenderPass::type_GLOSSY_INDIRECT:
return PASS_GLOSSY_INDIRECT;
case BL::RenderPass::type_TRANSMISSION_INDIRECT:
return PASS_TRANSMISSION_INDIRECT;
case BL::RenderPass::type_DIFFUSE_COLOR:
return PASS_DIFFUSE_COLOR;
case BL::RenderPass::type_GLOSSY_COLOR:
return PASS_GLOSSY_COLOR;
case BL::RenderPass::type_TRANSMISSION_COLOR:
return PASS_TRANSMISSION_COLOR;
case BL::RenderPass::type_EMIT:
return PASS_EMISSION;
case BL::RenderPass::type_ENVIRONMENT:
return PASS_BACKGROUND;
case BL::RenderPass::type_DIFFUSE:
case BL::RenderPass::type_SHADOW:
case BL::RenderPass::type_AO:
case BL::RenderPass::type_COLOR:
case BL::RenderPass::type_REFRACTION:
case BL::RenderPass::type_SPECULAR:
case BL::RenderPass::type_REFLECTION:
case BL::RenderPass::type_VECTOR:
case BL::RenderPass::type_MIST:
return PASS_NONE;
}
return PASS_NONE;
}
void BlenderSession::render() void BlenderSession::render()
{ {
/* get buffer parameters */ /* get buffer parameters */
SessionParams session_params = BlenderSync::get_session_params(b_userpref, b_scene, background);
BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height); BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, b_rv3d, width, height);
int w = buffer_params.width, h = buffer_params.height; int w = buffer_params.width, h = buffer_params.height;
@@ -143,6 +202,29 @@ void BlenderSession::render()
/* set layer */ /* set layer */
b_rlay = *b_iter; b_rlay = *b_iter;
/* add passes */
vector<Pass> passes;
Pass::add(PASS_COMBINED, passes);
if(session_params.device.advanced_shading) {
BL::RenderLayer::passes_iterator b_pass_iter;
for(b_rlay.passes.begin(b_pass_iter); b_pass_iter != b_rlay.passes.end(); ++b_pass_iter) {
BL::RenderPass b_pass(*b_pass_iter);
PassType pass_type = get_pass_type(b_pass);
if(pass_type != PASS_NONE)
Pass::add(pass_type, passes);
}
}
buffer_params.passes = passes;
scene->film->passes = passes;
scene->film->tag_update(scene);
/* update session */
session->reset(buffer_params, session_params.samples);
/* update scene */ /* update scene */
sync->sync_data(b_v3d, active); sync->sync_data(b_v3d, active);
@@ -165,22 +247,41 @@ void BlenderSession::write_render_result()
{ {
/* get state */ /* get state */
RenderBuffers *buffers = session->buffers; RenderBuffers *buffers = session->buffers;
/* copy data from device */
if(!buffers->copy_from_device())
return;
BufferParams& params = buffers->params;
float exposure = scene->film->exposure; float exposure = scene->film->exposure;
double total_time, sample_time; double total_time, sample_time;
int sample; int sample;
session->progress.get_sample(sample, total_time, sample_time); session->progress.get_sample(sample, total_time, sample_time);
/* get pixels */ vector<float> pixels(params.width*params.height*4);
float4 *pixels = buffers->copy_from_device(exposure, sample);
if(!pixels) /* copy each pass */
return; BL::RenderLayer::passes_iterator b_iter;
for(b_rlay.passes.begin(b_iter); b_iter != b_rlay.passes.end(); ++b_iter) {
BL::RenderPass b_pass(*b_iter);
/* write pixels */ /* find matching pass type */
rna_RenderLayer_rect_set(&b_rlay.ptr, (float*)pixels); PassType pass_type = get_pass_type(b_pass);
int components = b_pass.channels();
/* copy pixels */
if(buffers->get_pass(pass_type, exposure, sample, components, &pixels[0]))
rna_RenderPass_rect_set(&b_pass.ptr, &pixels[0]);
}
/* copy combined pass */
if(buffers->get_pass(PASS_COMBINED, exposure, sample, 4, &pixels[0]))
rna_RenderLayer_rect_set(&b_rlay.ptr, &pixels[0]);
/* tag result as updated */
RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data); RE_engine_update_result((RenderEngine*)b_engine.ptr.data, (RenderResult*)b_rr.ptr.data);
delete [] pixels;
} }
void BlenderSession::synchronize() void BlenderSession::synchronize()

View File

@@ -142,6 +142,10 @@ static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Shader
node = new GammaNode(); node = new GammaNode();
break; break;
} }
case BL::ShaderNode::type_BRIGHTCONTRAST: {
node = new BrightContrastNode();
break;
}
case BL::ShaderNode::type_MIX_RGB: { case BL::ShaderNode::type_MIX_RGB: {
BL::ShaderNodeMixRGB b_mix_node(b_node); BL::ShaderNodeMixRGB b_mix_node(b_node);
MixNode *mix = new MixNode(); MixNode *mix = new MixNode();
@@ -632,6 +636,7 @@ void BlenderSync::sync_materials()
ShaderGraph *graph = new ShaderGraph(); ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat->name().c_str(); shader->name = b_mat->name().c_str();
shader->pass_id = b_mat->pass_index();
/* create nodes */ /* create nodes */
if(b_mat->use_nodes() && b_mat->node_tree()) { if(b_mat->use_nodes() && b_mat->node_tree()) {

View File

@@ -183,6 +183,9 @@ Device *Device::create(DeviceInfo& info, bool background, int threads)
return NULL; return NULL;
} }
if(device)
device->info = info;
return device; return device;
} }

View File

@@ -51,6 +51,7 @@ public:
string id; string id;
int num; int num;
bool display_device; bool display_device;
bool advanced_shading;
vector<DeviceInfo> multi_devices; vector<DeviceInfo> multi_devices;
DeviceInfo() DeviceInfo()
@@ -59,6 +60,7 @@ public:
id = "CPU"; id = "CPU";
num = 0; num = 0;
display_device = false; display_device = false;
advanced_shading = true;
} }
}; };
@@ -101,10 +103,8 @@ protected:
public: public:
virtual ~Device() {} virtual ~Device() {}
virtual bool support_full_kernel() = 0;
/* info */ /* info */
virtual string description() = 0; DeviceInfo info;
virtual const string& error_message() { return error_msg; } virtual const string& error_message() { return error_msg; }
/* regular memory */ /* regular memory */

View File

@@ -72,16 +72,11 @@ public:
kernel_globals_free(kg); kernel_globals_free(kg);
} }
bool support_full_kernel() bool support_advanced_shading()
{ {
return true; return true;
} }
string description()
{
return system_cpu_brand_string();
}
void mem_alloc(device_memory& mem, MemoryType type) void mem_alloc(device_memory& mem, MemoryType type)
{ {
mem.device_pointer = mem.data_pointer; mem.device_pointer = mem.data_pointer;
@@ -162,7 +157,7 @@ public:
if(system_cpu_support_optimized()) { if(system_cpu_support_optimized()) {
for(int y = task.y; y < task.y + task.h; y++) { for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++) for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_optimized_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, kernel_cpu_optimized_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
task.sample, x, y, task.offset, task.stride); task.sample, x, y, task.offset, task.stride);
if(tasks.worker_cancel()) if(tasks.worker_cancel())
@@ -174,7 +169,7 @@ public:
{ {
for(int y = task.y; y < task.y + task.h; y++) { for(int y = task.y; y < task.y + task.h; y++) {
for(int x = task.x; x < task.x + task.w; x++) for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_path_trace(kg, (float4*)task.buffer, (unsigned int*)task.rng_state, kernel_cpu_path_trace(kg, (float*)task.buffer, (unsigned int*)task.rng_state,
task.sample, x, y, task.offset, task.stride); task.sample, x, y, task.offset, task.stride);
if(tasks.worker_cancel()) if(tasks.worker_cancel())
@@ -194,7 +189,7 @@ public:
if(system_cpu_support_optimized()) { if(system_cpu_support_optimized()) {
for(int y = task.y; y < task.y + task.h; y++) for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++) for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_optimized_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, kernel_cpu_optimized_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer,
task.sample, task.resolution, x, y, task.offset, task.stride); task.sample, task.resolution, x, y, task.offset, task.stride);
} }
else else
@@ -202,7 +197,7 @@ public:
{ {
for(int y = task.y; y < task.y + task.h; y++) for(int y = task.y; y < task.y + task.h; y++)
for(int x = task.x; x < task.x + task.w; x++) for(int x = task.x; x < task.x + task.w; x++)
kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float4*)task.buffer, kernel_cpu_tonemap(kg, (uchar4*)task.rgba, (float*)task.buffer,
task.sample, task.resolution, x, y, task.offset, task.stride); task.sample, task.resolution, x, y, task.offset, task.stride);
} }
} }
@@ -271,6 +266,7 @@ void device_cpu_info(vector<DeviceInfo>& devices)
info.description = system_cpu_brand_string(); info.description = system_cpu_brand_string();
info.id = "CPU"; info.id = "CPU";
info.num = 0; info.num = 0;
info.advanced_shading = true;
devices.insert(devices.begin(), info); devices.insert(devices.begin(), info);
} }

View File

@@ -106,11 +106,6 @@ public:
} }
} }
static int cuda_align_up(int& offset, int alignment)
{
return (offset + alignment - 1) & ~(alignment - 1);
}
#ifdef NDEBUG #ifdef NDEBUG
#define cuda_abort() #define cuda_abort()
#else #else
@@ -194,26 +189,6 @@ public:
cuda_assert(cuCtxDetach(cuContext)) cuda_assert(cuCtxDetach(cuContext))
} }
bool support_full_kernel()
{
int major, minor;
cuDeviceComputeCapability(&major, &minor, cuDevId);
return (major >= 2);
}
string description()
{
/* print device information */
char deviceName[256];
cuda_push_context();
cuDeviceGetName(deviceName, 256, cuDevId);
cuda_pop_context();
return string("CUDA ") + deviceName;
}
bool support_device(bool experimental) bool support_device(bool experimental)
{ {
if(!experimental) { if(!experimental) {
@@ -505,7 +480,7 @@ public:
offset += sizeof(d_rng_state); offset += sizeof(d_rng_state);
int sample = task.sample; int sample = task.sample;
offset = cuda_align_up(offset, __alignof(sample)); offset = align_up(offset, __alignof(sample));
cuda_assert(cuParamSeti(cuPathTrace, offset, task.sample)) cuda_assert(cuParamSeti(cuPathTrace, offset, task.sample))
offset += sizeof(task.sample); offset += sizeof(task.sample);
@@ -569,7 +544,7 @@ public:
offset += sizeof(d_buffer); offset += sizeof(d_buffer);
int sample = task.sample; int sample = task.sample;
offset = cuda_align_up(offset, __alignof(sample)); offset = align_up(offset, __alignof(sample));
cuda_assert(cuParamSeti(cuFilmConvert, offset, task.sample)) cuda_assert(cuParamSeti(cuFilmConvert, offset, task.sample))
offset += sizeof(task.sample); offset += sizeof(task.sample);
@@ -638,7 +613,7 @@ public:
offset += sizeof(d_offset); offset += sizeof(d_offset);
int shader_eval_type = task.shader_eval_type; int shader_eval_type = task.shader_eval_type;
offset = cuda_align_up(offset, __alignof(shader_eval_type)); offset = align_up(offset, __alignof(shader_eval_type));
cuda_assert(cuParamSeti(cuDisplace, offset, task.shader_eval_type)) cuda_assert(cuParamSeti(cuDisplace, offset, task.shader_eval_type))
offset += sizeof(task.shader_eval_type); offset += sizeof(task.shader_eval_type);
@@ -881,6 +856,10 @@ void device_cuda_info(vector<DeviceInfo>& devices)
info.id = string_printf("CUDA_%d", num); info.id = string_printf("CUDA_%d", num);
info.num = num; info.num = num;
int major, minor;
cuDeviceComputeCapability(&major, &minor, num);
info.advanced_shading = (major >= 2);
/* if device has a kernel timeout, assume it is used for display */ /* if device has a kernel timeout, assume it is used for display */
if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) { if(cuDeviceGetAttribute(&attr, CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT, num) == CUDA_SUCCESS && attr == 1) {
info.display_device = true; info.display_device = true;

View File

@@ -76,16 +76,6 @@ public:
delete sub.device; delete sub.device;
} }
bool support_full_kernel()
{
foreach(SubDevice& sub, devices) {
if(!sub.device->support_full_kernel())
return false;
}
return true;
}
const string& error_message() const string& error_message()
{ {
foreach(SubDevice& sub, devices) { foreach(SubDevice& sub, devices) {
@@ -99,38 +89,6 @@ public:
return error_msg; return error_msg;
} }
string description()
{
/* create map to find duplicate descriptions */
map<string, int> dupli_map;
map<string, int>::iterator dt;
foreach(SubDevice& sub, devices) {
string key = sub.device->description();
if(dupli_map.find(key) == dupli_map.end())
dupli_map[key] = 1;
else
dupli_map[key]++;
}
/* generate string */
stringstream desc;
bool first = true;
for(dt = dupli_map.begin(); dt != dupli_map.end(); dt++) {
if(!first) desc << ", ";
first = false;
if(dt->second > 1)
desc << dt->second << "x " << dt->first;
else
desc << dt->first;
}
return desc.str();
}
bool load_kernels(bool experimental) bool load_kernels(bool experimental)
{ {
foreach(SubDevice& sub, devices) foreach(SubDevice& sub, devices)
@@ -344,6 +302,8 @@ static void device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool
map<string, int>::iterator dt; map<string, int>::iterator dt;
int num_added = 0, num_display = 0; int num_added = 0, num_display = 0;
info.advanced_shading = true;
foreach(DeviceInfo& subinfo, devices) { foreach(DeviceInfo& subinfo, devices) {
if(subinfo.type == type) { if(subinfo.type == type) {
if(subinfo.display_device) { if(subinfo.display_device) {
@@ -363,6 +323,8 @@ static void device_multi_add(vector<DeviceInfo>& devices, DeviceType type, bool
info.multi_devices.push_back(subinfo); info.multi_devices.push_back(subinfo);
if(subinfo.display_device) if(subinfo.display_device)
info.display_device = true; info.display_device = true;
if(!subinfo.advanced_shading)
info.advanced_shading = false;
num_added++; num_added++;
} }
} }

View File

@@ -57,24 +57,6 @@ public:
{ {
} }
bool support_full_kernel()
{
return false;
}
string description()
{
RPCSend snd(socket, "description");
snd.write();
RPCReceive rcv(socket);
string desc_string;
*rcv.archive & desc_string;
return desc_string + " (remote)";
}
void mem_alloc(device_memory& mem, MemoryType type) void mem_alloc(device_memory& mem, MemoryType type)
{ {
#if 0 #if 0

View File

@@ -453,20 +453,6 @@ public:
clReleaseContext(cxContext); clReleaseContext(cxContext);
} }
bool support_full_kernel()
{
return false;
}
string description()
{
char name[1024];
clGetDeviceInfo(cdDevice, CL_DEVICE_NAME, sizeof(name), &name, NULL);
return string("OpenCL ") + name;
}
void mem_alloc(device_memory& mem, MemoryType type) void mem_alloc(device_memory& mem, MemoryType type)
{ {
size_t size = mem.memory_size(); size_t size = mem.memory_size();
@@ -750,6 +736,7 @@ void device_opencl_info(vector<DeviceInfo>& devices)
info.num = num; info.num = num;
/* we don't know if it's used for display, but assume it is */ /* we don't know if it's used for display, but assume it is */
info.display_device = true; info.display_device = true;
info.advanced_shading = false;
devices.push_back(info); devices.push_back(info);
} }

View File

@@ -15,6 +15,7 @@ set(SRC
set(SRC_HEADERS set(SRC_HEADERS
kernel.h kernel.h
kernel_accumulate.h
kernel_bvh.h kernel_bvh.h
kernel_camera.h kernel_camera.h
kernel_compat_cpu.h kernel_compat_cpu.h
@@ -30,6 +31,7 @@ set(SRC_HEADERS
kernel_mbvh.h kernel_mbvh.h
kernel_montecarlo.h kernel_montecarlo.h
kernel_object.h kernel_object.h
kernel_passes.h
kernel_path.h kernel_path.h
kernel_qbvh.h kernel_qbvh.h
kernel_random.h kernel_random.h
@@ -61,6 +63,7 @@ set(SRC_SVM_HEADERS
svm/svm_displace.h svm/svm_displace.h
svm/svm_fresnel.h svm/svm_fresnel.h
svm/svm_gamma.h svm/svm_gamma.h
svm/svm_brightness.h
svm/svm_geometry.h svm/svm_geometry.h
svm/svm_gradient.h svm/svm_gradient.h
svm/svm_hsv.h svm/svm_hsv.h

View File

@@ -28,7 +28,7 @@
__kernel void kernel_ocl_path_trace( __kernel void kernel_ocl_path_trace(
__constant KernelData *data, __constant KernelData *data,
__global float4 *buffer, __global float *buffer,
__global uint *rng_state, __global uint *rng_state,
#define KERNEL_TEX(type, ttype, name) \ #define KERNEL_TEX(type, ttype, name) \
@@ -56,7 +56,7 @@ __kernel void kernel_ocl_path_trace(
__kernel void kernel_ocl_tonemap( __kernel void kernel_ocl_tonemap(
__constant KernelData *data, __constant KernelData *data,
__global uchar4 *rgba, __global uchar4 *rgba,
__global float4 *buffer, __global float *buffer,
#define KERNEL_TEX(type, ttype, name) \ #define KERNEL_TEX(type, ttype, name) \
__global type *name, __global type *name,

View File

@@ -204,14 +204,14 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
/* Path Tracing */ /* Path Tracing */
void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride) void kernel_cpu_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
{ {
kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride); kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
} }
/* Tonemapping */ /* Tonemapping */
void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y, int offset, int stride) void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer, int sample, int resolution, int x, int y, int offset, int stride)
{ {
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
} }

View File

@@ -26,7 +26,7 @@
#include "kernel_path.h" #include "kernel_path.h"
#include "kernel_displace.h" #include "kernel_displace.h"
extern "C" __global__ void kernel_cuda_path_trace(float4 *buffer, uint *rng_state, int sample, int sx, int sy, int sw, int sh, int offset, int stride) extern "C" __global__ void kernel_cuda_path_trace(float *buffer, uint *rng_state, int sample, int sx, int sy, int sw, int sh, int offset, int stride)
{ {
int x = sx + blockDim.x*blockIdx.x + threadIdx.x; int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y; int y = sy + blockDim.y*blockIdx.y + threadIdx.y;
@@ -35,7 +35,7 @@ extern "C" __global__ void kernel_cuda_path_trace(float4 *buffer, uint *rng_stat
kernel_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride); kernel_path_trace(NULL, buffer, rng_state, sample, x, y, offset, stride);
} }
extern "C" __global__ void kernel_cuda_tonemap(uchar4 *rgba, float4 *buffer, int sample, int resolution, int sx, int sy, int sw, int sh, int offset, int stride) extern "C" __global__ void kernel_cuda_tonemap(uchar4 *rgba, float *buffer, int sample, int resolution, int sx, int sy, int sw, int sh, int offset, int stride)
{ {
int x = sx + blockDim.x*blockIdx.x + threadIdx.x; int x = sx + blockDim.x*blockIdx.x + threadIdx.x;
int y = sy + blockDim.y*blockIdx.y + threadIdx.y; int y = sy + blockDim.y*blockIdx.y + threadIdx.y;

View File

@@ -36,17 +36,17 @@ bool kernel_osl_use(KernelGlobals *kg);
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size); void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size);
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height); void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height);
void kernel_cpu_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, void kernel_cpu_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
int sample, int x, int y, int offset, int stride); int sample, int x, int y, int offset, int stride);
void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, void kernel_cpu_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer,
int sample, int resolution, int x, int y, int offset, int stride); int sample, int resolution, int x, int y, int offset, int stride);
void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output, void kernel_cpu_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i); int type, int i);
#ifdef WITH_OPTIMIZED_KERNEL #ifdef WITH_OPTIMIZED_KERNEL
void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
int sample, int x, int y, int offset, int stride); int sample, int x, int y, int offset, int stride);
void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer,
int sample, int resolution, int x, int y, int offset, int stride); int sample, int resolution, int x, int y, int offset, int stride);
void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float4 *output, void kernel_cpu_optimized_shader(KernelGlobals *kg, uint4 *input, float4 *output,
int type, int i); int type, int i);

View File

@@ -0,0 +1,283 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CCL_NAMESPACE_BEGIN
/* BSDF Eval
*
* BSDF evaluation result, split per BSDF type. This is used to accumulate
* render passes separately. */
__device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
{
#ifdef __PASSES__
eval->use_light_pass = use_light_pass;
if(eval->use_light_pass) {
eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
if(type == CLOSURE_BSDF_TRANSPARENT_ID)
eval->transparent = value;
else if(CLOSURE_IS_BSDF_DIFFUSE(type))
eval->diffuse = value;
else if(CLOSURE_IS_BSDF_GLOSSY(type))
eval->glossy = value;
else
eval->transmission = value;
}
else
eval->diffuse = value;
#else
*eval = value;
#endif
}
__device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
if(CLOSURE_IS_BSDF_DIFFUSE(type))
eval->diffuse += value;
else if(CLOSURE_IS_BSDF_GLOSSY(type))
eval->glossy += value;
else
eval->transmission += value;
/* skipping transparent, this function is used by for eval(), will be zero then */
}
else
eval->diffuse += value;
#else
*eval += value;
#endif
}
__device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
return is_zero(eval->diffuse)
&& is_zero(eval->glossy)
&& is_zero(eval->transmission)
&& is_zero(eval->transparent);
}
else
return is_zero(eval->diffuse);
#else
return is_zero(*eval);
#endif
}
__device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
{
#ifdef __PASSES__
if(eval->use_light_pass) {
eval->diffuse *= value;
eval->glossy *= value;
eval->transmission *= value;
/* skipping transparent, this function is used by for eval(), will be zero then */
}
else
eval->diffuse *= value;
#else
*eval *= value;
#endif
}
/* Path Radiance
*
* We accumulate different render passes separately. After summing at the end
* to get the combined result, it should be identical. We definte directly
* visible as the first non-transparent hit, while indirectly visible are the
* bounces after that. */
__device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
{
/* clear all */
#ifdef __PASSES__
L->use_light_pass = use_light_pass;
if(use_light_pass) {
L->indirect = make_float3(0.0f, 0.0f, 0.0f);
L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
L->emission = make_float3(0.0f, 0.0f, 0.0f);
L->background = make_float3(0.0f, 0.0f, 0.0f);
}
else
L->emission = make_float3(0.0f, 0.0f, 0.0f);
#else
*L = make_float3(0.0f, 0.0f, 0.0f);
#endif
}
__device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput,
BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
{
float inverse_pdf = 1.0f/bsdf_pdf;
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0) {
if(bsdf_label & LABEL_TRANSPARENT) {
/* transparent bounce before first hit */
*throughput *= bsdf_eval->transparent*inverse_pdf;
}
else {
/* first on directly visible surface */
float3 value = *throughput*inverse_pdf;
L->indirect_diffuse = bsdf_eval->diffuse*value;
L->indirect_glossy = bsdf_eval->glossy*value;
L->indirect_transmission = bsdf_eval->transmission*value;
*throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
L->direct_throughput = *throughput;
}
}
else {
/* indirectly visible through BSDF */
float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent)*inverse_pdf;
*throughput *= sum;
}
}
else
*throughput *= bsdf_eval->diffuse*inverse_pdf;
#else
*throughput *= *bsdf_eval*inverse_pdf;
#endif
}
__device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
{
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0)
L->emission += throughput*value;
else if(bounce == 1)
L->direct_emission += throughput*value;
else
L->indirect += throughput*value;
}
else
L->emission += throughput*value;
#else
*L += throughput*value;
#endif
}
__device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, int bounce)
{
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0) {
/* directly visible lighting */
L->direct_diffuse += throughput*bsdf_eval->diffuse;
L->direct_glossy += throughput*bsdf_eval->glossy;
L->direct_transmission += throughput*bsdf_eval->transmission;
}
else {
/* indirectly visible lighting after BSDF bounce */
float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission;
L->indirect += throughput*sum;
}
}
else
L->emission += throughput*bsdf_eval->diffuse;
#else
*L += throughput*(*bsdf_eval);
#endif
}
__device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
{
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0)
L->background += throughput*value;
else if(bounce == 1)
L->direct_emission += throughput*value;
else
L->indirect += throughput*value;
}
else
L->emission += throughput*value;
#else
*L += throughput*value;
#endif
}
__device_inline float3 safe_divide_color(float3 a, float3 b)
{
float x, y, z;
x = (b.x != 0.0f)? a.x/b.x: 0.0f;
y = (b.y != 0.0f)? a.y/b.y: 0.0f;
z = (b.z != 0.0f)? a.z/b.z: 0.0f;
return make_float3(x, y, z);
}
__device_inline float3 path_radiance_sum(PathRadiance *L)
{
#ifdef __PASSES__
if(L->use_light_pass) {
/* this division is a bit ugly, but means we only have to keep track of
only a single throughput further along the path, here we recover just
the indirect parth that is not influenced by any particular BSDF type */
L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
L->direct_diffuse += L->indirect_diffuse*L->direct_emission;
L->direct_glossy += L->indirect_glossy*L->direct_emission;
L->direct_transmission += L->indirect_transmission*L->direct_emission;
L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
L->indirect_diffuse *= L->indirect;
L->indirect_glossy *= L->indirect;
L->indirect_transmission *= L->indirect;
return L->emission + L->background
+ L->direct_diffuse + L->direct_glossy + L->direct_transmission
+ L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
}
else
return L->emission;
#else
return *L;
#endif
}
CCL_NAMESPACE_END

View File

@@ -27,6 +27,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
ShaderData sd; ShaderData sd;
float3 eval; float3 eval;
#ifdef __BACKGROUND_MIS__
if(ls->type == LIGHT_BACKGROUND) { if(ls->type == LIGHT_BACKGROUND) {
Ray ray; Ray ray;
ray.D = ls->D; ray.D = ls->D;
@@ -36,7 +37,9 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
shader_setup_from_background(kg, &sd, &ray); shader_setup_from_background(kg, &sd, &ray);
eval = shader_eval_background(kg, &sd, 0); eval = shader_eval_background(kg, &sd, 0);
} }
else { else
#endif
{
shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v); shader_setup_from_sample(kg, &sd, ls->P, ls->Ng, I, ls->shader, ls->object, ls->prim, u, v);
ls->Ng = sd.Ng; ls->Ng = sd.Ng;
@@ -57,7 +60,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando,
} }
__device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex, __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
float randt, float rando, float randu, float randv, Ray *ray, float3 *eval) float randt, float rando, float randu, float randv, Ray *ray, BsdfEval *eval)
{ {
LightSample ls; LightSample ls;
@@ -83,32 +86,33 @@ __device bool direct_emission(KernelGlobals *kg, ShaderData *sd, int lindex,
return false; return false;
/* evaluate closure */ /* evaluate closure */
*eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D); float3 light_eval = direct_emissive_eval(kg, rando, &ls, randu, randv, -ls.D);
if(is_zero(*eval)) if(is_zero(light_eval))
return false; return false;
/* todo: use visbility flag to skip lights */ /* todo: use visbility flag to skip lights */
/* evaluate BSDF at shading point */ /* evaluate BSDF at shading point */
float bsdf_pdf; float bsdf_pdf;
float3 bsdf_eval = shader_bsdf_eval(kg, sd, ls.D, &bsdf_pdf);
*eval *= bsdf_eval/pdf; shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf);
if(is_zero(*eval))
return false;
if(ls.prim != ~0 || ls.type == LIGHT_BACKGROUND) { if(ls.prim != ~0 || ls.type == LIGHT_BACKGROUND) {
/* multiple importance sampling */ /* multiple importance sampling */
float mis_weight = power_heuristic(pdf, bsdf_pdf); float mis_weight = power_heuristic(pdf, bsdf_pdf);
*eval *= mis_weight; light_eval *= mis_weight;
} }
/* todo: clean up these weights */ /* todo: clean up these weights */
else if(ls.shader & SHADER_AREA_LIGHT) else if(ls.shader & SHADER_AREA_LIGHT)
*eval *= 0.25f; /* area lamp */ light_eval *= 0.25f; /* area lamp */
else if(ls.t != FLT_MAX) else if(ls.t != FLT_MAX)
*eval *= 0.25f*M_1_PI_F; /* point lamp */ light_eval *= 0.25f*M_1_PI_F; /* point lamp */
bsdf_eval_mul(eval, light_eval/pdf);
if(bsdf_eval_is_zero(eval))
return false;
if(ls.shader & SHADER_CAST_SHADOW) { if(ls.shader & SHADER_CAST_SHADOW) {
/* setup ray */ /* setup ray */
@@ -163,6 +167,7 @@ __device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag,
float3 L = shader_eval_background(kg, &sd, path_flag); float3 L = shader_eval_background(kg, &sd, path_flag);
shader_release(kg, &sd); shader_release(kg, &sd);
#ifdef __BACKGROUND_MIS__
/* check if background light exists or if we should skip pdf */ /* check if background light exists or if we should skip pdf */
int res = kernel_data.integrator.pdf_background_res; int res = kernel_data.integrator.pdf_background_res;
@@ -174,6 +179,7 @@ __device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag,
return L*mis_weight; return L*mis_weight;
} }
#endif
return L; return L;
#else #else

View File

@@ -48,15 +48,22 @@ __device uchar4 film_float_to_byte(float4 color)
return result; return result;
} }
__device void kernel_film_tonemap(KernelGlobals *kg, __global uchar4 *rgba, __global float4 *buffer, int sample, int resolution, int x, int y, int offset, int stride) __device void kernel_film_tonemap(KernelGlobals *kg,
__global uchar4 *rgba, __global float *buffer,
int sample, int resolution, int x, int y, int offset, int stride)
{ {
/* buffer offset */
int index = offset + x + y*stride; int index = offset + x + y*stride;
float4 irradiance = buffer[index];
rgba += index;
buffer += index*kernel_data.film.pass_stride;
/* map colors */
float4 irradiance = *((__global float4*)buffer);
float4 float_result = film_map(kg, irradiance, sample); float4 float_result = film_map(kg, irradiance, sample);
uchar4 byte_result = film_float_to_byte(float_result); uchar4 byte_result = film_float_to_byte(float_result);
rgba[index] = byte_result; *rgba = byte_result;
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -192,6 +192,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point,
ls->D = -D; ls->D = -D;
ls->t = FLT_MAX; ls->t = FLT_MAX;
} }
#ifdef __BACKGROUND_MIS__
else if(type == LIGHT_BACKGROUND) { else if(type == LIGHT_BACKGROUND) {
/* infinite area light (e.g. light dome or env light) */ /* infinite area light (e.g. light dome or env light) */
float3 D = background_light_sample(kg, randu, randv, pdf); float3 D = background_light_sample(kg, randu, randv, pdf);
@@ -201,6 +202,7 @@ __device void regular_light_sample(KernelGlobals *kg, int point,
ls->D = -D; ls->D = -D;
ls->t = FLT_MAX; ls->t = FLT_MAX;
} }
#endif
else { else {
ls->P = make_float3(data0.y, data0.z, data0.w); ls->P = make_float3(data0.y, data0.z, data0.w);

View File

@@ -64,5 +64,15 @@ __device_inline float object_surface_area(KernelGlobals *kg, int object)
return f.x; return f.x;
} }
__device_inline float object_pass_id(KernelGlobals *kg, int object)
{
if(object == ~0)
return 0.0f;
int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
float4 f = kernel_tex_fetch(__objects, offset);
return f.y;
}
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -35,14 +35,14 @@ CCL_NAMESPACE_BEGIN
/* Path Tracing */ /* Path Tracing */
void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float4 *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride) void kernel_cpu_optimized_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state, int sample, int x, int y, int offset, int stride)
{ {
kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride); kernel_path_trace(kg, buffer, rng_state, sample, x, y, offset, stride);
} }
/* Tonemapping */ /* Tonemapping */
void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float4 *buffer, int sample, int resolution, int x, int y, int offset, int stride) void kernel_cpu_optimized_tonemap(KernelGlobals *kg, uchar4 *rgba, float *buffer, int sample, int resolution, int x, int y, int offset, int stride)
{ {
kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride); kernel_film_tonemap(kg, rgba, buffer, sample, resolution, x, y, offset, stride);
} }

View File

@@ -0,0 +1,137 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CCL_NAMESPACE_BEGIN
__device_inline void kernel_write_pass_float(__global float *buffer, int sample, float value)
{
__global float *buf = buffer;
*buf = (sample == 0)? value: *buf + value;
}
__device_inline void kernel_write_pass_float3(__global float *buffer, int sample, float3 value)
{
__global float3 *buf = (__global float3*)buffer;
*buf = (sample == 0)? value: *buf + value;
}
__device_inline void kernel_write_pass_float4(__global float *buffer, int sample, float4 value)
{
__global float4 *buf = (__global float4*)buffer;
*buf = (sample == 0)? value: *buf + value;
}
__device_inline void kernel_write_data_passes(KernelGlobals *kg, __global float *buffer, PathRadiance *L,
ShaderData *sd, int sample, int path_flag, float3 throughput)
{
#ifdef __PASSES__
if(!(path_flag & PATH_RAY_CAMERA))
return;
int flag = kernel_data.film.pass_flag;
if(!(flag & PASS_ALL))
return;
/* todo: add alpha treshold */
if(!(path_flag & PATH_RAY_TRANSPARENT)) {
if(sample == 0) {
if(flag & PASS_DEPTH) {
Transform tfm = kernel_data.cam.worldtocamera;
float depth = len(transform(&tfm, sd->P));
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, sample, depth);
}
if(flag & PASS_OBJECT_ID) {
float id = object_pass_id(kg, sd->object);
kernel_write_pass_float(buffer + kernel_data.film.pass_object_id, sample, id);
}
if(flag & PASS_MATERIAL_ID) {
float id = shader_pass_id(kg, sd);
kernel_write_pass_float(buffer + kernel_data.film.pass_material_id, sample, id);
}
}
if(flag & PASS_NORMAL) {
float3 normal = sd->N;
kernel_write_pass_float3(buffer + kernel_data.film.pass_normal, sample, normal);
}
if(flag & PASS_UV) {
float3 uv = make_float3(0.0f, 0.0f, 0.0f); /* todo: request and lookup */
kernel_write_pass_float3(buffer + kernel_data.film.pass_uv, sample, uv);
}
}
if(flag & (PASS_DIFFUSE_INDIRECT|PASS_DIFFUSE_COLOR|PASS_DIFFUSE_DIRECT))
L->color_diffuse += shader_bsdf_diffuse(kg, sd)*throughput;
if(flag & (PASS_GLOSSY_INDIRECT|PASS_GLOSSY_COLOR|PASS_GLOSSY_DIRECT))
L->color_glossy += shader_bsdf_glossy(kg, sd)*throughput;
if(flag & (PASS_TRANSMISSION_INDIRECT|PASS_TRANSMISSION_COLOR|PASS_TRANSMISSION_DIRECT))
L->color_transmission += shader_bsdf_transmission(kg, sd)*throughput;
#endif
}
__device_inline void kernel_write_light_passes(KernelGlobals *kg, __global float *buffer, PathRadiance *L, int sample)
{
#ifdef __PASSES__
int flag = kernel_data.film.pass_flag;
if(!kernel_data.film.use_light_pass)
return;
if(flag & PASS_DIFFUSE_INDIRECT) {
float3 color = safe_divide_color(L->indirect_diffuse, L->color_diffuse);
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_indirect, sample, color);
}
if(flag & PASS_GLOSSY_INDIRECT) {
float3 color = safe_divide_color(L->indirect_glossy, L->color_glossy);
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_indirect, sample, color);
}
if(flag & PASS_TRANSMISSION_INDIRECT) {
float3 color = safe_divide_color(L->indirect_transmission, L->color_transmission);
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_indirect, sample, color);
}
if(flag & PASS_DIFFUSE_DIRECT) {
float3 color = safe_divide_color(L->direct_diffuse, L->color_diffuse);
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_direct, sample, color);
}
if(flag & PASS_GLOSSY_DIRECT) {
float3 color = safe_divide_color(L->direct_glossy, L->color_glossy);
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_direct, sample, color);
}
if(flag & PASS_TRANSMISSION_DIRECT) {
float3 color = safe_divide_color(L->direct_transmission, L->color_transmission);
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_direct, sample, color);
}
if(flag & PASS_EMISSION)
kernel_write_pass_float3(buffer + kernel_data.film.pass_emission, sample, L->emission);
if(flag & PASS_BACKGROUND)
kernel_write_pass_float3(buffer + kernel_data.film.pass_background, sample, L->background);
if(flag & PASS_DIFFUSE_COLOR)
kernel_write_pass_float3(buffer + kernel_data.film.pass_diffuse_color, sample, L->color_diffuse);
if(flag & PASS_GLOSSY_COLOR)
kernel_write_pass_float3(buffer + kernel_data.film.pass_glossy_color, sample, L->color_glossy);
if(flag & PASS_TRANSMISSION_COLOR)
kernel_write_pass_float3(buffer + kernel_data.film.pass_transmission_color, sample, L->color_transmission);
#endif
}
CCL_NAMESPACE_END

View File

@@ -25,39 +25,16 @@
#else #else
#include "kernel_bvh.h" #include "kernel_bvh.h"
#endif #endif
#include "kernel_accumulate.h"
#include "kernel_camera.h" #include "kernel_camera.h"
#include "kernel_shader.h" #include "kernel_shader.h"
#include "kernel_light.h" #include "kernel_light.h"
#include "kernel_emission.h" #include "kernel_emission.h"
#include "kernel_random.h" #include "kernel_random.h"
#include "kernel_passes.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
#ifdef __MODIFY_TP__
__device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int offset, int stride, int sample)
{
/* modify throughput to influence path termination probability, to avoid
darker regions receiving fewer samples than lighter regions. also RGB
are weighted differently. proper validation still remains to be done. */
const float3 weights = make_float3(1.0f, 1.33f, 0.66f);
const float3 one = make_float3(1.0f, 1.0f, 1.0f);
const int minsample = 5;
const float minL = 0.1f;
if(sample >= minsample) {
float3 L = buffer[offset + x + y*stride];
float3 Lmin = make_float3(minL, minL, minL);
float correct = (float)(sample+1)/(float)sample;
L = film_map(L*correct, sample);
return weights/clamp(L, Lmin, one);
}
return weights;
}
#endif
typedef struct PathState { typedef struct PathState {
uint flag; uint flag;
int bounce; int bounce;
@@ -168,7 +145,7 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt
return average(throughput); return average(throughput);
} }
__device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, float3 *light_L) __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, Intersection *isect, BsdfEval *L_light)
{ {
if(ray->t == 0.0f) if(ray->t == 0.0f)
return false; return false;
@@ -208,7 +185,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
} }
if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect)) { if(!scene_intersect(kg, ray, PATH_RAY_SHADOW_TRANSPARENT, isect)) {
*light_L *= throughput; bsdf_eval_mul(L_light, throughput);
return false; return false;
} }
@@ -234,13 +211,16 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra
return result; return result;
} }
__device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, float3 throughput) __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer)
{ {
/* initialize */ /* initialize */
float3 L = make_float3(0.0f, 0.0f, 0.0f); PathRadiance L;
float Ltransparent = 0.0f; float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float L_transparent = 0.0f;
#ifdef __EMISSION__ path_radiance_init(&L, kernel_data.film.use_light_pass);
#if defined(__EMISSION__) || defined(__BACKGROUND__)
float ray_pdf = 0.0f; float ray_pdf = 0.0f;
#endif #endif
PathState state; PathState state;
@@ -257,13 +237,15 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
if(!scene_intersect(kg, &ray, visibility, &isect)) { if(!scene_intersect(kg, &ray, visibility, &isect)) {
/* eval background shader if nothing hit */ /* eval background shader if nothing hit */
if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) { if(kernel_data.background.transparent && (state.flag & PATH_RAY_CAMERA)) {
Ltransparent += average(throughput); L_transparent += average(throughput);
} }
#ifdef __BACKGROUND__
else { else {
/* sample background shader */ /* sample background shader */
float3 background_L = indirect_background(kg, &ray, state.flag, ray_pdf); float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf);
L += throughput*background_L; path_radiance_accum_background(&L, throughput, L_background, state.bounce);
} }
#endif
break; break;
} }
@@ -274,19 +256,24 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF); float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, state.flag); shader_eval_surface(kg, &sd, rbsdf, state.flag);
kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput);
#ifdef __HOLDOUT__ #ifdef __HOLDOUT__
if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) { if((sd.flag & SD_HOLDOUT) && (state.flag & PATH_RAY_CAMERA)) {
float3 holdout_weight = shader_holdout_eval(kg, &sd); float3 holdout_weight = shader_holdout_eval(kg, &sd);
if(kernel_data.background.transparent) if(kernel_data.background.transparent)
Ltransparent += average(holdout_weight*throughput); /* any throughput is ok, should all be identical here */
L_transparent += average(holdout_weight*throughput);
} }
#endif #endif
#ifdef __EMISSION__ #ifdef __EMISSION__
/* emission */ /* emission */
if(sd.flag & SD_EMISSION) if(sd.flag & SD_EMISSION) {
L += throughput*indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf); float3 emission = indirect_emission(kg, &sd, isect.t, state.flag, ray_pdf);
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif #endif
/* path termination. this is a strange place to put the termination, it's /* path termination. this is a strange place to put the termination, it's
@@ -310,7 +297,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
float light_v = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_V); float light_v = path_rng(kg, rng, sample, rng_offset + PRNG_LIGHT_V);
Ray light_ray; Ray light_ray;
float3 light_L; BsdfEval L_light;
#ifdef __MULTI_LIGHT__ #ifdef __MULTI_LIGHT__
/* index -1 means randomly sample from distribution */ /* index -1 means randomly sample from distribution */
@@ -320,10 +307,10 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
#else #else
const int i = -1; const int i = -1;
#endif #endif
if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &light_L)) { if(direct_emission(kg, &sd, i, light_t, light_o, light_u, light_v, &light_ray, &L_light)) {
/* trace shadow ray */ /* trace shadow ray */
if(!shadow_blocked(kg, &state, &light_ray, &isect, &light_L)) if(!shadow_blocked(kg, &state, &light_ray, &isect, &L_light))
L += throughput*light_L; path_radiance_accum_light(&L, throughput, &L_light, state.bounce);
} }
#ifdef __MULTI_LIGHT__ #ifdef __MULTI_LIGHT__
} }
@@ -338,7 +325,7 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
/* sample BSDF */ /* sample BSDF */
float bsdf_pdf; float bsdf_pdf;
float3 bsdf_eval; BsdfEval bsdf_eval;
float3 bsdf_omega_in; float3 bsdf_omega_in;
differential3 bsdf_domega_in; differential3 bsdf_domega_in;
float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U); float bsdf_u = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF_U);
@@ -350,11 +337,11 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
shader_release(kg, &sd); shader_release(kg, &sd);
if(bsdf_pdf == 0.0f || is_zero(bsdf_eval)) if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
break; break;
/* modify throughput */ /* modify throughput */
throughput *= bsdf_eval/bsdf_pdf; path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
/* set labels */ /* set labels */
#if defined(__EMISSION__) || defined(__BACKGROUND__) #if defined(__EMISSION__) || defined(__BACKGROUND__)
@@ -374,18 +361,31 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
#endif #endif
} }
return make_float4(L.x, L.y, L.z, 1.0f - Ltransparent); float3 L_sum = path_radiance_sum(&L);
kernel_write_light_passes(kg, buffer, &L, sample);
return make_float4(L_sum.x, L_sum.y, L_sum.z, 1.0f - L_transparent);
} }
__device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int sample, int x, int y, int offset, int stride) __device void kernel_path_trace(KernelGlobals *kg,
__global float *buffer, __global uint *rng_state,
int sample, int x, int y, int offset, int stride)
{ {
/* buffer offset */
int index = offset + x + y*stride;
int pass_stride = kernel_data.film.pass_stride;
rng_state += index;
buffer += index*pass_stride;
/* initialize random numbers */ /* initialize random numbers */
RNG rng; RNG rng;
float filter_u; float filter_u;
float filter_v; float filter_v;
path_rng_init(kg, rng_state, sample, &rng, x, y, offset, stride, &filter_u, &filter_v); path_rng_init(kg, rng_state, sample, &rng, x, y, &filter_u, &filter_v);
/* sample camera ray */ /* sample camera ray */
Ray ray; Ray ray;
@@ -396,23 +396,12 @@ __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __gl
camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray); camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
/* integrate */ /* integrate */
#ifdef __MODIFY_TP__ float4 L = kernel_path_integrate(kg, &rng, sample, ray, buffer);
float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, offset, stride, sample);
float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput)/throughput;
#else
float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
float4 L = kernel_path_integrate(kg, &rng, sample, ray, throughput);
#endif
/* accumulate result in output buffer */ /* accumulate result in output buffer */
int index = offset + x + y*stride; kernel_write_pass_float4(buffer, sample, L);
if(sample == 0) path_rng_end(kg, rng_state, rng);
buffer[index] = L;
else
buffer[index] += L;
path_rng_end(kg, rng_state, rng, x, y, offset, stride);
} }
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -123,7 +123,7 @@ __device_inline float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dime
#endif #endif
} }
__device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, int offset, int stride, float *fx, float *fy) __device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, float *fx, float *fy)
{ {
#ifdef __SOBOL_FULL_SCREEN__ #ifdef __SOBOL_FULL_SCREEN__
uint px, py; uint px, py;
@@ -135,19 +135,31 @@ __device_inline void path_rng_init(KernelGlobals *kg, __global uint *rng_state,
*rng ^= kernel_data.integrator.seed; *rng ^= kernel_data.integrator.seed;
*fx = size * (float)px * (1.0f/(float)0xFFFFFFFF) - x; if(sample == 0) {
*fy = size * (float)py * (1.0f/(float)0xFFFFFFFF) - y; *fx = 0.5f;
*fy = 0.5f;
}
else {
*fx = size * (float)px * (1.0f/(float)0xFFFFFFFF) - x;
*fy = size * (float)py * (1.0f/(float)0xFFFFFFFF) - y;
}
#else #else
*rng = rng_state[offset + x + y*stride]; *rng = *rng_state;
*rng ^= kernel_data.integrator.seed; *rng ^= kernel_data.integrator.seed;
*fx = path_rng(kg, rng, sample, PRNG_FILTER_U); if(sample == 0) {
*fy = path_rng(kg, rng, sample, PRNG_FILTER_V); *fx = 0.5f;
*fy = 0.5f;
}
else {
*fx = path_rng(kg, rng, sample, PRNG_FILTER_U);
*fy = path_rng(kg, rng, sample, PRNG_FILTER_V);
}
#endif #endif
} }
__device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, int x, int y, int offset, int stride) __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng)
{ {
/* nothing to do */ /* nothing to do */
} }
@@ -163,21 +175,27 @@ __device float path_rng(KernelGlobals *kg, RNG *rng, int sample, int dimension)
return (float)*rng * (1.0f/(float)0xFFFFFFFF); return (float)*rng * (1.0f/(float)0xFFFFFFFF);
} }
__device void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, int offset, int stride, float *fx, float *fy) __device void path_rng_init(KernelGlobals *kg, __global uint *rng_state, int sample, RNG *rng, int x, int y, float *fx, float *fy)
{ {
/* load state */ /* load state */
*rng = rng_state[offset + x + y*stride]; *rng = *rng_state;
*rng ^= kernel_data.integrator.seed; *rng ^= kernel_data.integrator.seed;
*fx = path_rng(kg, rng, sample, PRNG_FILTER_U); if(sample == 0) {
*fy = path_rng(kg, rng, sample, PRNG_FILTER_V); *fx = 0.5f;
*fy = 0.5f;
}
else {
*fx = path_rng(kg, rng, sample, PRNG_FILTER_U);
*fy = path_rng(kg, rng, sample, PRNG_FILTER_V);
}
} }
__device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng, int x, int y, int offset, int stride) __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng)
{ {
/* store state for next sample */ /* store state for next sample */
rng_state[offset + x + y*stride] = rng; *rng_state = rng;
} }
#endif #endif

View File

@@ -26,7 +26,6 @@
* *
*/ */
#ifdef __OSL__ #ifdef __OSL__
#include "osl_shader.h" #include "osl_shader.h"
@@ -75,7 +74,7 @@ __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd,
if(sd->shader & SHADER_SMOOTH_NORMAL) if(sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v);
sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK); sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */ /* dPdu/dPdv */
@@ -166,7 +165,7 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd,
#endif #endif
} }
sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK); sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
#ifdef __DPDU__ #ifdef __DPDU__
/* dPdu/dPdv */ /* dPdu/dPdv */
@@ -243,7 +242,7 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
sd->Ng = -sd->P; sd->Ng = -sd->P;
sd->I = -sd->P; sd->I = -sd->P;
sd->shader = kernel_data.background.shader; sd->shader = kernel_data.background.shader;
sd->flag = kernel_tex_fetch(__shader_flag, sd->shader & SHADER_MASK); sd->flag = kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2);
#ifdef __INSTANCING__ #ifdef __INSTANCING__
sd->object = ~0; sd->object = ~0;
@@ -275,8 +274,8 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
__device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf, __device_inline void _shader_bsdf_multi_eval(const ShaderData *sd, const float3 omega_in, float *pdf,
int skip_bsdf, float3 sum_eval, float sum_pdf, float sum_sample_weight) int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight)
{ {
for(int i = 0; i< sd->num_closure; i++) { for(int i = 0; i< sd->num_closure; i++) {
if(i == skip_bsdf) if(i == skip_bsdf)
@@ -293,7 +292,7 @@ __device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float
#endif #endif
if(bsdf_pdf != 0.0f) { if(bsdf_pdf != 0.0f) {
sum_eval += eval*sc->weight; bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight);
sum_pdf += bsdf_pdf*sc->sample_weight; sum_pdf += bsdf_pdf*sc->sample_weight;
} }
@@ -302,25 +301,27 @@ __device_inline float3 _shader_bsdf_multi_eval(const ShaderData *sd, const float
} }
*pdf = sum_pdf/sum_sample_weight; *pdf = sum_pdf/sum_sample_weight;
return sum_eval;
} }
#endif #endif
__device float3 shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd,
const float3 omega_in, float *pdf) const float3 omega_in, BsdfEval *eval, float *pdf)
{ {
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, make_float3(0.0f, 0.0f, 0.0f), 0.0f, 0.0f); bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass);
return _shader_bsdf_multi_eval(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f);
#else #else
const ShaderClosure *sc = &sd->closure; const ShaderClosure *sc = &sd->closure;
*pdf = 0.0f; *pdf = 0.0f;
return svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight; *eval = svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight;
#endif #endif
} }
__device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
float randu, float randv, float3 *eval, float randu, float randv, BsdfEval *bsdf_eval,
float3 *omega_in, differential3 *domega_in, float *pdf) float3 *omega_in, differential3 *domega_in, float *pdf)
{ {
#ifdef __MULTI_CLOSURE__ #ifdef __MULTI_CLOSURE__
@@ -359,27 +360,28 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd,
const ShaderClosure *sc = &sd->closure[sampled]; const ShaderClosure *sc = &sd->closure[sampled];
int label; int label;
float3 eval;
*pdf = 0.0f; *pdf = 0.0f;
#ifdef __OSL__ #ifdef __OSL__
label = OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf); label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf);
#else #else
label = svm_bsdf_sample(sd, sc, randu, randv, eval, omega_in, domega_in, pdf); label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
#endif #endif
*eval *= sc->weight; bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass);
if(sd->num_closure > 1 && *pdf != 0.0f) { if(sd->num_closure > 1 && *pdf != 0.0f) {
float sweight = sc->sample_weight; float sweight = sc->sample_weight;
*eval = _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, *eval, *pdf*sweight, sweight); _shader_bsdf_multi_eval(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight);
} }
return label; return label;
#else #else
/* sample the single closure that we picked */ /* sample the single closure that we picked */
*pdf = 0.0f; *pdf = 0.0f;
int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, eval, omega_in, domega_in, pdf); int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, bsdf_eval, omega_in, domega_in, pdf);
*eval *= sd->closure.weight; *bsdf_eval *= sd->closure.weight;
return label; return label;
#endif #endif
} }
@@ -421,6 +423,68 @@ __device float3 shader_bsdf_transparency(KernelGlobals *kg, ShaderData *sd)
#endif #endif
} }
__device float3 shader_bsdf_diffuse(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __MULTI_CLOSURE__
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type))
eval += sc->weight;
}
return eval;
#else
if(CLOSURE_IS_BSDF_DIFFUSE(sd->closure.type))
return sd->closure.weight;
else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
}
__device float3 shader_bsdf_glossy(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __MULTI_CLOSURE__
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_GLOSSY(sc->type))
eval += sc->weight;
}
return eval;
#else
if(CLOSURE_IS_BSDF_GLOSSY(sd->closure.type))
return sd->closure.weight;
else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
}
__device float3 shader_bsdf_transmission(KernelGlobals *kg, ShaderData *sd)
{
#ifdef __MULTI_CLOSURE__
float3 eval = make_float3(0.0f, 0.0f, 0.0f);
for(int i = 0; i< sd->num_closure; i++) {
ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
eval += sc->weight;
}
return eval;
#else
if(CLOSURE_IS_BSDF_TRANSMISSION(sd->closure.type))
return sd->closure.weight;
else
return make_float3(0.0f, 0.0f, 0.0f);
#endif
}
/* Emission */ /* Emission */
@@ -588,12 +652,17 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect)
int prim = kernel_tex_fetch(__prim_index, isect->prim); int prim = kernel_tex_fetch(__prim_index, isect->prim);
float4 Ns = kernel_tex_fetch(__tri_normal, prim); float4 Ns = kernel_tex_fetch(__tri_normal, prim);
int shader = __float_as_int(Ns.w); int shader = __float_as_int(Ns.w);
int flag = kernel_tex_fetch(__shader_flag, shader & SHADER_MASK); int flag = kernel_tex_fetch(__shader_flag, (shader & SHADER_MASK)*2);
return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0; return (flag & SD_HAS_SURFACE_TRANSPARENT) != 0;
} }
#endif #endif
__device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
{
return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
}
/* Free ShaderData */ /* Free ShaderData */
__device void shader_release(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd)

View File

@@ -70,6 +70,8 @@ CCL_NAMESPACE_BEGIN
#ifdef __KERNEL_ADV_SHADING__ #ifdef __KERNEL_ADV_SHADING__
#define __MULTI_CLOSURE__ #define __MULTI_CLOSURE__
#define __TRANSPARENT_SHADOWS__ #define __TRANSPARENT_SHADOWS__
#define __PASSES__
#define __BACKGROUND_MIS__
#endif #endif
//#define __MULTI_LIGHT__ //#define __MULTI_LIGHT__
@@ -150,6 +152,75 @@ typedef enum ClosureLabel {
LABEL_STOP = 2048 LABEL_STOP = 2048
} ClosureLabel; } ClosureLabel;
/* Render Passes */
typedef enum PassType {
PASS_NONE = 0,
PASS_COMBINED = 1,
PASS_DEPTH = 2,
PASS_NORMAL = 8,
PASS_UV = 16,
PASS_OBJECT_ID = 32,
PASS_MATERIAL_ID = 64,
PASS_DIFFUSE_COLOR = 128,
PASS_GLOSSY_COLOR = 256,
PASS_TRANSMISSION_COLOR = 512,
PASS_DIFFUSE_INDIRECT = 1024,
PASS_GLOSSY_INDIRECT = 2048,
PASS_TRANSMISSION_INDIRECT = 4096,
PASS_DIFFUSE_DIRECT = 8192,
PASS_GLOSSY_DIRECT = 16384,
PASS_TRANSMISSION_DIRECT = 32768,
PASS_EMISSION = 65536,
PASS_BACKGROUND = 131072
} PassType;
#define PASS_ALL (~0)
#ifdef __PASSES__
typedef float3 PathThroughput;
struct PathRadiance {
int use_light_pass;
float3 emission;
float3 background;
float3 indirect;
float3 direct_throughput;
float3 direct_emission;
float3 color_diffuse;
float3 color_glossy;
float3 color_transmission;
float3 direct_diffuse;
float3 direct_glossy;
float3 direct_transmission;
float3 indirect_diffuse;
float3 indirect_glossy;
float3 indirect_transmission;
};
struct BsdfEval {
int use_light_pass;
float3 diffuse;
float3 glossy;
float3 transmission;
float3 transparent;
};
#else
typedef float3 PathThroughput;
typedef float3 PathRadiance;
typedef float3 BsdfEval;
#endif
/* Shader Flag */ /* Shader Flag */
typedef enum ShaderFlag { typedef enum ShaderFlag {
@@ -353,7 +424,32 @@ typedef struct KernelCamera {
typedef struct KernelFilm { typedef struct KernelFilm {
float exposure; float exposure;
int pad1, pad2, pad3; int pass_flag;
int pass_stride;
int use_light_pass;
int pass_combined;
int pass_depth;
int pass_normal;
int pass_pad;
int pass_uv;
int pass_object_id;
int pass_material_id;
int pass_diffuse_color;
int pass_glossy_color;
int pass_transmission_color;
int pass_diffuse_indirect;
int pass_glossy_indirect;
int pass_transmission_indirect;
int pass_diffuse_direct;
int pass_glossy_direct;
int pass_transmission_direct;
int pass_emission;
int pass_background;
} KernelFilm; } KernelFilm;
typedef struct KernelBackground { typedef struct KernelBackground {

View File

@@ -20,6 +20,7 @@ set(SRC_OSL
node_environment_texture.osl node_environment_texture.osl
node_fresnel.osl node_fresnel.osl
node_gamma.osl node_gamma.osl
node_brightness.osl
node_geometry.osl node_geometry.osl
node_glass_bsdf.osl node_glass_bsdf.osl
node_glossy_bsdf.osl node_glossy_bsdf.osl

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "stdosl.h"
shader node_brightness(
color ColorIn = color(0.8, 0.8, 0.8),
float Bright = 0.0,
float Contrast = 0.0,
output ColorOut = color(0.8, 0.8, 0.8)
{
float delta = Contrast * (1.0/200.0);
float a = 1.0 - delta * 2.0;
float b;
Bright *= 1.0/100.0;
/*
* The algorithm is by Werner D. Streidt
* (http://visca.com/ffactory/archives/5-99/msg00021.html)
* Extracted of OpenCV demhist.c
*/
if (Contrast > 0.0) {
a = (a < 0.0 ? 1.0/a : 0.0);
b = a * (Brightness - delta);
}
else {
delta *= -1.0;
b = a * (Brightness + delta);
}
ColorOut = a * ColorIn + b;
}

View File

@@ -131,6 +131,7 @@ CCL_NAMESPACE_END
#include "svm_hsv.h" #include "svm_hsv.h"
#include "svm_image.h" #include "svm_image.h"
#include "svm_gamma.h" #include "svm_gamma.h"
#include "svm_brightness.h"
#include "svm_invert.h" #include "svm_invert.h"
#include "svm_light_path.h" #include "svm_light_path.h"
#include "svm_magic.h" #include "svm_magic.h"
@@ -270,6 +271,9 @@ __device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ShaderT
case NODE_GAMMA: case NODE_GAMMA:
svm_node_gamma(sd, stack, node.y, node.z, node.w); svm_node_gamma(sd, stack, node.y, node.z, node.w);
break; break;
case NODE_BRIGHTCONTRAST:
svm_node_brightness(sd, stack, node.y, node.z, node.w);
break;
case NODE_MIX: case NODE_MIX:
svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset); svm_node_mix(kg, sd, stack, node.y, node.z, node.w, &offset);
break; break;

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2011, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
CCL_NAMESPACE_BEGIN
__device void svm_node_brightness(ShaderData *sd, float *stack, uint in_color, uint out_color, uint node)
{
uint bright_offset, contrast_offset;
float3 color = stack_load_float3(stack, in_color);
decode_node_uchar4(node, &bright_offset, &contrast_offset, NULL, NULL);
float brightness = stack_load_float(stack, bright_offset);
float contrast = stack_load_float(stack, contrast_offset);
brightness *= 1.0f/100.0f;
float delta = contrast * (1.0f/200.0f);
float a = 1.0f - delta * 2.0f;
float b;
/*
* The algorithm is by Werner D. Streidt
* (http://visca.com/ffactory/archives/5-99/msg00021.html)
* Extracted of OpenCV demhist.c
*/
if (contrast > 0.0f) {
a = (a > 0.0f? (1.0f / a): 0.0f);
b = a * (brightness - delta);
}
else {
delta *= -1.0f;
b = a * (brightness + delta);
}
color.x = a*color.x + b;
color.y = a*color.y + b;
color.z = a*color.z + b;
if (stack_valid(out_color))
stack_store_float3(stack, out_color, color);
}
CCL_NAMESPACE_END

View File

@@ -87,7 +87,8 @@ typedef enum NodeType {
NODE_INVERT = 5400, NODE_INVERT = 5400,
NODE_NORMAL = 5500, NODE_NORMAL = 5500,
NODE_GAMMA = 5600, NODE_GAMMA = 5600,
NODE_TEX_CHECKER = 5700 NODE_TEX_CHECKER = 5700,
NODE_BRIGHTCONTRAST = 5800
} NodeType; } NodeType;
typedef enum NodeAttributeType { typedef enum NodeAttributeType {
@@ -265,22 +266,26 @@ typedef enum ShaderType {
typedef enum ClosureType { typedef enum ClosureType {
CLOSURE_BSDF_ID, CLOSURE_BSDF_ID,
CLOSURE_BSDF_DIFFUSE_ID, CLOSURE_BSDF_DIFFUSE_ID,
CLOSURE_BSDF_OREN_NAYAR_ID, CLOSURE_BSDF_OREN_NAYAR_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
CLOSURE_BSDF_REFLECTION_ID, CLOSURE_BSDF_REFLECTION_ID,
CLOSURE_BSDF_REFRACTION_ID,
CLOSURE_BSDF_GLASS_ID,
CLOSURE_BSDF_TRANSPARENT_ID,
CLOSURE_BSDF_MICROFACET_GGX_ID, CLOSURE_BSDF_MICROFACET_GGX_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_WARD_ID, CLOSURE_BSDF_WARD_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_WESTIN_SHEEN_ID, CLOSURE_BSDF_WESTIN_SHEEN_ID,
CLOSURE_BSDF_TRANSLUCENT_ID,
CLOSURE_BSDF_REFRACTION_ID,
CLOSURE_BSDF_WESTIN_BACKSCATTER_ID,
CLOSURE_BSDF_ASHIKHMIN_VELVET_ID,
CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID,
CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID,
CLOSURE_BSDF_GLASS_ID,
CLOSURE_BSDF_TRANSPARENT_ID,
CLOSURE_BSSRDF_CUBIC_ID, CLOSURE_BSSRDF_CUBIC_ID,
CLOSURE_EMISSION_ID, CLOSURE_EMISSION_ID,
CLOSURE_DEBUG_ID, CLOSURE_DEBUG_ID,
@@ -296,7 +301,10 @@ typedef enum ClosureType {
} ClosureType; } ClosureType;
/* watch this, being lazy with memory usage */ /* watch this, being lazy with memory usage */
#define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_WESTIN_SHEEN_ID) #define CLOSURE_IS_BSDF(type) (type <= CLOSURE_BSDF_TRANSPARENT_ID)
#define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID)
#define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_WESTIN_SHEEN_ID)
#define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSLUCENT_ID && type <= CLOSURE_BSDF_GLASS_ID)
#define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID)
#define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID) #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID) #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)

View File

@@ -22,6 +22,7 @@
#include "device.h" #include "device.h"
#include "util_debug.h" #include "util_debug.h"
#include "util_foreach.h"
#include "util_hash.h" #include "util_hash.h"
#include "util_image.h" #include "util_image.h"
#include "util_math.h" #include "util_math.h"
@@ -31,6 +32,48 @@
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
/* Buffer Params */
BufferParams::BufferParams()
{
width = 0;
height = 0;
full_x = 0;
full_y = 0;
full_width = 0;
full_height = 0;
Pass::add(PASS_COMBINED, passes);
}
void BufferParams::get_offset_stride(int& offset, int& stride)
{
offset = -(full_x + full_y*width);
stride = width;
}
bool BufferParams::modified(const BufferParams& params)
{
return !(full_x == params.full_x
&& full_y == params.full_y
&& width == params.width
&& height == params.height
&& full_width == params.full_width
&& full_height == params.full_height
&& Pass::equals(passes, params.passes));
}
int BufferParams::get_passes_size()
{
int size = 0;
foreach(Pass& pass, passes)
size += pass.components;
return align_up(size, 4);
}
/* Render Buffers */ /* Render Buffers */
RenderBuffers::RenderBuffers(Device *device_) RenderBuffers::RenderBuffers(Device *device_)
@@ -64,7 +107,7 @@ void RenderBuffers::reset(Device *device, BufferParams& params_)
device_free(); device_free();
/* allocate buffer */ /* allocate buffer */
buffer.resize(params.width, params.height); buffer.resize(params.width*params.height*params.get_passes_size());
device->mem_alloc(buffer, MEM_READ_WRITE); device->mem_alloc(buffer, MEM_READ_WRITE);
device->mem_zero(buffer); device->mem_zero(buffer);
@@ -82,31 +125,83 @@ void RenderBuffers::reset(Device *device, BufferParams& params_)
device->mem_copy_to(rng_state); device->mem_copy_to(rng_state);
} }
float4 *RenderBuffers::copy_from_device(float exposure, int sample) bool RenderBuffers::copy_from_device()
{ {
if(!buffer.device_pointer) if(!buffer.device_pointer)
return NULL; return false;
device->mem_copy_from(buffer, 0, params.width, params.height, sizeof(float4)); device->mem_copy_from(buffer, 0, params.width, params.height, params.get_passes_size()*sizeof(float));
float4 *out = new float4[params.width*params.height]; return true;
float4 *in = (float4*)buffer.data_pointer; }
float scale = 1.0f/(float)sample;
for(int i = params.width*params.height - 1; i >= 0; i--) {
float4 rgba = in[i]*scale;
rgba.x = rgba.x*exposure; bool RenderBuffers::get_pass(PassType type, float exposure, int sample, int components, float *pixels)
rgba.y = rgba.y*exposure; {
rgba.z = rgba.z*exposure; int pass_offset = 0;
/* clamp since alpha might be > 1.0 due to russian roulette */ foreach(Pass& pass, params.passes) {
rgba.w = clamp(rgba.w, 0.0f, 1.0f); if(pass.type != type) {
pass_offset += pass.components;
continue;
}
out[i] = rgba; float *in = (float*)buffer.data_pointer + pass_offset;
int pass_stride = params.get_passes_size();
float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
float scale_exposure = (pass.exposure)? scale*exposure: scale;
int size = params.width*params.height;
if(components == 1) {
assert(pass.components == components);
/* scalar */
if(type == PASS_DEPTH) {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
}
}
else {
for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
float f = *in;
pixels[0] = f*scale_exposure;
}
}
}
else if(components == 3) {
assert(pass.components == 4);
/* RGB/vector */
for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
float3 f = make_float3(in[0], in[1], in[2]);
pixels[0] = f.x*scale_exposure;
pixels[1] = f.y*scale_exposure;
pixels[2] = f.z*scale_exposure;
}
}
else if(components == 4) {
assert(pass.components == components);
/* RGBA */
for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
float4 f = make_float4(in[0], in[1], in[2], in[3]);
pixels[0] = f.x*scale_exposure;
pixels[1] = f.y*scale_exposure;
pixels[2] = f.z*scale_exposure;
/* clamp since alpha might be > 1.0 due to russian roulette */
pixels[3] = clamp(f.w*scale, 0.0f, 1.0f);
}
}
return true;
} }
return out; return false;
} }
/* Display Buffer */ /* Display Buffer */

View File

@@ -21,6 +21,10 @@
#include "device_memory.h" #include "device_memory.h"
#include "film.h"
#include "kernel_types.h"
#include "util_string.h" #include "util_string.h"
#include "util_thread.h" #include "util_thread.h"
#include "util_types.h" #include "util_types.h"
@@ -45,32 +49,16 @@ public:
int full_width; int full_width;
int full_height; int full_height;
BufferParams() /* passes */
{ vector<Pass> passes;
width = 0;
height = 0;
full_x = 0; /* functions */
full_y = 0; BufferParams();
full_width = 0;
full_height = 0;
}
void get_offset_stride(int& offset, int& stride) void get_offset_stride(int& offset, int& stride);
{ bool modified(const BufferParams& params);
offset = -(full_x + full_y*width); void add_pass(PassType type);
stride = width; int get_passes_size();
}
bool modified(const BufferParams& params)
{
return !(full_x == params.full_x
&& full_y == params.full_y
&& width == params.width
&& height == params.height
&& full_width == params.full_width
&& full_height == params.full_height);
}
}; };
/* Render Buffers */ /* Render Buffers */
@@ -80,7 +68,7 @@ public:
/* buffer parameters */ /* buffer parameters */
BufferParams params; BufferParams params;
/* float buffer */ /* float buffer */
device_vector<float4> buffer; device_vector<float> buffer;
/* random number generator state */ /* random number generator state */
device_vector<uint> rng_state; device_vector<uint> rng_state;
/* mutex, must be locked manually by callers */ /* mutex, must be locked manually by callers */
@@ -90,7 +78,9 @@ public:
~RenderBuffers(); ~RenderBuffers();
void reset(Device *device, BufferParams& params); void reset(Device *device, BufferParams& params);
float4 *copy_from_device(float exposure, int sample);
bool copy_from_device();
bool get_pass(PassType type, float exposure, int sample, int components, float *pixels);
protected: protected:
void device_free(); void device_free();

View File

@@ -21,11 +21,123 @@
#include "film.h" #include "film.h"
#include "scene.h" #include "scene.h"
#include "util_algorithm.h"
#include "util_foreach.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
/* Pass */
static bool compare_pass_order(const Pass& a, const Pass& b)
{
if(a.components == b.components)
return (a.type < b.type);
return (a.components > b.components);
}
void Pass::add(PassType type, vector<Pass>& passes)
{
Pass pass;
pass.type = type;
pass.filter = true;
pass.exposure = false;
switch(type) {
case PASS_NONE:
pass.components = 0;
break;
case PASS_COMBINED:
pass.components = 4;
pass.exposure = true;
break;
case PASS_DEPTH:
pass.components = 1;
pass.filter = false;
break;
case PASS_NORMAL:
pass.components = 4;
break;
case PASS_UV:
pass.components = 4;
break;
case PASS_OBJECT_ID:
pass.components = 1;
pass.filter = false;
break;
case PASS_MATERIAL_ID:
pass.components = 1;
pass.filter = false;
break;
case PASS_DIFFUSE_COLOR:
pass.components = 4;
break;
case PASS_GLOSSY_COLOR:
pass.components = 4;
break;
case PASS_TRANSMISSION_COLOR:
pass.components = 4;
break;
case PASS_DIFFUSE_INDIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_GLOSSY_INDIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_TRANSMISSION_INDIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_DIFFUSE_DIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_GLOSSY_DIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_TRANSMISSION_DIRECT:
pass.components = 4;
pass.exposure = true;
break;
case PASS_EMISSION:
pass.components = 4;
pass.exposure = true;
break;
case PASS_BACKGROUND:
pass.components = 4;
pass.exposure = true;
break;
}
passes.push_back(pass);
/* order from by components, to ensure alignment so passes with size 4
come first and then passes with size 1 */
sort(passes.begin(), passes.end(), compare_pass_order);
}
bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
{
if(A.size() != B.size())
return false;
for(int i = 0; i < A.size(); i++)
if(A[i].type != B[i].type)
return false;
return true;
}
/* Film */
Film::Film() Film::Film()
{ {
exposure = 0.8f; exposure = 0.8f;
Pass::add(PASS_COMBINED, passes);
need_update = true; need_update = true;
} }
@@ -42,6 +154,84 @@ void Film::device_update(Device *device, DeviceScene *dscene)
/* update __data */ /* update __data */
kfilm->exposure = exposure; kfilm->exposure = exposure;
kfilm->pass_flag = 0;
kfilm->pass_stride = 0;
kfilm->use_light_pass = 0;
foreach(Pass& pass, passes) {
kfilm->pass_flag |= pass.type;
switch(pass.type) {
case PASS_COMBINED:
kfilm->pass_combined = kfilm->pass_stride;
break;
case PASS_DEPTH:
kfilm->pass_depth = kfilm->pass_stride;
break;
case PASS_NORMAL:
kfilm->pass_normal = kfilm->pass_stride;
break;
case PASS_UV:
kfilm->pass_uv = kfilm->pass_stride;
break;
case PASS_OBJECT_ID:
kfilm->pass_object_id = kfilm->pass_stride;
break;
case PASS_MATERIAL_ID:
kfilm->pass_material_id = kfilm->pass_stride;
break;
case PASS_DIFFUSE_COLOR:
kfilm->pass_diffuse_color = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_COLOR:
kfilm->pass_glossy_color = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_COLOR:
kfilm->pass_transmission_color = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_DIFFUSE_INDIRECT:
kfilm->pass_diffuse_indirect = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_INDIRECT:
kfilm->pass_glossy_indirect = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_INDIRECT:
kfilm->pass_transmission_indirect = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_DIFFUSE_DIRECT:
kfilm->pass_diffuse_direct = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_GLOSSY_DIRECT:
kfilm->pass_glossy_direct = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_TRANSMISSION_DIRECT:
kfilm->pass_transmission_direct = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_EMISSION:
kfilm->pass_emission = kfilm->pass_stride;
kfilm->use_light_pass = 1;
break;
case PASS_BACKGROUND:
kfilm->pass_background = kfilm->pass_stride;
kfilm->use_light_pass = 1;
case PASS_NONE:
break;
}
kfilm->pass_stride += pass.components;
}
kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
need_update = false; need_update = false;
} }
@@ -52,7 +242,8 @@ void Film::device_free(Device *device, DeviceScene *dscene)
bool Film::modified(const Film& film) bool Film::modified(const Film& film)
{ {
return !(exposure == film.exposure); return !(exposure == film.exposure
&& Pass::equals(passes, film.passes));
} }
void Film::tag_update(Scene *scene) void Film::tag_update(Scene *scene)

View File

@@ -20,6 +20,9 @@
#define __FILM_H__ #define __FILM_H__
#include "util_string.h" #include "util_string.h"
#include "util_vector.h"
#include "kernel_types.h"
CCL_NAMESPACE_BEGIN CCL_NAMESPACE_BEGIN
@@ -27,9 +30,21 @@ class Device;
class DeviceScene; class DeviceScene;
class Scene; class Scene;
class Pass {
public:
PassType type;
int components;
bool filter;
bool exposure;
static void add(PassType type, vector<Pass>& passes);
static bool equals(const vector<Pass>& A, const vector<Pass>& B);
};
class Film { class Film {
public: public:
float exposure; float exposure;
vector<Pass> passes;
bool need_update; bool need_update;
Film(); Film();

View File

@@ -402,6 +402,16 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE); float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
if(!device->info.advanced_shading) {
/* remove unsupported light */
foreach(Light *light, scene->lights) {
if(light->type == LIGHT_BACKGROUND) {
scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end());
break;
}
}
}
for(size_t i = 0; i < scene->lights.size(); i++) { for(size_t i = 0; i < scene->lights.size(); i++) {
Light *light = scene->lights[i]; Light *light = scene->lights[i];
float3 co = light->co; float3 co = light->co;
@@ -431,7 +441,7 @@ void LightManager::device_update_points(Device *device, DeviceScene *dscene, Sce
shader_id &= ~SHADER_AREA_LIGHT; shader_id &= ~SHADER_AREA_LIGHT;
light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 1] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
} }

View File

@@ -1820,6 +1820,38 @@ void GammaNode::compile(OSLCompiler& compiler)
compiler.add(this, "node_gamma"); compiler.add(this, "node_gamma");
} }
/* Bright Contrast */
BrightContrastNode::BrightContrastNode()
: ShaderNode("brightness")
{
add_input("Color", SHADER_SOCKET_COLOR);
add_input("Bright", SHADER_SOCKET_FLOAT);
add_input("Contrast", SHADER_SOCKET_FLOAT);
add_output("Color", SHADER_SOCKET_COLOR);
}
void BrightContrastNode::compile(SVMCompiler& compiler)
{
ShaderInput *color_in = input("Color");
ShaderInput *bright_in = input("Bright");
ShaderInput *contrast_in = input("Contrast");
ShaderOutput *color_out = output("Color");
compiler.stack_assign(color_in);
compiler.stack_assign(bright_in);
compiler.stack_assign(contrast_in);
compiler.stack_assign(color_out);
compiler.add_node(NODE_BRIGHTCONTRAST,
color_in->stack_offset, color_out->stack_offset,
compiler.encode_uchar4(bright_in->stack_offset, contrast_in->stack_offset));
}
void BrightContrastNode::compile(OSLCompiler& compiler)
{
compiler.add(this, "node_brightness");
}
/* Separate RGB */ /* Separate RGB */
SeparateRGBNode::SeparateRGBNode() SeparateRGBNode::SeparateRGBNode()
: ShaderNode("separate_rgb") : ShaderNode("separate_rgb")

View File

@@ -320,6 +320,11 @@ public:
SHADER_NODE_CLASS(GammaNode) SHADER_NODE_CLASS(GammaNode)
}; };
class BrightContrastNode : public ShaderNode {
public:
SHADER_NODE_CLASS(BrightContrastNode)
};
class SeparateRGBNode : public ShaderNode { class SeparateRGBNode : public ShaderNode {
public: public:
SHADER_NODE_CLASS(SeparateRGBNode) SHADER_NODE_CLASS(SeparateRGBNode)

View File

@@ -36,6 +36,7 @@ Object::Object()
mesh = NULL; mesh = NULL;
tfm = transform_identity(); tfm = transform_identity();
visibility = ~0; visibility = ~0;
pass_id = 0;
} }
Object::~Object() Object::~Object()
@@ -135,6 +136,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
/* todo: correct for displacement, and move to a better place */ /* todo: correct for displacement, and move to a better place */
float uniform_scale; float uniform_scale;
float surface_area = 0.0f; float surface_area = 0.0f;
float pass_id = ob->pass_id;
if(transform_uniform_scale(tfm, uniform_scale)) { if(transform_uniform_scale(tfm, uniform_scale)) {
map<Mesh*, float>::iterator it = surface_area_map.find(mesh); map<Mesh*, float>::iterator it = surface_area_map.find(mesh);
@@ -171,7 +173,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
memcpy(&objects[offset], &tfm, sizeof(float4)*4); memcpy(&objects[offset], &tfm, sizeof(float4)*4);
memcpy(&objects[offset+4], &itfm, sizeof(float4)*4); memcpy(&objects[offset+4], &itfm, sizeof(float4)*4);
memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4); memcpy(&objects[offset+8], &ntfm, sizeof(float4)*4);
objects[offset+12] = make_float4(surface_area, 0.0f, 0.0f, 0.0f); objects[offset+12] = make_float4(surface_area, pass_id, 0.0f, 0.0f);
i++; i++;

View File

@@ -41,6 +41,7 @@ public:
Transform tfm; Transform tfm;
BoundBox bounds; BoundBox bounds;
ustring name; ustring name;
int pass_id;
vector<ParamValue> attributes; vector<ParamValue> attributes;
uint visibility; uint visibility;

View File

@@ -35,6 +35,7 @@ CCL_NAMESPACE_BEGIN
Shader::Shader() Shader::Shader()
{ {
name = ""; name = "";
pass_id = 0;
graph = NULL; graph = NULL;
graph_bump = NULL; graph_bump = NULL;
@@ -167,7 +168,7 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
if(scene->shaders.size() == 0) if(scene->shaders.size() == 0)
return; return;
uint shader_flag_size = scene->shaders.size()*2; uint shader_flag_size = scene->shaders.size()*4;
uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint *shader_flag = dscene->shader_flag.resize(shader_flag_size);
uint i = 0; uint i = 0;
@@ -184,7 +185,9 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
flag |= SD_HOMOGENEOUS_VOLUME; flag |= SD_HOMOGENEOUS_VOLUME;
shader_flag[i++] = flag; shader_flag[i++] = flag;
shader_flag[i++] = shader->pass_id;
shader_flag[i++] = flag; shader_flag[i++] = flag;
shader_flag[i++] = shader->pass_id;
} }
device->tex_alloc("__shader_flag", dscene->shader_flag); device->tex_alloc("__shader_flag", dscene->shader_flag);

View File

@@ -47,6 +47,7 @@ class Shader {
public: public:
/* name */ /* name */
string name; string name;
int pass_id;
/* shader graph */ /* shader graph */
ShaderGraph *graph; ShaderGraph *graph;

View File

@@ -58,7 +58,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
} }
bool sunsky_done = false; bool sunsky_done = false;
bool use_multi_closure = device->support_full_kernel(); bool use_multi_closure = device->info.advanced_shading;
for(i = 0; i < scene->shaders.size(); i++) { for(i = 0; i < scene->shaders.size(); i++) {
Shader *shader = scene->shaders[i]; Shader *shader = scene->shaders[i];

View File

@@ -96,7 +96,7 @@ public:
{ {
thread_scoped_lock lock(progress_mutex); thread_scoped_lock lock(progress_mutex);
start_time = start_time; start_time = start_time_;
} }
void set_sample(int sample_, double sample_time_) void set_sample(int sample_, double sample_time_)

View File

@@ -277,6 +277,11 @@ __device float4 make_float4(float x, float y, float z, float w)
return a; return a;
} }
__device int align_up(int offset, int alignment)
{
return (offset + alignment - 1) & ~(alignment - 1);
}
#endif #endif
CCL_NAMESPACE_END CCL_NAMESPACE_END

View File

@@ -35,6 +35,7 @@
#include <libavcodec/avcodec.h> #include <libavcodec/avcodec.h>
#include <libavutil/rational.h> #include <libavutil/rational.h>
#include <libavutil/opt.h>
#if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101)) #if (LIBAVFORMAT_VERSION_MAJOR > 52) || ((LIBAVFORMAT_VERSION_MAJOR >= 52) && (LIBAVFORMAT_VERSION_MINOR >= 101))
#define FFMPEG_HAVE_PARSE_UTILS 1 #define FFMPEG_HAVE_PARSE_UTILS 1

View File

@@ -271,6 +271,15 @@ public:
*/ */
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0) = 0; const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0) = 0;
/**
* Updates the resolution while in fullscreen mode.
* @param setting The new setting of the display.
* @param window Window displayed in full screen.
*
* @return Indication of success.
*/
virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window) = 0;
/** /**
* Ends full screen mode. * Ends full screen mode.

View File

@@ -77,6 +77,12 @@ static const char* ndof_button_names[] = {
"NDOF_BUTTON_8", "NDOF_BUTTON_8",
"NDOF_BUTTON_9", "NDOF_BUTTON_9",
"NDOF_BUTTON_10", "NDOF_BUTTON_10",
// more general-purpose buttons
"NDOF_BUTTON_A",
"NDOF_BUTTON_B",
"NDOF_BUTTON_C",
// the end
"NDOF_BUTTON_LAST"
}; };
#endif #endif
@@ -169,7 +175,7 @@ static const NDOF_ButtonT SpaceMousePro_HID_map[] = {
}; };
/* this is the older SpacePilot (sans Pro) /* this is the older SpacePilot (sans Pro)
* thanks to polosson for the info in this table */ * thanks to polosson for info about this device */
static const NDOF_ButtonT SpacePilot_HID_map[] = { static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_1, NDOF_BUTTON_1,
NDOF_BUTTON_2, NDOF_BUTTON_2,
@@ -194,6 +200,23 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = {
NDOF_BUTTON_NONE // the CONFIG button -- what does it do? NDOF_BUTTON_NONE // the CONFIG button -- what does it do?
}; };
/* this is the older Spaceball 5000 USB
* thanks to Tehrasha Darkon for info about this device */
static const NDOF_ButtonT Spaceball5000_HID_map[] = {
NDOF_BUTTON_1,
NDOF_BUTTON_2,
NDOF_BUTTON_3,
NDOF_BUTTON_4,
NDOF_BUTTON_5,
NDOF_BUTTON_6,
NDOF_BUTTON_7,
NDOF_BUTTON_8,
NDOF_BUTTON_9,
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C
};
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
: m_system(sys) : m_system(sys)
, m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code
@@ -237,12 +260,12 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
m_buttonCount = 15; m_buttonCount = 15;
break; break;
case 0xC629: case 0xC629:
puts("ndof: using SpacePilotPro"); puts("ndof: using SpacePilot Pro");
m_deviceType = NDOF_SpacePilotPro; m_deviceType = NDOF_SpacePilotPro;
m_buttonCount = 31; m_buttonCount = 31;
break; break;
case 0xC62B: case 0xC62B:
puts("ndof: using SpaceMousePro"); puts("ndof: using SpaceMouse Pro");
m_deviceType = NDOF_SpaceMousePro; m_deviceType = NDOF_SpaceMousePro;
m_buttonCount = 27; m_buttonCount = 27;
// ^^ actually has 15 buttons, but their HID codes range from 0 to 26 // ^^ actually has 15 buttons, but their HID codes range from 0 to 26
@@ -255,6 +278,12 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ
m_buttonCount = 21; m_buttonCount = 21;
break; break;
case 0xC621:
puts("ndof: using Spaceball 5000");
m_deviceType = NDOF_Spaceball5000;
m_buttonCount = 12;
break;
case 0xC623: case 0xC623:
puts("ndof: SpaceTraveler not supported, please file a bug report"); puts("ndof: SpaceTraveler not supported, please file a bug report");
m_buttonCount = 8; m_buttonCount = 8;
@@ -385,8 +414,21 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64
default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window);
} }
break; break;
case NDOF_Spaceball5000:
// has no special 'keyboard' buttons
sendButtonEvent(Spaceball5000_HID_map[button_number], press, time, window);
break;
case NDOF_UnknownDevice: case NDOF_UnknownDevice:
printf("ndof: button %d on unknown device (ignoring)\n", button_number); printf("ndof: button %d on unknown device (", button_number);
// map to the 'general purpose' buttons
// this is mainly for old serial devices
if (button_number < NDOF_BUTTON_LAST - NDOF_BUTTON_1) {
printf("sending)\n");
sendButtonEvent((NDOF_ButtonT)(NDOF_BUTTON_1 + button_number), press, time, window);
}
else {
printf("discarding)\n");
}
} }
int mask = 1 << button_number; int mask = 1 << button_number;

View File

@@ -40,7 +40,8 @@ typedef enum {
NDOF_SpaceMousePro, NDOF_SpaceMousePro,
// older devices // older devices
NDOF_SpacePilot NDOF_SpacePilot,
NDOF_Spaceball5000
} NDOF_DeviceT; } NDOF_DeviceT;
@@ -87,7 +88,12 @@ typedef enum {
NDOF_BUTTON_8, NDOF_BUTTON_8,
NDOF_BUTTON_9, NDOF_BUTTON_9,
NDOF_BUTTON_10, NDOF_BUTTON_10,
// more general-purpose buttons
NDOF_BUTTON_A,
NDOF_BUTTON_B,
NDOF_BUTTON_C,
// the end
NDOF_BUTTON_LAST
} NDOF_ButtonT; } NDOF_ButtonT;
class GHOST_NDOFManager class GHOST_NDOFManager

View File

@@ -168,6 +168,19 @@ GHOST_TSuccess GHOST_System::beginFullScreen(const GHOST_DisplaySetting& setting
} }
GHOST_TSuccess GHOST_System::updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window)
{
GHOST_TSuccess success = GHOST_kFailure;
GHOST_ASSERT(m_windowManager, "GHOST_System::updateFullScreen(): invalid window manager");
if(m_displayManager) {
if (m_windowManager->getFullScreen()) {
success = m_displayManager->setCurrentDisplaySetting(GHOST_DisplayManager::kMainDisplay, setting);
}
}
return success;
}
GHOST_TSuccess GHOST_System::endFullScreen(void) GHOST_TSuccess GHOST_System::endFullScreen(void)
{ {
GHOST_TSuccess success = GHOST_kFailure; GHOST_TSuccess success = GHOST_kFailure;

View File

@@ -145,6 +145,15 @@ public:
*/ */
virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, virtual GHOST_TSuccess beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window,
const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0); const bool stereoVisual, const GHOST_TUns16 numOfAASamples=0);
/**
* Updates the resolution while in fullscreen mode.
* @param setting The new setting of the display.
* @param window Window displayed in full screen.
*
* @return Indication of success.
*/
virtual GHOST_TSuccess updateFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window);
/** /**
* Ends full screen mode. * Ends full screen mode.

View File

@@ -219,7 +219,8 @@ kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED' kmi.properties.value_2 = 'ENABLED'
kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS') kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS')
kmi = km.keymap_items.new('object.select_all', 'A', 'PRESS') kmi = km.keymap_items.new('object.select_all', 'A', 'PRESS')
kmi = km.keymap_items.new('object.select_all', 'I', 'PRESS', ctrl=True).action = 'INVERT' kmi = km.keymap_items.new('object.select_all', 'I', 'PRESS', ctrl=True)
kmi.properties.action = 'INVERT'
kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True) kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True)
kmi = km.keymap_items.new('object.select_grouped', 'G', 'PRESS', shift=True) kmi = km.keymap_items.new('object.select_grouped', 'G', 'PRESS', shift=True)
kmi = km.keymap_items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True) kmi = km.keymap_items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)

View File

@@ -9,3 +9,6 @@ settings.default_search_size = 100
settings.default_frames_limit = 0 settings.default_frames_limit = 0
settings.default_pattern_match = 'PREV_FRAME' settings.default_pattern_match = 'PREV_FRAME'
settings.default_margin = 0 settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True

View File

@@ -9,3 +9,6 @@ settings.default_search_size = 61
settings.default_frames_limit = 0 settings.default_frames_limit = 0
settings.default_pattern_match = 'KEYFRAME' settings.default_pattern_match = 'KEYFRAME'
settings.default_margin = 0 settings.default_margin = 0
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True

View File

@@ -9,3 +9,6 @@ settings.default_search_size = 300
settings.default_frames_limit = 0 settings.default_frames_limit = 0
settings.default_pattern_match = 'PREV_FRAME' settings.default_pattern_match = 'PREV_FRAME'
settings.default_margin = 5 settings.default_margin = 5
settings.use_default_red_channel = True
settings.use_default_green_channel = True
settings.use_default_blue_channel = True

View File

@@ -90,6 +90,34 @@ def CLIP_track_view_selected(sc, track):
return False return False
def CLIP_default_settings_from_track(clip, track):
settings = clip.tracking.settings
width = clip.size[0]
height = clip.size[1]
pattern = track.pattern_max - track.pattern_min
search = track.search_max - track.search_min
pattern[0] = pattern[0] * clip.size[0]
pattern[1] = pattern[1] * clip.size[1]
search[0] = search[0] * clip.size[0]
search[1] = search[1] * clip.size[1]
settings.default_tracker = track.tracker
settings.default_pyramid_levels = track.pyramid_levels
settings.default_correlation_min = track.correlation_min
settings.default_pattern_size = max(pattern[0], pattern[1])
settings.default_search_size = max(search[0], search[1])
settings.default_frames_limit = track.frames_limit
settings.default_pattern_match = track.pattern_match
settings.default_margin = track.margin
settings.use_default_red_channel = track.use_red_channel
settings.use_default_green_channel = track.use_green_channel
settings.use_default_blue_channel = track.use_blue_channel
class CLIP_OT_track_to_empty(Operator): class CLIP_OT_track_to_empty(Operator):
"""Create an Empty object which will be copying movement of active track""" """Create an Empty object which will be copying movement of active track"""
@@ -805,3 +833,29 @@ class CLIP_OT_setup_tracking_scene(Operator):
self._setupObjects(context) self._setupObjects(context)
return {'FINISHED'} return {'FINISHED'}
class CLIP_OT_track_settings_as_default(Operator):
"""Copy trackign settings from active track to default settings"""
bl_idname = "clip.track_settings_as_default"
bl_label = "Track Settings As Default"
bl_options = {'UNDO', 'REGISTER'}
@classmethod
def poll(cls, context):
sc = context.space_data
if sc.type != 'CLIP_EDITOR':
return False
clip = sc.clip
return clip and clip.tracking.tracks.active
def execute(self, context):
sc = context.space_data
clip = sc.clip
CLIP_default_settings_from_track(clip, clip.tracking.tracks.active)
return {'FINISHED'}

View File

@@ -409,7 +409,10 @@ class AddPresetTrackingSettings(AddPresetBase, Operator):
"settings.default_search_size", "settings.default_search_size",
"settings.default_frames_limit", "settings.default_frames_limit",
"settings.default_pattern_match", "settings.default_pattern_match",
"settings.default_margin" "settings.default_margin",
"settings.use_default_red_channel",
"settings.use_default_green_channel",
"settings.use_default_blue_channel"
] ]
preset_subdir = "tracking_settings" preset_subdir = "tracking_settings"

View File

@@ -434,25 +434,28 @@ class ConstraintButtonsPanel():
def ACTION(self, context, layout, con): def ACTION(self, context, layout, con):
self.target_template(layout, con) self.target_template(layout, con)
layout.prop(con, "action")
layout.prop(con, "transform_channel")
split = layout.split() split = layout.split()
col = split.column(align=True) col = split.column()
col.label(text="Action Length:") col.label(text="From Target:")
col.prop(con, "frame_start", text="Start") col.prop(con, "transform_channel", text="")
col.prop(con, "frame_end", text="End") col.prop(con, "target_space", text="")
col = split.column()
col.label(text="To Action:")
col.prop(con, "action", text="")
split = layout.split()
col = split.column(align=True) col = split.column(align=True)
col.label(text="Target Range:") col.label(text="Target Range:")
col.prop(con, "min", text="Min") col.prop(con, "min", text="Min")
col.prop(con, "max", text="Max") col.prop(con, "max", text="Max")
row = layout.row() col = split.column(align=True)
row.label(text="Convert:") col.label(text="Action Range:")
row.prop(con, "target_space", text="") col.prop(con, "frame_start", text="Start")
col.prop(con, "frame_end", text="End")
def LOCKED_TRACK(self, context, layout, con): def LOCKED_TRACK(self, context, layout, con):
self.target_template(layout, con) self.target_template(layout, con)

View File

@@ -911,7 +911,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_textures") col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_textures")
split = layout.split(percentage=0.33) split = layout.split(percentage=0.33)
split.label(text="Split uv's:") split.label(text="Split UVs:")
split.prop(part, "billboard_uv_split", text="Number of splits") split.prop(part, "billboard_uv_split", text="Number of splits")
if psys: if psys:

View File

@@ -87,6 +87,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
col.label(text="Damping:") col.label(text="Damping:")
col.prop(cloth, "spring_damping", text="Spring") col.prop(cloth, "spring_damping", text="Spring")
col.prop(cloth, "air_damping", text="Air") col.prop(cloth, "air_damping", text="Air")
col.prop(cloth, "vel_damping", text="Velocity")
col.prop(cloth, "use_pin_cloth", text="Pinning") col.prop(cloth, "use_pin_cloth", text="Pinning")
sub = col.column() sub = col.column()

View File

@@ -79,6 +79,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
sub = col.column(align=True) sub = col.column(align=True)
sub.prop(fluid, "start_time", text="Start") sub.prop(fluid, "start_time", text="Start")
sub.prop(fluid, "end_time", text="End") sub.prop(fluid, "end_time", text="End")
col.prop(fluid, "simulation_rate", text="Speed")
col = split.column() col = split.column()
col.label() col.label()
@@ -230,6 +231,10 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
if fluid.viscosity_preset == 'MANUAL': if fluid.viscosity_preset == 'MANUAL':
sub.prop(fluid, "viscosity_base", text="Base") sub.prop(fluid, "viscosity_base", text="Base")
sub.prop(fluid, "viscosity_exponent", text="Exponent", slider=True) sub.prop(fluid, "viscosity_exponent", text="Exponent", slider=True)
else:
# just for padding to prevent jumping around
sub.separator()
sub.separator()
col.label(text="Optimization:") col.label(text="Optimization:")
col.prop(fluid, "grid_levels", slider=True) col.prop(fluid, "grid_levels", slider=True)

View File

@@ -127,6 +127,13 @@ class CLIP_PT_tools_marker(Panel):
col.separator() col.separator()
row = col.row(align=True)
row.prop(settings, "use_default_red_channel", text="R", toggle=True)
row.prop(settings, "use_default_green_channel", text="G", toggle=True)
row.prop(settings, "use_default_blue_channel", text="B", toggle=True)
col.separator()
sub = col.column(align=True) sub = col.column(align=True)
sub.prop(settings, "default_pattern_size") sub.prop(settings, "default_pattern_size")
sub.prop(settings, "default_search_size") sub.prop(settings, "default_search_size")
@@ -147,6 +154,9 @@ class CLIP_PT_tools_marker(Panel):
col.label(text="Match:") col.label(text="Match:")
col.prop(settings, "default_pattern_match", text="") col.prop(settings, "default_pattern_match", text="")
col.separator()
col.operator('clip.track_settings_as_default', text="Copy From Active Track")
class CLIP_PT_tools_tracking(Panel): class CLIP_PT_tools_tracking(Panel):
bl_space_type = 'CLIP_EDITOR' bl_space_type = 'CLIP_EDITOR'
@@ -172,6 +182,7 @@ class CLIP_PT_tools_tracking(Panel):
props.backwards = True props.backwards = True
props.sequence = True props.sequence = True
props = row.operator("clip.track_markers", text="", icon='PLAY') props = row.operator("clip.track_markers", text="", icon='PLAY')
props.backwards = False
props.sequence = True props.sequence = True
row.operator("clip.track_markers", text="", icon='FRAME_NEXT') row.operator("clip.track_markers", text="", icon='FRAME_NEXT')
@@ -558,6 +569,9 @@ class CLIP_PT_display(Panel):
col.prop(sc, "lock_selection") col.prop(sc, "lock_selection")
if sc.view == 'GRAPH':
col.prop(sc, "lock_time_cursor")
clip = sc.clip clip = sc.clip
if clip: if clip:
col.label(text="Display Aspect Ratio:") col.label(text="Display Aspect Ratio:")

View File

@@ -68,7 +68,7 @@ class LOGIC_PT_properties(Panel):
row = box.row() row = box.row()
row.prop(prop, "name", text="") row.prop(prop, "name", text="")
row.prop(prop, "type", text="") row.prop(prop, "type", text="")
row.prop(prop, "value", text="", toggle=True) # we don't care about the type. rna will display correctly row.prop(prop, "value", text="")
row.prop(prop, "show_debug", text="", toggle=True, icon='INFO') row.prop(prop, "show_debug", text="", toggle=True, icon='INFO')
row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i

View File

@@ -58,6 +58,11 @@ class NODE_HT_header(Header):
# Don't show "Use Nodes" Button when Engine is BI for Lamps # Don't show "Use Nodes" Button when Engine is BI for Lamps
if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'): if snode_id and not (scene.render.use_shading_nodes == 0 and ob.type == 'LAMP'):
layout.prop(snode_id, "use_nodes") layout.prop(snode_id, "use_nodes")
if snode.shader_type == 'WORLD':
layout.template_ID(scene, "world", new="world.new")
if snode_id:
layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'TEXTURE': elif snode.tree_type == 'TEXTURE':
layout.prop(snode, "texture_type", text="", expand=True) layout.prop(snode, "texture_type", text="", expand=True)

View File

@@ -526,9 +526,9 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
if brush.use_space and tool != 'SMOOTH': if brush.use_space and tool != 'SMOOTH':
if brush.use_space_atten: if brush.use_space_atten:
row.prop(brush, "use_space_atten", toggle=True, icon='LOCKED') row.prop(brush, "use_space_atten", toggle=True, text="", icon='LOCKED')
else: else:
row.prop(brush, "use_space_atten", toggle=True, icon='UNLOCKED') row.prop(brush, "use_space_atten", toggle=True, text="", icon='UNLOCKED')
self.prop_unified_strength(row, context, brush, "strength", text="Strength") self.prop_unified_strength(row, context, brush, "strength", text="Strength")
self.prop_unified_strength(row, context, brush, "use_pressure_strength") self.prop_unified_strength(row, context, brush, "use_pressure_strength")

View File

@@ -42,6 +42,10 @@
#include "endian.h" #include "endian.h"
#include "avi_intern.h" #include "avi_intern.h"
#ifdef __BIG_ENDIAN__
#include "MEM_guardedalloc.h"
#endif
#ifdef __BIG_ENDIAN__ #ifdef __BIG_ENDIAN__
static void invert (int *num) static void invert (int *num)
{ {

View File

@@ -538,6 +538,15 @@ int sculpt_get_deform_matrices(struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]); float (**deformmats)[3][3], float (**deformcos)[3]);
void weight_to_rgb(float r_rgb[3], const float weight); void weight_to_rgb(float r_rgb[3], const float weight);
/* Update the weight MCOL preview layer.
* If weights are NULL, use object's active vgroup(s).
* Else, weights must be an array of weight float values.
* If indices is NULL, it must be of numVerts length.
* Else, it must be of num length, as indices, which contains vertices' idx to apply weights to.
* (other vertices are assumed zero weight).
*/
void DM_update_weight_mcol(struct Object *ob, struct DerivedMesh *dm, int const draw_flag,
float *weights, int num, const int *indices);
/* convert layers requested by a GLSL material to actually available layers in /* convert layers requested by a GLSL material to actually available layers in
* the DerivedMesh, with both a pointer for arrays and an offset for editmesh */ * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */

View File

@@ -86,7 +86,7 @@ int bone_autoside_name (char name[64], int strip_number, short axis, float head,
struct Bone *get_named_bone (struct bArmature *arm, const char *name); struct Bone *get_named_bone (struct bArmature *arm, const char *name);
float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist); float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist);
void where_is_armature (struct bArmature *arm); void where_is_armature (struct bArmature *arm);
void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone);

View File

@@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines. * and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */ * Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 261 #define BLENDER_VERSION 261
#define BLENDER_SUBVERSION 3 #define BLENDER_SUBVERSION 4
#define BLENDER_MINVERSION 250 #define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0 #define BLENDER_MINSUBVERSION 0
@@ -51,7 +51,7 @@ extern "C" {
/* can be left blank, otherwise a,b,c... etc with no quotes */ /* can be left blank, otherwise a,b,c... etc with no quotes */
#define BLENDER_VERSION_CHAR #define BLENDER_VERSION_CHAR
/* alpha/beta/rc/release, docs use this */ /* alpha/beta/rc/release, docs use this */
#define BLENDER_VERSION_CYCLE alpha #define BLENDER_VERSION_CYCLE beta
extern char versionstr[]; /* from blender.c */ extern char versionstr[]; /* from blender.c */

View File

@@ -216,7 +216,7 @@ void clmdSetInterruptCallBack ( int ( *f ) ( void ) );
void cloth_free_modifier_extern ( struct ClothModifierData *clmd ); void cloth_free_modifier_extern ( struct ClothModifierData *clmd );
void cloth_free_modifier ( struct ClothModifierData *clmd ); void cloth_free_modifier ( struct ClothModifierData *clmd );
void cloth_init ( struct ClothModifierData *clmd ); void cloth_init ( struct ClothModifierData *clmd );
struct DerivedMesh *clothModifier_do ( struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); void clothModifier_do ( struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]);
void cloth_update_normals ( ClothVertex *verts, int nVerts, struct MFace *face, int totface ); void cloth_update_normals ( ClothVertex *verts, int nVerts, struct MFace *face, int totface );
int cloth_uses_vgroup(struct ClothModifierData *clmd); int cloth_uses_vgroup(struct ClothModifierData *clmd);

View File

@@ -67,7 +67,7 @@ extern const CustomDataMask CD_MASK_FACECORNERS;
#define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source #define CD_DUPLICATE 4 /* do a full copy of all layers, only allowed if source
has same number of elements */ has same number of elements */
#define CD_TYPE_AS_MASK(_type) (CustomDataMask)(1 << (CustomDataMask)(_type)) #define CD_TYPE_AS_MASK(_type) (CustomDataMask)((CustomDataMask)1 << (CustomDataMask)(_type))
/* initialises a CustomData object with the same layer setup as source. /* initialises a CustomData object with the same layer setup as source.
* mask is a bitfield where (mask & (1 << (layer type))) indicates * mask is a bitfield where (mask & (1 << (layer type))) indicates

View File

@@ -99,7 +99,10 @@ typedef enum {
eModifierTypeFlag_Single = (1<<7), eModifierTypeFlag_Single = (1<<7),
/* Some modifier can't be added manually by user */ /* Some modifier can't be added manually by user */
eModifierTypeFlag_NoUserAdd = (1<<8) eModifierTypeFlag_NoUserAdd = (1<<8),
/* For modifiers that use CD_WEIGHT_MCOL for preview. */
eModifierTypeFlag_UsesPreview = (1<<9)
} ModifierTypeFlag; } ModifierTypeFlag;
typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin); typedef void (*ObjectWalkFunc)(void *userData, struct Object *ob, struct Object **obpoin);
@@ -323,6 +326,7 @@ void modifier_setError(struct ModifierData *md, const char *format, ...
__attribute__ ((format (printf, 2, 3))) __attribute__ ((format (printf, 2, 3)))
#endif #endif
; ;
int modifier_isPreview(struct ModifierData *md);
void modifiers_foreachObjectLink(struct Object *ob, void modifiers_foreachObjectLink(struct Object *ob,
ObjectWalkFunc walk, ObjectWalkFunc walk,
@@ -349,6 +353,7 @@ struct Object *modifiers_isDeformedByLattice(struct Object *ob);
int modifiers_usesArmature(struct Object *ob, struct bArmature *arm); int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
int modifiers_isCorrectableDeformed(struct Object *ob); int modifiers_isCorrectableDeformed(struct Object *ob);
void modifier_freeTemporaryData(struct ModifierData *md); void modifier_freeTemporaryData(struct ModifierData *md);
int modifiers_isPreview(struct Object *ob);
int modifiers_indexInObject(struct Object *ob, struct ModifierData *md); int modifiers_indexInObject(struct Object *ob, struct ModifierData *md);
@@ -362,6 +367,9 @@ struct LinkNode *modifiers_calcDataMasks(struct Scene *scene,
struct ModifierData *md, struct ModifierData *md,
CustomDataMask dataMask, CustomDataMask dataMask,
int required_mode); int required_mode);
struct ModifierData *modifiers_getLastPreview(struct Scene *scene,
struct ModifierData *md,
int required_mode);
struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob); struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob);
/* ensure modifier correctness when changing ob->data */ /* ensure modifier correctness when changing ob->data */

View File

@@ -523,6 +523,7 @@ struct ShadeResult;
#define SH_NODE_VOLUME_ISOTROPIC 162 #define SH_NODE_VOLUME_ISOTROPIC 162
#define SH_NODE_GAMMA 163 #define SH_NODE_GAMMA 163
#define SH_NODE_TEX_CHECKER 164 #define SH_NODE_TEX_CHECKER 164
#define SH_NODE_BRIGHTCONTRAST 165
/* custom defines options for Material node */ /* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1 #define SH_NODE_MAT_DIFF 1
@@ -556,25 +557,34 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
/* ************** COMPOSITE NODES *************** */ /* ************** COMPOSITE NODES *************** */
/* output socket defines */ /* output socket defines */
#define RRES_OUT_IMAGE 0 #define RRES_OUT_IMAGE 0
#define RRES_OUT_ALPHA 1 #define RRES_OUT_ALPHA 1
#define RRES_OUT_Z 2 #define RRES_OUT_Z 2
#define RRES_OUT_NORMAL 3 #define RRES_OUT_NORMAL 3
#define RRES_OUT_UV 4 #define RRES_OUT_UV 4
#define RRES_OUT_VEC 5 #define RRES_OUT_VEC 5
#define RRES_OUT_RGBA 6 #define RRES_OUT_RGBA 6
#define RRES_OUT_DIFF 7 #define RRES_OUT_DIFF 7
#define RRES_OUT_SPEC 8 #define RRES_OUT_SPEC 8
#define RRES_OUT_SHADOW 9 #define RRES_OUT_SHADOW 9
#define RRES_OUT_AO 10 #define RRES_OUT_AO 10
#define RRES_OUT_REFLECT 11 #define RRES_OUT_REFLECT 11
#define RRES_OUT_REFRACT 12 #define RRES_OUT_REFRACT 12
#define RRES_OUT_INDIRECT 13 #define RRES_OUT_INDIRECT 13
#define RRES_OUT_INDEXOB 14 #define RRES_OUT_INDEXOB 14
#define RRES_OUT_INDEXMA 15 #define RRES_OUT_INDEXMA 15
#define RRES_OUT_MIST 16 #define RRES_OUT_MIST 16
#define RRES_OUT_EMIT 17 #define RRES_OUT_EMIT 17
#define RRES_OUT_ENV 18 #define RRES_OUT_ENV 18
#define RRES_OUT_DIFF_DIRECT 19
#define RRES_OUT_DIFF_INDIRECT 20
#define RRES_OUT_DIFF_COLOR 21
#define RRES_OUT_GLOSSY_DIRECT 22
#define RRES_OUT_GLOSSY_INDIRECT 23
#define RRES_OUT_GLOSSY_COLOR 24
#define RRES_OUT_TRANSM_DIRECT 25
#define RRES_OUT_TRANSM_INDIRECT 26
#define RRES_OUT_TRANSM_COLOR 27
/* note: types are needed to restore callbacks, don't change values */ /* note: types are needed to restore callbacks, don't change values */
#define CMP_NODE_VIEWER 201 #define CMP_NODE_VIEWER 201

View File

@@ -61,6 +61,7 @@ struct MovieTrackingMarker *BKE_tracking_get_marker(struct MovieTrackingTrack *t
struct MovieTrackingMarker *BKE_tracking_ensure_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_ensure_marker(struct MovieTrackingTrack *track, int framenr);
struct MovieTrackingMarker *BKE_tracking_exact_marker(struct MovieTrackingTrack *track, int framenr); struct MovieTrackingMarker *BKE_tracking_exact_marker(struct MovieTrackingTrack *track, int framenr);
int BKE_tracking_has_marker(struct MovieTrackingTrack *track, int framenr); int BKE_tracking_has_marker(struct MovieTrackingTrack *track, int framenr);
int BKE_tracking_has_enabled_marker(struct MovieTrackingTrack *track, int framenr);
void BKE_tracking_free_track(struct MovieTrackingTrack *track); void BKE_tracking_free_track(struct MovieTrackingTrack *track);

View File

@@ -722,24 +722,23 @@ void vDM_ColorBand_store(ColorBand *coba)
* note that we could save some memory and allocate RGB only but then we'd need to * note that we could save some memory and allocate RGB only but then we'd need to
* re-arrange the colors when copying to the face since MCol has odd ordering, * re-arrange the colors when copying to the face since MCol has odd ordering,
* so leave this as is - campbell */ * so leave this as is - campbell */
static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_flag, ColorBand *coba) static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba)
{ {
Mesh *me = ob->data; MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * me->totvert * 4, "weightmap_v"); int numVerts = dm->getNumVerts(dm);
unsigned char *wtcol_v = MEM_mallocN (sizeof(unsigned char) * numVerts * 4, "weightmap_v");
if (me->dvert) { if (dv) {
unsigned char *wc = wtcol_v; unsigned char *wc = wtcol_v;
MDeformVert *dv= me->dvert;
unsigned int i; unsigned int i;
/* varisbles for multipaint */ /* variables for multipaint */
const int defbase_tot = BLI_countlist(&ob->defbase); const int defbase_tot = BLI_countlist(&ob->defbase);
const int defbase_act = ob->actdef-1; const int defbase_act = ob->actdef-1;
char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__); char *dg_flags = MEM_mallocN(defbase_tot * sizeof(char), __func__);
const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot); const int selected = get_selected_defgroups(ob, dg_flags, defbase_tot);
/* const int unselected = defbase_tot - selected; */ /* UNUSED */
for (i = me->totvert; i != 0; i--, wc += 4, dv++) { for (i = numVerts; i != 0; i--, wc += 4, dv++) {
calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag); calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, dg_flags, selected, draw_flag);
} }
@@ -748,48 +747,94 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, int const draw_fla
else { else {
int col_i; int col_i;
weightpaint_color((unsigned char *)&col_i, coba, 0.0f); weightpaint_color((unsigned char *)&col_i, coba, 0.0f);
fill_vn_i((int *)wtcol_v, me->totvert, col_i); fill_vn_i((int *)wtcol_v, numVerts, col_i);
} }
return wtcol_v; return wtcol_v;
} }
static void add_weight_mcol_dm(Object *ob, DerivedMesh *dm, int const draw_flag) /* return an array of vertex weight colors from given weights, caller must free.
*
* note that we could save some memory and allocate RGB only but then we'd need to
* re-arrange the colors when copying to the face since MCol has odd ordering,
* so leave this as is - campbell */
static unsigned char *calc_colors_from_weights_array(const int num, float *weights)
{
unsigned char *wtcol_v = MEM_mallocN(sizeof(unsigned char) * num * 4, "weightmap_v");
unsigned char *wc = wtcol_v;
int i;
for (i = 0; i < num; i++, wc += 4, weights++)
weightpaint_color((unsigned char *) wc, NULL, *weights);
return wtcol_v;
}
void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag,
float *weights, int num, const int *indices)
{ {
ColorBand *coba= stored_cb; /* warning, not a local var */ ColorBand *coba= stored_cb; /* warning, not a local var */
Mesh *me = ob->data; MFace *mf = dm->getFaceArray(dm);
unsigned char *wtcol_v = calc_weightpaint_vert_array(ob, draw_flag, coba); int numFaces = dm->getNumFaces(dm);
unsigned char *wtcol_f = MEM_mallocN (sizeof(unsigned char) * me->totface*4*4, "weightmap_f"); int numVerts = dm->getNumVerts(dm);
unsigned char *wtcol_f_step = wtcol_f; unsigned char *wtcol_v;
unsigned char *wtcol_f = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
MFace *mf = me->mface;
int i; int i;
for (i=0; i<me->totface; i++, mf++, wtcol_f_step += (4 * 4)) { /* If no CD_WEIGHT_MCOL existed yet, add a new one! */
if (!wtcol_f)
wtcol_f = CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numFaces);
if (wtcol_f) {
unsigned char *wtcol_f_step = wtcol_f;
/* Weights are given by caller. */
if (weights) {
float *w = weights;
/* If indices is not NULL, it means we do not have weights for all vertices,
* so we must create them (and set them to zero)... */
if(indices) {
w = MEM_callocN(sizeof(float)*numVerts, "Temp weight array DM_update_weight_mcol");
i = num;
while(i--)
w[indices[i]] = weights[i];
}
/* Convert float weights to colors. */
wtcol_v = calc_colors_from_weights_array(numVerts, w);
if(indices)
MEM_freeN(w);
}
/* No weights given, take them from active vgroup(s). */
else
wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba);
/* Now copy colors in all face verts. */
for (i = 0; i < numFaces; i++, mf++, wtcol_f_step += (4 * 4)) {
#if 0 #if 0
unsigned int fidx= mf->v4 ? 3:2; unsigned int fidx= mf->v4 ? 3:2;
#else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */ #else /* better zero out triangles 4th component. else valgrind complains when the buffer's copied */
unsigned int fidx; unsigned int fidx;
if (mf->v4) { if (mf->v4) {
fidx = 3; fidx = 3;
} }
else { else {
fidx = 2; fidx = 2;
*(int *)(&wtcol_f_step[3 * 4]) = 0; *(int *)(&wtcol_f_step[3 * 4]) = 0;
} }
#endif #endif
do { do {
copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4], copy_v4_v4_char((char *)&wtcol_f_step[fidx * 4],
(char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]); (char *)&wtcol_v[4 * (*(&mf->v1 + fidx))]);
} while (fidx--); } while (fidx--);
}
MEM_freeN(wtcol_v);
} }
MEM_freeN(wtcol_v);
CustomData_add_layer(&dm->faceData, CD_WEIGHT_MCOL, CD_ASSIGN, wtcol_f, dm->numFaceData);
} }
/* new value for useDeform -1 (hack for the gameengine): /* new value for useDeform -1 (hack for the gameengine):
@@ -803,7 +848,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
int needMapping, CustomDataMask dataMask, int index, int useCache) int needMapping, CustomDataMask dataMask, int index, int useCache)
{ {
Mesh *me = ob->data; Mesh *me = ob->data;
ModifierData *firstmd, *md; ModifierData *firstmd, *md, *previewmd = NULL;
LinkNode *datamasks, *curr; LinkNode *datamasks, *curr;
CustomDataMask mask, nextmask, append_mask = 0; CustomDataMask mask, nextmask, append_mask = 0;
float (*deformedVerts)[3] = NULL; float (*deformedVerts)[3] = NULL;
@@ -816,8 +861,17 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
int has_multires = mmd != NULL, multires_applied = 0; int has_multires = mmd != NULL, multires_applied = 0;
int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; int sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt;
int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) | const int draw_flag= ((scene->toolsettings->multipaint ? CALC_WP_MULTIPAINT : 0) |
(scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0)); (scene->toolsettings->auto_normalize ? CALC_WP_AUTO_NORMALIZE : 0));
/* Generic preview only in object mode! */
const int do_mod_mcol = (ob->mode == OB_MODE_OBJECT);
#if 0 /* XXX Will re-enable this when we have global mod stack options. */
const int do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol;
#endif
const int do_final_wmcol = FALSE;
int do_init_wmcol = ((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol);
/* XXX Same as above... For now, only weights preview in WPaint mode. */
const int do_mod_wmcol = do_init_wmcol;
if(mmd && !mmd->sculptlvl) if(mmd && !mmd->sculptlvl)
has_multires = 0; has_multires = 0;
@@ -842,6 +896,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode); datamasks = modifiers_calcDataMasks(scene, ob, md, dataMask, required_mode);
curr = datamasks; curr = datamasks;
if(do_mod_wmcol || do_mod_mcol) {
/* Find the last active modifier generating a preview, or NULL if none. */
/* XXX Currently, DPaint modifier just ignores this.
* Needs a stupid hack...
* The whole "modifier preview" thing has to be (re?)designed, anyway! */
previewmd = modifiers_getLastPreview(scene, md, required_mode);
}
if(deform_r) *deform_r = NULL; if(deform_r) *deform_r = NULL;
*final_r = NULL; *final_r = NULL;
@@ -997,8 +1059,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_calc_normals(dm); CDDM_calc_normals(dm);
} }
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) if(do_init_wmcol)
add_weight_mcol_dm(ob, dm, draw_flag); DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL);
/* Constructive modifiers need to have an origindex /* Constructive modifiers need to have an origindex
* otherwise they wont have anywhere to copy the data from. * otherwise they wont have anywhere to copy the data from.
@@ -1085,8 +1147,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
} }
/* in case of dynamic paint, make sure preview mask remains for following modifiers */ /* in case of dynamic paint, make sure preview mask remains for following modifiers */
/* XXX Temp and hackish solution! */
if (md->type == eModifierType_DynamicPaint) if (md->type == eModifierType_DynamicPaint)
append_mask |= CD_MASK_WEIGHT_MCOL; append_mask |= CD_MASK_WEIGHT_MCOL;
/* In case of active preview modifier, make sure preview mask remains for following modifiers. */
else if ((md == previewmd) && (do_mod_wmcol)) {
DM_update_weight_mcol(ob, dm, draw_flag, NULL, 0, NULL);
append_mask |= CD_MASK_WEIGHT_MCOL;
}
} }
isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform); isPrevDeform= (mti->type == eModifierTypeType_OnlyDeform);
@@ -1114,10 +1182,19 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_apply_vert_coords(finaldm, deformedVerts); CDDM_apply_vert_coords(finaldm, deformedVerts);
CDDM_calc_normals(finaldm); CDDM_calc_normals(finaldm);
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) #if 0 /* For later nice mod preview! */
add_weight_mcol_dm(ob, finaldm, draw_flag); /* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */
if(do_final_wmcol)
DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
#endif
} else if(dm) { } else if(dm) {
finaldm = dm; finaldm = dm;
#if 0 /* For later nice mod preview! */
/* In case we need modified weights in CD_WEIGHT_MCOL, we have to re-compute it. */
if(do_final_wmcol)
DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
#endif
} else { } else {
finaldm = CDDM_from_mesh(me, ob); finaldm = CDDM_from_mesh(me, ob);
@@ -1126,8 +1203,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
CDDM_calc_normals(finaldm); CDDM_calc_normals(finaldm);
} }
if((dataMask & CD_MASK_WEIGHT_MCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT)) /* In this case, we should never have weight-modifying modifiers in stack... */
add_weight_mcol_dm(ob, finaldm, draw_flag); if(do_init_wmcol)
DM_update_weight_mcol(ob, finaldm, draw_flag, NULL, 0, NULL);
} }
/* add an orco layer if needed */ /* add an orco layer if needed */

View File

@@ -665,7 +665,7 @@ static void b_bone_deform(bPoseChanDeform *pdef_info, Bone *bone, float *co, Dua
} }
/* using vec with dist to bone b1 - b2 */ /* using vec with dist to bone b1 - b2 */
float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, float rad2, float rdist) float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist)
{ {
float dist=0.0f; float dist=0.0f;
float bdelta[3]; float bdelta[3];
@@ -677,18 +677,18 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl
sub_v3_v3v3(pdelta, vec, b1); sub_v3_v3v3(pdelta, vec, b1);
a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2]; a = dot_v3v3(bdelta, pdelta);
hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2])); hsqr = dot_v3v3(pdelta, pdelta);
if (a < 0.0F){ if (a < 0.0f) {
/* If we're past the end of the bone, do a spherical field attenuation thing */ /* If we're past the end of the bone, do a spherical field attenuation thing */
dist= ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ; dist = len_squared_v3v3(b1, vec);
rad= rad1; rad= rad1;
} }
else if (a > l){ else if (a > l) {
/* If we're past the end of the bone, do a spherical field attenuation thing */ /* If we're past the end of the bone, do a spherical field attenuation thing */
dist= ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ; dist = len_squared_v3v3(b2, vec);
rad= rad2; rad = rad2;
} }
else { else {
dist= (hsqr - (a*a)); dist= (hsqr - (a*a));
@@ -709,7 +709,7 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl
if(rdist==0.0f || dist >= l) if(rdist==0.0f || dist >= l)
return 0.0f; return 0.0f;
else { else {
a= (float)sqrt(dist)-rad; a = sqrtf(dist)-rad;
return 1.0f-( a*a )/( rdist*rdist ); return 1.0f-( a*a )/( rdist*rdist );
} }
} }

View File

@@ -90,7 +90,7 @@ static CM_SOLVER_DEF solvers [] =
/* ********** cloth engine ******* */ /* ********** cloth engine ******* */
/* Prototypes for internal functions. /* Prototypes for internal functions.
*/ */
static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]);
static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm );
static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first);
static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm );
@@ -130,6 +130,7 @@ void cloth_init ( ClothModifierData *clmd )
clmd->sim_parms->presets = 2; /* cotton as start setting */ clmd->sim_parms->presets = 2; /* cotton as start setting */
clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */ clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */
clmd->sim_parms->reset = 0; clmd->sim_parms->reset = 0;
clmd->sim_parms->vel_damping = 1.0f; /* 1.0 = no damping, 0.0 = fully dampened */
clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->self_friction = 5.0;
clmd->coll_parms->friction = 5.0; clmd->coll_parms->friction = 5.0;
@@ -428,9 +429,8 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
/************************************************ /************************************************
* clothModifier_do - main simulation function * clothModifier_do - main simulation function
************************************************/ ************************************************/
DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm) void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
{ {
DerivedMesh *result;
PointCache *cache; PointCache *cache;
PTCacheID pid; PTCacheID pid;
float timescale; float timescale;
@@ -440,20 +440,14 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
clmd->scene= scene; /* nice to pass on later :) */ clmd->scene= scene; /* nice to pass on later :) */
framenr= (int)scene->r.cfra; framenr= (int)scene->r.cfra;
cache= clmd->point_cache; cache= clmd->point_cache;
result = CDDM_copy(dm);
BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_from_cloth(&pid, ob, clmd);
BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, &timescale);
clmd->sim_parms->timescale= timescale; clmd->sim_parms->timescale= timescale;
if(!result) {
BKE_ptcache_invalidate(cache);
return dm;
}
if(clmd->sim_parms->reset if(clmd->sim_parms->reset
|| (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0) || (framenr == (startframe - clmd->sim_parms->preroll) && clmd->sim_parms->preroll != 0)
|| (clmd->clothObject && result->getNumVerts(result) != clmd->clothObject->numverts)) || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->numverts))
{ {
clmd->sim_parms->reset = 0; clmd->sim_parms->reset = 0;
cache->flag |= PTCACHE_OUTDATED; cache->flag |= PTCACHE_OUTDATED;
@@ -461,7 +455,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
BKE_ptcache_validate(cache, 0); BKE_ptcache_validate(cache, 0);
cache->last_exact= 0; cache->last_exact= 0;
cache->flag &= ~PTCACHE_REDO_NEEDED; cache->flag &= ~PTCACHE_REDO_NEEDED;
return result; return;
} }
// unused in the moment, calculated separately in implicit.c // unused in the moment, calculated separately in implicit.c
@@ -473,20 +467,20 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
/* do simulation */ /* do simulation */
if(!do_init_cloth(ob, clmd, dm, framenr)) if(!do_init_cloth(ob, clmd, dm, framenr))
return result; return;
do_step_cloth(ob, clmd, dm, framenr); do_step_cloth(ob, clmd, dm, framenr);
cloth_to_object(ob, clmd, result); cloth_to_object(ob, clmd, vertexCos);
clmd->clothObject->last_frame= framenr; clmd->clothObject->last_frame= framenr;
return result; return;
} }
/* simulation is only active during a specific period */ /* simulation is only active during a specific period */
if(framenr < startframe) { if(framenr < startframe) {
BKE_ptcache_invalidate(cache); BKE_ptcache_invalidate(cache);
return result; return;
} }
else if(framenr > endframe) { else if(framenr > endframe) {
framenr= endframe; framenr= endframe;
@@ -494,7 +488,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
/* initialize simulation data if it didn't exist already */ /* initialize simulation data if it didn't exist already */
if(!do_init_cloth(ob, clmd, dm, framenr)) if(!do_init_cloth(ob, clmd, dm, framenr))
return result; return;
if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { if((framenr == startframe) && (clmd->sim_parms->preroll == 0)) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
@@ -502,7 +496,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
BKE_ptcache_validate(cache, framenr); BKE_ptcache_validate(cache, framenr);
cache->flag &= ~PTCACHE_REDO_NEEDED; cache->flag &= ~PTCACHE_REDO_NEEDED;
clmd->clothObject->last_frame= framenr; clmd->clothObject->last_frame= framenr;
return result; return;
} }
/* try to read from cache */ /* try to read from cache */
@@ -510,7 +504,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
implicit_set_positions(clmd); implicit_set_positions(clmd);
cloth_to_object (ob, clmd, result); cloth_to_object (ob, clmd, vertexCos);
BKE_ptcache_validate(cache, framenr); BKE_ptcache_validate(cache, framenr);
@@ -519,7 +513,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
clmd->clothObject->last_frame= framenr; clmd->clothObject->last_frame= framenr;
return result; return;
} }
else if(cache_result==PTCACHE_READ_OLD) { else if(cache_result==PTCACHE_READ_OLD) {
implicit_set_positions(clmd); implicit_set_positions(clmd);
@@ -527,11 +521,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ else if( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */
/* if baked and nothing in cache, do nothing */ /* if baked and nothing in cache, do nothing */
BKE_ptcache_invalidate(cache); BKE_ptcache_invalidate(cache);
return result; return;
} }
if(framenr!=clmd->clothObject->last_frame+1) if(framenr!=clmd->clothObject->last_frame+1)
return result; return;
/* if on second frame, write cache for first frame */ /* if on second frame, write cache for first frame */
if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
@@ -548,10 +542,8 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
else else
BKE_ptcache_write(&pid, framenr); BKE_ptcache_write(&pid, framenr);
cloth_to_object (ob, clmd, result); cloth_to_object (ob, clmd, vertexCos);
clmd->clothObject->last_frame= framenr; clmd->clothObject->last_frame= framenr;
return result;
} }
/* frees all */ /* frees all */
@@ -706,24 +698,19 @@ void cloth_free_modifier_extern ( ClothModifierData *clmd )
* cloth_to_object - copies the deformed vertices to the object. * cloth_to_object - copies the deformed vertices to the object.
* *
**/ **/
static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm) static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3])
{ {
unsigned int i = 0; unsigned int i = 0;
MVert *mvert = NULL;
unsigned int numverts;
Cloth *cloth = clmd->clothObject; Cloth *cloth = clmd->clothObject;
if (clmd->clothObject) { if (clmd->clothObject) {
/* inverse matrix is not uptodate... */ /* inverse matrix is not uptodate... */
invert_m4_m4(ob->imat, ob->obmat); invert_m4_m4(ob->imat, ob->obmat);
mvert = CDDM_get_verts(dm); for (i = 0; i < cloth->numverts; i++)
numverts = dm->getNumVerts(dm);
for (i = 0; i < numverts; i++)
{ {
copy_v3_v3 (mvert[i].co, cloth->verts[i].x); copy_v3_v3 (vertexCos[i], cloth->verts[i].x);
mul_m4_v3(ob->imat, mvert[i].co); /* cloth is in global coords */ mul_m4_v3(ob->imat, vertexCos[i]); /* cloth is in global coords */
} }
} }
} }

View File

@@ -2775,8 +2775,7 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
/* store Z orientation before destroying obmat */ /* store Z orientation before destroying obmat */
normalize_v3_v3(zz, cob->matrix[2]); normalize_v3_v3(zz, cob->matrix[2]);
dist = len_v3v3(cob->matrix[3], ct->matrix[3]); /* XXX That makes the constraint buggy with asymmetrically scaled objects, see #29940. */
/* XXX What was all that for??? Makes the constraint buggy with scaled objects, see #29940. */
/* sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);*/ /* sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]);*/
/* vec[0] /= size[0];*/ /* vec[0] /= size[0];*/
/* vec[1] /= size[1];*/ /* vec[1] /= size[1];*/
@@ -2784,10 +2783,14 @@ static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
/* dist = normalize_v3(vec);*/ /* dist = normalize_v3(vec);*/
dist = len_v3v3(cob->matrix[3], ct->matrix[3]);
/* Only Y constrained object axis scale should be used, to keep same length when scaling it. */
dist /= size[1];
/* data->orglength==0 occurs on first run, and after 'R' button is clicked */ /* data->orglength==0 occurs on first run, and after 'R' button is clicked */
if (data->orglength == 0) if (data->orglength == 0)
data->orglength = dist; data->orglength = dist;
if (data->bulge == 0) if (data->bulge == 0)
data->bulge = 1.0; data->bulge = 1.0;
scale[1] = dist/data->orglength; scale[1] = dist/data->orglength;

View File

@@ -833,6 +833,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
int editmode = (!forRender && cu->editnurb); int editmode = (!forRender && cu->editnurb);
DerivedMesh *dm= NULL, *ndm; DerivedMesh *dm= NULL, *ndm;
float (*vertCos)[3] = NULL; float (*vertCos)[3] = NULL;
int useCache = !forRender;
if(forRender) required_mode = eModifierMode_Render; if(forRender) required_mode = eModifierMode_Render;
else required_mode = eModifierMode_Realtime; else required_mode = eModifierMode_Realtime;
@@ -911,7 +912,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
vertCos= NULL; vertCos= NULL;
} }
ndm = mti->applyModifier(md, ob, dm, forRender, editmode); ndm = mti->applyModifier(md, ob, dm, forRender, useCache);
if (ndm) { if (ndm) {
/* Modifier returned a new derived mesh */ /* Modifier returned a new derived mesh */

View File

@@ -97,6 +97,10 @@ static int neighY[8] = {0,1,1, 1, 0,-1,-1,-1};
/* brush mesh raycast status */ /* brush mesh raycast status */
#define HIT_VOLUME 1 #define HIT_VOLUME 1
#define HIT_PROXIMITY 2 #define HIT_PROXIMITY 2
/* dynamicPaint_findNeighbourPixel() return codes */
#define NOT_FOUND -1
#define ON_MESH_EDGE -2
#define OUT_OF_TEXTURE -3
/* paint effect default movement per frame in global units */ /* paint effect default movement per frame in global units */
#define EFF_MOVEMENT_PER_FRAME 0.05f #define EFF_MOVEMENT_PER_FRAME 0.05f
/* initial wave time factor */ /* initial wave time factor */
@@ -134,10 +138,10 @@ typedef struct Vec3f {
float v[3]; float v[3];
} Vec3f; } Vec3f;
typedef struct BakeNeighPoint { typedef struct BakeAdjPoint {
float dir[3]; /* vector pointing towards this neighbour */ float dir[3]; /* vector pointing towards this neighbour */
float dist; /* distance to */ float dist; /* distance to */
} BakeNeighPoint; } BakeAdjPoint;
/* Surface data used while processing a frame */ /* Surface data used while processing a frame */
typedef struct PaintBakeNormal { typedef struct PaintBakeNormal {
@@ -156,7 +160,7 @@ typedef struct PaintBakeData {
Bounds3D mesh_bounds; Bounds3D mesh_bounds;
/* adjacency info */ /* adjacency info */
BakeNeighPoint *bNeighs; /* current global neighbour distances and directions, if required */ BakeAdjPoint *bNeighs; /* current global neighbour distances and directions, if required */
double average_dist; double average_dist;
/* space partitioning */ /* space partitioning */
VolumeGrid *grid; /* space partitioning grid to optimize brush checks */ VolumeGrid *grid; /* space partitioning grid to optimize brush checks */
@@ -188,13 +192,6 @@ typedef struct ImgSeqFormatData {
Vec3f *barycentricWeights; /* b-weights for all pixel samples */ Vec3f *barycentricWeights; /* b-weights for all pixel samples */
} ImgSeqFormatData; } ImgSeqFormatData;
#if 0 /* UNUSED */
typedef struct EffVelPoint {
float previous_pos[3];
float previous_vel[3];
} EffVelPoint;
#endif
/* adjacency data flags */ /* adjacency data flags */
#define ADJ_ON_MESH_EDGE (1<<0) #define ADJ_ON_MESH_EDGE (1<<0)
@@ -470,19 +467,25 @@ static void object_cacheIgnoreClear(Object *ob, int state)
BLI_freelistN(&pidlist); BLI_freelistN(&pidlist);
} }
static void subframe_updateObject(Scene *scene, Object *ob, int flags, float frame) static int subframe_updateObject(Scene *scene, Object *ob, int flags, float frame)
{ {
DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
bConstraint *con; bConstraint *con;
/* if other is dynamic paint canvas, dont update */ /* if other is dynamic paint canvas, dont update */
if (pmd && pmd->canvas) if (pmd && pmd->canvas)
return; return 1;
/* if object has parents, update them too */ /* if object has parents, update them too */
if (flags & UPDATE_PARENTS) { if (flags & UPDATE_PARENTS) {
if (ob->parent) subframe_updateObject(scene, ob->parent, 0, frame); int is_canvas = 0;
if (ob->track) subframe_updateObject(scene, ob->track, 0, frame); if (ob->parent) is_canvas += subframe_updateObject(scene, ob->parent, 0, frame);
if (ob->track) is_canvas += subframe_updateObject(scene, ob->track, 0, frame);
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
if (is_canvas && (ob->partype == PARVERT1 || ob->partype == PARVERT3))
return 0;
/* also update constraint targets */ /* also update constraint targets */
for (con = ob->constraints.first; con; con=con->next) { for (con = ob->constraints.first; con; con=con->next) {
@@ -519,6 +522,8 @@ static void subframe_updateObject(Scene *scene, Object *ob, int flags, float fra
} }
else else
where_is_object_time(scene, ob, frame); where_is_object_time(scene, ob, frame);
return 0;
} }
static void scene_setSubframe(Scene *scene, float subframe) static void scene_setSubframe(Scene *scene, float subframe)
@@ -1222,7 +1227,7 @@ static int surface_usesAdjData(DynamicPaintSurface *surface)
static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init) static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int force_init)
{ {
PaintSurfaceData *sData = surface->data; PaintSurfaceData *sData = surface->data;
PaintAdjData *ed; PaintAdjData *ad;
int *temp_data; int *temp_data;
int neigh_points = 0; int neigh_points = 0;
@@ -1238,17 +1243,17 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
if (!neigh_points) return; if (!neigh_points) return;
/* allocate memory */ /* allocate memory */
ed = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data"); ad = sData->adj_data = MEM_callocN(sizeof(PaintAdjData), "Surface Adj Data");
if (!ed) return; if (!ad) return;
ed->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index"); ad->n_index = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Index");
ed->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts"); ad->n_num = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Counts");
temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data"); temp_data = MEM_callocN(sizeof(int)*sData->total_points, "Temp Adj Data");
ed->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets"); ad->n_target = MEM_callocN(sizeof(int)*neigh_points, "Surface Adj Targets");
ed->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags"); ad->flags = MEM_callocN(sizeof(int)*sData->total_points, "Surface Adj Flags");
ed->total_targets = neigh_points; ad->total_targets = neigh_points;
/* in case of allocation error, free memory */ /* in case of allocation error, free memory */
if (!ed->n_index || !ed->n_num || !ed->n_target || !temp_data) { if (!ad->n_index || !ad->n_num || !ad->n_target || !temp_data) {
dynamicPaint_freeAdjData(sData); dynamicPaint_freeAdjData(sData);
if (temp_data) MEM_freeN(temp_data); if (temp_data) MEM_freeN(temp_data);
setError(surface->canvas, "Not enough free memory."); setError(surface->canvas, "Not enough free memory.");
@@ -1267,14 +1272,15 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
/* count number of edges per vertex */ /* count number of edges per vertex */
for (i=0; i<numOfEdges; i++) { for (i=0; i<numOfEdges; i++) {
ed->n_num[edge[i].v1]++; ad->n_num[edge[i].v1]++;
ed->n_num[edge[i].v2]++; ad->n_num[edge[i].v2]++;
temp_data[edge[i].v1]++; temp_data[edge[i].v1]++;
temp_data[edge[i].v2]++; temp_data[edge[i].v2]++;
} }
/* to locate points on "mesh edge" */ /* also add number of vertices to temp_data
* to locate points on "mesh edge" */
for (i=0; i<numOfFaces; i++) { for (i=0; i<numOfFaces; i++) {
temp_data[face[i].v1]++; temp_data[face[i].v1]++;
temp_data[face[i].v2]++; temp_data[face[i].v2]++;
@@ -1288,7 +1294,7 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
for (i=0; i<sData->total_points; i++) { for (i=0; i<sData->total_points; i++) {
if ((temp_data[i]%2) || if ((temp_data[i]%2) ||
temp_data[i] < 4) temp_data[i] < 4)
ed->flags[i] |= ADJ_ON_MESH_EDGE; ad->flags[i] |= ADJ_ON_MESH_EDGE;
/* reset temp data */ /* reset temp data */
temp_data[i] = 0; temp_data[i] = 0;
@@ -1297,22 +1303,22 @@ static void dynamicPaint_initAdjacencyData(DynamicPaintSurface *surface, int for
/* order n_index array */ /* order n_index array */
n_pos = 0; n_pos = 0;
for (i=0; i<sData->total_points; i++) { for (i=0; i<sData->total_points; i++) {
ed->n_index[i] = n_pos; ad->n_index[i] = n_pos;
n_pos += ed->n_num[i]; n_pos += ad->n_num[i];
} }
/* and now add neighbour data using that info */ /* and now add neighbour data using that info */
for (i=0; i<numOfEdges; i++) { for (i=0; i<numOfEdges; i++) {
/* first vertex */ /* first vertex */
int index = edge[i].v1; int index = edge[i].v1;
n_pos = ed->n_index[index]+temp_data[index]; n_pos = ad->n_index[index]+temp_data[index];
ed->n_target[n_pos] = edge[i].v2; ad->n_target[n_pos] = edge[i].v2;
temp_data[index]++; temp_data[index]++;
/* second vertex */ /* second vertex */
index = edge[i].v2; index = edge[i].v2;
n_pos = ed->n_index[index]+temp_data[index]; n_pos = ad->n_index[index]+temp_data[index];
ed->n_target[n_pos] = edge[i].v1; ad->n_target[n_pos] = edge[i].v1;
temp_data[index]++; temp_data[index]++;
} }
} }
@@ -1500,10 +1506,11 @@ void dynamicPaint_clearSurface(DynamicPaintSurface *surface)
int dynamicPaint_resetSurface(DynamicPaintSurface *surface) int dynamicPaint_resetSurface(DynamicPaintSurface *surface)
{ {
int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface); int numOfPoints = dynamicPaint_surfaceNumOfPoints(surface);
/* dont touch image sequence types. they get handled only on bake */ /* free existing data */
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
if (surface->data) dynamicPaint_freeSurfaceData(surface); if (surface->data) dynamicPaint_freeSurfaceData(surface);
/* dont reallocate for image sequence types. they get handled only on bake */
if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1;
if (numOfPoints < 1) return 0; if (numOfPoints < 1) return 0;
/* allocate memory */ /* allocate memory */
@@ -1574,7 +1581,6 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
DynamicPaintSurface *surface = pmd->canvas->surfaces.first; DynamicPaintSurface *surface = pmd->canvas->surfaces.first;
int update_normals = 0; int update_normals = 0;
pmd->canvas->flags &= ~MOD_DPAINT_PREVIEW_READY;
/* loop through surfaces */ /* loop through surfaces */
for (; surface; surface=surface->next) { for (; surface; surface=surface->next) {
@@ -1651,7 +1657,6 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
} }
} }
} }
pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
} }
} }
@@ -1711,29 +1716,7 @@ static struct DerivedMesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData
if (surface->flags & MOD_DPAINT_PREVIEW) { if (surface->flags & MOD_DPAINT_PREVIEW) {
/* Save preview results to weight layer, to be /* Save preview results to weight layer, to be
* able to share same drawing methods */ * able to share same drawing methods */
MFace *mface = result->getFaceArray(result); DM_update_weight_mcol(ob, result, 0, weight, 0, NULL);
int numOfFaces = result->getNumFaces(result);
int i;
MCol *col = result->getFaceDataArray(result, CD_WEIGHT_MCOL);
if (!col) col = CustomData_add_layer(&result->faceData, CD_WEIGHT_MCOL, CD_CALLOC, NULL, numOfFaces);
if (col) {
#pragma omp parallel for schedule(static)
for (i=0; i<numOfFaces; i++) {
float temp_color[3];
int j = (mface[i].v4) ? 4 : 3;
while (j--) {
int index = *((&mface[i].v1)+j);
weight_to_rgb(temp_color, weight[index]);
col[i*4+j].r = FTOCHAR(temp_color[2]);
col[i*4+j].g = FTOCHAR(temp_color[1]);
col[i*4+j].b = FTOCHAR(temp_color[0]);
col[i*4+j].a = 255;
}
}
pmd->canvas->flags |= MOD_DPAINT_PREVIEW_READY;
}
} }
/* apply weights into a vertex group, if doesnt exists add a new layer */ /* apply weights into a vertex group, if doesnt exists add a new layer */
@@ -1923,8 +1906,8 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
x = px + neighX[n_index]; x = px + neighX[n_index];
y = py + neighY[n_index]; y = py + neighY[n_index];
if (x<0 || x>=w) return -1; if (x<0 || x>=w) return OUT_OF_TEXTURE;
if (y<0 || y>=h) return -1; if (y<0 || y>=h) return OUT_OF_TEXTURE;
tPoint = &tempPoints[x+w*y]; /* UV neighbour */ tPoint = &tempPoints[x+w*y]; /* UV neighbour */
cPoint = &tempPoints[px+w*py]; /* Origin point */ cPoint = &tempPoints[px+w*py]; /* Origin point */
@@ -2037,8 +2020,8 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
} }
} }
/* If none found return -1 */ /* If none found pixel is on mesh edge */
if (target_face == -1) return -1; if (target_face == -1) return ON_MESH_EDGE;
/* /*
* If target face is connected in UV space as well, just use original index * If target face is connected in UV space as well, just use original index
@@ -2076,15 +2059,15 @@ static int dynamicPaint_findNeighbourPixel(PaintUVPoint *tempPoints, DerivedMesh
final_pixel[1] = (int)floor(pixel[1]); final_pixel[1] = (int)floor(pixel[1]);
/* If current pixel uv is outside of texture */ /* If current pixel uv is outside of texture */
if (final_pixel[0] < 0 || final_pixel[0] >= w) return -1; if (final_pixel[0] < 0 || final_pixel[0] >= w) return OUT_OF_TEXTURE;
if (final_pixel[1] < 0 || final_pixel[1] >= h) return -1; if (final_pixel[1] < 0 || final_pixel[1] >= h) return OUT_OF_TEXTURE;
final_index = final_pixel[0] + w * final_pixel[1]; final_index = final_pixel[0] + w * final_pixel[1];
/* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */ /* If we ended up to our origin point ( mesh has smaller than pixel sized faces) */
if (final_index == (px+w*py)) return -1; if (final_index == (px+w*py)) return NOT_FOUND;
/* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */ /* If found pixel still lies on wrong face ( mesh has smaller than pixel sized faces) */
if (tempPoints[final_index].face_index != target_face) return -1; if (tempPoints[final_index].face_index != target_face) return NOT_FOUND;
/* /*
* If final point is an "edge pixel", use it's "real" neighbour instead * If final point is an "edge pixel", use it's "real" neighbour instead
@@ -2466,11 +2449,14 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface)
* If not found, -1 is returned */ * If not found, -1 is returned */
int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i); int n_target = dynamicPaint_findNeighbourPixel(tempPoints, dm, uvname, w, h, tx, ty, i);
if (n_target != -1) { if (n_target >= 0) {
ed->n_target[n_pos] = final_index[n_target]; ed->n_target[n_pos] = final_index[n_target];
ed->n_num[final_index[index]]++; ed->n_num[final_index[index]]++;
n_pos++; n_pos++;
} }
else if (n_target == ON_MESH_EDGE || n_target == OUT_OF_TEXTURE) {
ed->flags[final_index[index]] |= ADJ_ON_MESH_EDGE;
}
} }
} }
} }
@@ -3171,8 +3157,8 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
mul_m4_v3(brushOb->obmat, mvert[ii].co); mul_m4_v3(brushOb->obmat, mvert[ii].co);
boundInsert(&mesh_bb, mvert[ii].co); boundInsert(&mesh_bb, mvert[ii].co);
/* for project brush calculate average normal */ /* for proximity project calculate average normal */
if (brush->flags & MOD_DPAINT_PROX_PROJECT) { if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
float nor[3]; float nor[3];
normal_short_to_float_v3(nor, mvert[ii].no); normal_short_to_float_v3(nor, mvert[ii].no);
mul_mat3_m4_v3(brushOb->obmat, nor); mul_mat3_m4_v3(brushOb->obmat, nor);
@@ -3182,7 +3168,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
} }
} }
if (brush->flags & MOD_DPAINT_PROX_PROJECT) { if (brush->flags & MOD_DPAINT_PROX_PROJECT && brush->collision != MOD_DPAINT_COL_VOLUME) {
mul_v3_fl(avg_brushNor, 1.0f/(float)numOfVerts); mul_v3_fl(avg_brushNor, 1.0f/(float)numOfVerts);
/* instead of null vector use positive z */ /* instead of null vector use positive z */
if (!(MIN3(avg_brushNor[0],avg_brushNor[1],avg_brushNor[2]))) if (!(MIN3(avg_brushNor[0],avg_brushNor[1],avg_brushNor[2])))
@@ -3566,7 +3552,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
/* Proceed only if particle is active */ /* Proceed only if particle is active */
if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue;
else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue;
else if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; else if(pa->flag & PARS_UNEXIST) continue;
/* for debug purposes check if any NAN particle proceeds /* for debug purposes check if any NAN particle proceeds
* For some reason they get past activity check, this should rule most of them out */ * For some reason they get past activity check, this should rule most of them out */
@@ -3879,14 +3865,13 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po
/***************************** Dynamic Paint Step / Baking ******************************/ /***************************** Dynamic Paint Step / Baking ******************************/
/* /*
* Calculate current frame neighbouring point distances * Calculate current frame distances and directions for adjacency data
* and direction vectors
*/ */
static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int force_init) static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, int force_init)
{ {
PaintSurfaceData *sData = surface->data; PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData; PaintBakeData *bData = sData->bData;
BakeNeighPoint *bNeighs; BakeAdjPoint *bNeighs;
PaintAdjData *adj_data = sData->adj_data; PaintAdjData *adj_data = sData->adj_data;
Vec3f *realCoord = bData->realCoord; Vec3f *realCoord = bData->realCoord;
int index; int index;
@@ -3894,7 +3879,7 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int
if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return; if ((!surface_usesAdjDistance(surface) && !force_init) || !sData->adj_data) return;
if (bData->bNeighs) MEM_freeN(bData->bNeighs); if (bData->bNeighs) MEM_freeN(bData->bNeighs);
bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeNeighPoint),"PaintEffectBake"); bNeighs = bData->bNeighs = MEM_mallocN(sData->adj_data->total_targets*sizeof(struct BakeAdjPoint),"PaintEffectBake");
if (!bNeighs) return; if (!bNeighs) return;
#pragma omp parallel for schedule(static) #pragma omp parallel for schedule(static)
@@ -3933,7 +3918,7 @@ static void dynamicPaint_prepareNeighbourData(DynamicPaintSurface *surface, int
/* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force */ /* find two adjacency points (closest_id) and influence (closest_d) to move paint towards when affected by a force */
void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2]) void surface_determineForceTargetPoints(PaintSurfaceData *sData, int index, float force[3], float closest_d[2], int closest_id[2])
{ {
BakeNeighPoint *bNeighs = sData->bData->bNeighs; BakeAdjPoint *bNeighs = sData->bData->bNeighs;
int numOfNeighs = sData->adj_data->n_num[index]; int numOfNeighs = sData->adj_data->n_num[index];
int i; int i;
@@ -4002,7 +3987,7 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus
{ {
PaintSurfaceData *sData = surface->data; PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData; PaintBakeData *bData = sData->bData;
BakeNeighPoint *bNeighs = sData->bData->bNeighs; BakeAdjPoint *bNeighs = sData->bData->bNeighs;
int index, steps, step; int index, steps, step;
float eff_scale, max_velocity = 0.0f; float eff_scale, max_velocity = 0.0f;
@@ -4161,7 +4146,7 @@ static int dynamicPaint_prepareEffectStep(DynamicPaintSurface *surface, Scene *s
static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps) static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force, PaintPoint *prevPoint, float timescale, float steps)
{ {
PaintSurfaceData *sData = surface->data; PaintSurfaceData *sData = surface->data;
BakeNeighPoint *bNeighs = sData->bData->bNeighs; BakeAdjPoint *bNeighs = sData->bData->bNeighs;
float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE; float distance_scale = getSurfaceDimension(sData)/CANVAS_REL_SIZE;
int index; int index;
timescale /= steps; timescale /= steps;
@@ -4190,7 +4175,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
/* Loop through neighbouring points */ /* Loop through neighbouring points */
for (i=0; i<numOfNeighs; i++) { for (i=0; i<numOfNeighs; i++) {
int n_index = sData->adj_data->n_index[index]+i; int n_index = sData->adj_data->n_index[index]+i;
float w_factor /* , p_alpha = pPoint->e_alpha */ /* UNUSED */; float w_factor;
PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]]; PaintPoint *ePoint = &prevPoint[sData->adj_data->n_target[n_index]];
float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist; float speed_scale = (bNeighs[n_index].dist<eff_scale) ? 1.0f : eff_scale/bNeighs[n_index].dist;
float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed; float color_mix = (MIN3(ePoint->wetness, pPoint->wetness, 1.0f))*0.25f*surface->color_spread_speed;
@@ -4327,7 +4312,7 @@ static void dynamicPaint_doEffectStep(DynamicPaintSurface *surface, float *force
void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale) void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescale)
{ {
PaintSurfaceData *sData = surface->data; PaintSurfaceData *sData = surface->data;
BakeNeighPoint *bNeighs = sData->bData->bNeighs; BakeAdjPoint *bNeighs = sData->bData->bNeighs;
int index; int index;
int steps, ss; int steps, ss;
float dt, min_dist, damp_factor; float dt, min_dist, damp_factor;
@@ -4760,8 +4745,8 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, Scene *sc
/* generate surface space partitioning grid */ /* generate surface space partitioning grid */
surfaceGenerateGrid(surface); surfaceGenerateGrid(surface);
/* calculate current frame neighbouring point distances and global dirs */ /* calculate current frame adjacency point distances and global dirs */
dynamicPaint_prepareNeighbourData(surface, 0); dynamicPaint_prepareAdjacencyData(surface, 0);
/* Copy current frame vertices to check against in next frame */ /* Copy current frame vertices to check against in next frame */
copy_m4_m4(bData->prev_obmat, ob->obmat); copy_m4_m4(bData->prev_obmat, ob->obmat);
@@ -4844,7 +4829,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
if (!sData->adj_data) if (!sData->adj_data)
dynamicPaint_initAdjacencyData(surface, 1); dynamicPaint_initAdjacencyData(surface, 1);
if (!bData->bNeighs) if (!bData->bNeighs)
dynamicPaint_prepareNeighbourData(surface, 1); dynamicPaint_prepareAdjacencyData(surface, 1);
} }
/* update object data on this subframe */ /* update object data on this subframe */

View File

@@ -1852,6 +1852,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
while(step < tf) while(step < tf)
{ {
// damping velocity for artistic reasons
mul_lfvectorS(id->V, id->V, clmd->sim_parms->vel_damping, numverts);
// calculate forces // calculate forces
cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M); cloth_calc_force(clmd, frame, id->F, id->X, id->V, id->dFdV, id->dFdX, effectors, step, id->M);

View File

@@ -142,6 +142,19 @@ int modifier_supportsMapping(ModifierData *md)
(mti->flags & eModifierTypeFlag_SupportsMapping)); (mti->flags & eModifierTypeFlag_SupportsMapping));
} }
int modifier_isPreview(ModifierData *md)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
if (!(mti->flags & eModifierTypeFlag_UsesPreview))
return FALSE;
if (md->mode & eModifierMode_Realtime)
return TRUE;
return FALSE;
}
ModifierData *modifiers_findByType(Object *ob, ModifierType type) ModifierData *modifiers_findByType(Object *ob, ModifierType type)
{ {
ModifierData *md = ob->modifiers.first; ModifierData *md = ob->modifiers.first;
@@ -385,6 +398,21 @@ LinkNode *modifiers_calcDataMasks(struct Scene *scene, Object *ob, ModifierData
return dataMasks; return dataMasks;
} }
ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode)
{
ModifierData *tmp_md = NULL;
if (required_mode != eModifierMode_Realtime)
return tmp_md;
/* Find the latest modifier in stack generating preview. */
for(; md; md = md->next) {
if(modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md))
tmp_md = md;
}
return tmp_md;
}
ModifierData *modifiers_getVirtualModifierList(Object *ob) ModifierData *modifiers_getVirtualModifierList(Object *ob)
{ {
/* Kinda hacky, but should be fine since we are never /* Kinda hacky, but should be fine since we are never
@@ -545,6 +573,20 @@ int modifiers_isCorrectableDeformed(Object *ob)
return 0; return 0;
} }
/* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer
* to preview something... Used by DynamicPaint and WeightVG currently. */
int modifiers_isPreview(Object *ob)
{
ModifierData *md = ob->modifiers.first;
for (; md; md = md->next) {
if (modifier_isPreview(md))
return TRUE;
}
return FALSE;
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek) int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
{ {
int i= 0; int i= 0;

View File

@@ -1448,9 +1448,17 @@ void BKE_nla_validate_state (AnimData *adt)
*/ */
// TODO: 1 solution is to tie this in with auto-blending... // TODO: 1 solution is to tie this in with auto-blending...
if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) { if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
/* 1) First strip must be set to extend hold, otherwise, stuff before acts dodgy
* 2) Only overwrite extend mode if *not* changing it will most probably result in
* occlusion problems, which will occur iff
* - blendmode = REPLACE
* - all channels the same (this is fiddly to test, so is currently assumed)
*
* Should fix problems such as [#29869]
*/
if (strip == fstrip) if (strip == fstrip)
strip->extendmode= NLASTRIP_EXTEND_HOLD; strip->extendmode= NLASTRIP_EXTEND_HOLD;
else else if (strip->blendmode == NLASTRIP_MODE_REPLACE)
strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD; strip->extendmode= NLASTRIP_EXTEND_HOLD_FORWARD;
} }
} }
@@ -1542,6 +1550,34 @@ short BKE_nla_tweakmode_enter (AnimData *adt)
break; break;
} }
} }
/* There are situations where we may have multiple strips selected and we want to enter tweakmode on all
* of those at once. Usually in those cases, it will usually just be a single strip per AnimData.
* In such cases, compromise and take the last selected track and/or last selected strip [#28468]
*/
if (activeTrack == NULL) {
/* try last selected track for active strip */
for (nlt = adt->nla_tracks.last; nlt; nlt = nlt->prev) {
if (nlt->flag & NLATRACK_SELECTED) {
/* assume this is the active track */
activeTrack= nlt;
/* try to find active strip */
activeStrip= BKE_nlastrip_find_active(nlt);
break;
}
}
}
if ((activeTrack) && (activeStrip == NULL)) {
/* no active strip in active or last selected track; compromise for first selected (assuming only single)... */
for (strip = activeTrack->strips.first; strip; strip= strip->next) {
if (strip->flag & (NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_ACTIVE)) {
activeStrip = strip;
break;
}
}
}
if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) { if ELEM3(NULL, activeTrack, activeStrip, activeStrip->act) {
if (G.f & G_DEBUG) { if (G.f & G_DEBUG) {
printf("NLA tweakmode enter - neither active requirement found \n"); printf("NLA tweakmode enter - neither active requirement found \n");

View File

@@ -1881,6 +1881,7 @@ static void registerShaderNodes(bNodeTreeType *ttype)
register_node_type_sh_material(ttype); register_node_type_sh_material(ttype);
register_node_type_sh_camera(ttype); register_node_type_sh_camera(ttype);
register_node_type_sh_gamma(ttype); register_node_type_sh_gamma(ttype);
register_node_type_sh_brightcontrast(ttype);
register_node_type_sh_value(ttype); register_node_type_sh_value(ttype);
register_node_type_sh_rgb(ttype); register_node_type_sh_rgb(ttype);
register_node_type_sh_mix_rgb(ttype); register_node_type_sh_mix_rgb(ttype);

View File

@@ -1126,6 +1126,9 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D
fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
if(dm != finaldm) dm->release(dm); if(dm != finaldm) dm->release(dm);
BLI_kdtree_free(tree);
return 0; return 0;
} }
@@ -3477,6 +3480,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
int totedge; int totedge;
int k; int k;
float hairmat[4][4]; float hairmat[4][4];
float (*deformedVerts)[3];
if(!psys->clmd) { if(!psys->clmd) {
psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
@@ -3570,7 +3574,15 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->clmd->point_cache = psys->pointcache; psys->clmd->point_cache = psys->pointcache;
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm); deformedVerts = MEM_callocN(sizeof(*deformedVerts)*dm->getNumVerts(dm), "do_hair_dynamics vertexCos");
psys->hair_out_dm = CDDM_copy(dm);
psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, deformedVerts);
CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
MEM_freeN(deformedVerts);
psys->clmd->sim_parms->effector_weights = NULL; psys->clmd->sim_parms->effector_weights = NULL;
} }

View File

@@ -538,6 +538,8 @@ Scene *add_scene(const char *name)
sce->gm.recastData.detailsampledist = 6.0f; sce->gm.recastData.detailsampledist = 6.0f;
sce->gm.recastData.detailsamplemaxerror = 1.0f; sce->gm.recastData.detailsamplemaxerror = 1.0f;
sce->gm.exitkey = 218; // Blender key code for ESC
sound_create_scene(sce); sound_create_scene(sce);
return sce; return sce;

View File

@@ -77,6 +77,9 @@
#include "BKE_smoke.h" #include "BKE_smoke.h"
/* UNUSED so far, may be enabled later */
/* #define USE_SMOKE_COLLISION_DM */
#ifdef WITH_SMOKE #ifdef WITH_SMOKE
#ifdef _WIN32 #ifdef _WIN32
@@ -617,9 +620,11 @@ static void smokeModifier_freeCollision(SmokeModifierData *smd)
smd->coll->bvhtree = NULL; smd->coll->bvhtree = NULL;
} }
#ifdef USE_SMOKE_COLLISION_DM
if(smd->coll->dm) if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm); smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = NULL; smd->coll->dm = NULL;
#endif
MEM_freeN(smd->coll); MEM_freeN(smd->coll);
smd->coll = NULL; smd->coll = NULL;
@@ -682,9 +687,11 @@ void smokeModifier_reset(struct SmokeModifierData *smd)
smd->coll->bvhtree = NULL; smd->coll->bvhtree = NULL;
} }
#ifdef USE_SMOKE_COLLISION_DM
if(smd->coll->dm) if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm); smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = NULL; smd->coll->dm = NULL;
#endif
} }
} }
@@ -772,7 +779,10 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->coll->points = NULL; smd->coll->points = NULL;
smd->coll->numpoints = 0; smd->coll->numpoints = 0;
smd->coll->bvhtree = NULL; smd->coll->bvhtree = NULL;
#ifdef USE_SMOKE_COLLISION_DM
smd->coll->dm = NULL; smd->coll->dm = NULL;
#endif
} }
} }
} }
@@ -1339,11 +1349,13 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM
{ {
// XXX TODO // XXX TODO
smd->time = scene->r.cfra; smd->time = scene->r.cfra;
#ifdef USE_SMOKE_COLLISION_DM
if(smd->coll->dm) if(smd->coll->dm)
smd->coll->dm->release(smd->coll->dm); smd->coll->dm->release(smd->coll->dm);
smd->coll->dm = CDDM_copy(dm); smd->coll->dm = CDDM_copy(dm);
#endif
// rigid movement support // rigid movement support
copy_m4_m4(smd->coll->mat_old, smd->coll->mat); copy_m4_m4(smd->coll->mat_old, smd->coll->mat);

Some files were not shown because too many files have changed in this diff Show More