Cycles: add "From Dupli" option for texture coordinate node. This gets the

Generated and UV coordinates from the duplicator of instance instead of the
object itself.

This was used in e.g. Big Buck Bunny for texturing instanced feathers with
a UV map on the bird. Many files changed, mainly to do some refactoring to
get rid of G.rendering global in duplilist code.
This commit is contained in:
Brecht Van Lommel 2012-10-04 21:40:39 +00:00
parent 984e9f9cc8
commit fedc8e1722
32 changed files with 222 additions and 80 deletions

@ -194,8 +194,10 @@ void BlenderSync::sync_background_light()
/* Object */
void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm, uint layer_flag, int motion, int particle_id)
void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id)
{
BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
/* light is handled separately */
if(object_is_light(b_ob)) {
if(!motion)
@ -274,6 +276,15 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::Object b_ob,
object->visibility &= ~PATH_RAY_CAMERA;
}
if (b_dupli_ob) {
object->dupli_generated = get_float3(b_dupli_ob.orco());
object->dupli_uv = get_float2(b_dupli_ob.uv());
}
else {
object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
object->dupli_uv = make_float2(0.0f, 0.0f);
}
object->particle_id = particle_id;
object->tag_update(scene);
@ -328,7 +339,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
bool dup_hide = (b_v3d)? b_dup_ob.hide(): b_dup_ob.hide_render();
if(!(b_dup->hide() || dup_hide)) {
sync_object(*b_ob, b_index, b_dup_ob, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset);
sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset);
}
++b_index;
@ -346,7 +357,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion)
if(!hide) {
/* object itself */
Transform tfm = get_transform(b_ob->matrix_world());
sync_object(*b_ob, 0, *b_ob, tfm, ob_layer, motion, 0);
sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0);
}
particle_offset += num_particles;

@ -490,7 +490,10 @@ static ShaderNode *add_node(BL::BlendData b_data, BL::Scene b_scene, ShaderGraph
break;
}
case BL::ShaderNode::type_TEX_COORD: {
node = new TextureCoordinateNode();
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
tex_coord->from_dupli = b_tex_coord_node.from_dupli();
node = tex_coord;
break;
}
case BL::ShaderNode::type_TEX_SKY: {

@ -81,7 +81,7 @@ private:
void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
Mesh *sync_mesh(BL::Object b_ob, bool object_updated);
void sync_object(BL::Object b_parent, int b_index, BL::Object b_object, Transform& tfm, uint layer_flag, int motion, int particle_id);
void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id);
void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm);
void sync_background_light();
void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion);

@ -36,7 +36,7 @@ struct RenderResult;
ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings);
void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh);
void rna_Object_create_duplilist(void *ob, void *reports, void *sce);
void rna_Object_create_duplilist(void *ob, void *reports, void *sce, int settings);
void rna_Object_free_duplilist(void *ob);
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
@ -84,7 +84,7 @@ static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh)
static inline void object_create_duplilist(BL::Object self, BL::Scene scene)
{
rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data);
rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data, 2);
}
static inline void object_free_duplilist(BL::Object self)

@ -23,7 +23,8 @@ enum ObjectTransform {
OBJECT_INVERSE_TRANSFORM = 3,
OBJECT_PROPERTIES = 6,
OBJECT_TRANSFORM_MOTION_PRE = 8,
OBJECT_TRANSFORM_MOTION_POST = 12
OBJECT_TRANSFORM_MOTION_POST = 12,
OBJECT_DUPLI = 16
};
__device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, float time, enum ObjectTransform type)
@ -164,6 +165,27 @@ __device_inline uint object_particle_id(KernelGlobals *kg, int object)
return __float_as_int(f.w);
}
__device_inline float3 object_dupli_generated(KernelGlobals *kg, int object)
{
if(object == ~0)
return make_float3(0.0f, 0.0f, 0.0f);
int offset = object*OBJECT_SIZE + OBJECT_DUPLI;
float4 f = kernel_tex_fetch(__objects, offset);
return make_float3(f.x, f.y, f.z);
}
__device_inline float3 object_dupli_uv(KernelGlobals *kg, int object)
{
if(object == ~0)
return make_float3(0.0f, 0.0f, 0.0f);
int offset = object*OBJECT_SIZE + OBJECT_DUPLI;
float4 f = kernel_tex_fetch(__objects, offset + 1);
return make_float3(f.x, f.y, 0.0f);
}
__device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
{
return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);

@ -29,7 +29,7 @@
CCL_NAMESPACE_BEGIN
/* constants */
#define OBJECT_SIZE 16
#define OBJECT_SIZE 18
#define LIGHT_SIZE 4
#define FILTER_TABLE_SIZE 256
#define RAMP_TABLE_SIZE 256

@ -92,6 +92,14 @@ __device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, float *stack
data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
data = object_dupli_uv(kg, sd->object);
break;
}
}
stack_store_float3(stack, out_offset, data);
@ -141,6 +149,14 @@ __device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, floa
data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
data = object_dupli_uv(kg, sd->object);
break;
}
}
stack_store_float3(stack, out_offset, data);
@ -193,6 +209,14 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa
data = sd->I;
break;
}
case NODE_TEXCO_DUPLI_GENERATED: {
data = object_dupli_generated(kg, sd->object);
break;
}
case NODE_TEXCO_DUPLI_UV: {
data = object_dupli_uv(kg, sd->object);
break;
}
}
stack_store_float3(stack, out_offset, data);

@ -43,6 +43,7 @@ typedef enum NodeType {
NODE_TEX_IMAGE_BOX,
NODE_TEX_SKY,
NODE_GEOMETRY,
NODE_GEOMETRY_DUPLI,
NODE_LIGHT_PATH,
NODE_VALUE_F,
NODE_VALUE_V,
@ -149,7 +150,9 @@ typedef enum NodeTexCoord {
NODE_TEXCO_OBJECT,
NODE_TEXCO_CAMERA,
NODE_TEXCO_WINDOW,
NODE_TEXCO_REFLECTION
NODE_TEXCO_REFLECTION,
NODE_TEXCO_DUPLI_GENERATED,
NODE_TEXCO_DUPLI_UV
} NodeTexCoord;
typedef enum NodeMix {

@ -1681,9 +1681,15 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
compiler.add_node(geom_node, NODE_GEOM_P, out->stack_offset);
}
else {
int attr = compiler.attribute(ATTR_STD_GENERATED);
compiler.stack_assign(out);
compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3);
if(from_dupli) {
compiler.stack_assign(out);
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_GENERATED, out->stack_offset);
}
else {
int attr = compiler.attribute(ATTR_STD_GENERATED);
compiler.stack_assign(out);
compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3);
}
}
}
@ -1695,9 +1701,15 @@ void TextureCoordinateNode::compile(SVMCompiler& compiler)
out = output("UV");
if(!out->links.empty()) {
int attr = compiler.attribute(ATTR_STD_UV);
compiler.stack_assign(out);
compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3);
if(from_dupli) {
int attr = compiler.attribute(ATTR_STD_UV);
compiler.stack_assign(out);
compiler.add_node(attr_node, attr, out->stack_offset, NODE_ATTR_FLOAT3);
}
else {
compiler.stack_assign(out);
compiler.add_node(texco_node, NODE_TEXCO_DUPLI_UV, out->stack_offset);
}
}
out = output("Object");

@ -284,6 +284,8 @@ class TextureCoordinateNode : public ShaderNode {
public:
SHADER_NODE_CLASS(TextureCoordinateNode)
void attributes(AttributeRequestSet *attributes);
bool from_dupli;
};
class LightPathNode : public ShaderNode {

@ -235,6 +235,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
}
}
/* dupli object coords */
objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
/* object flag */
if(ob->use_holdout)
flag |= SD_HOLDOUT_MASK;

@ -49,6 +49,9 @@ public:
bool use_motion;
bool use_holdout;
float3 dupli_generated;
float2 dupli_uv;
int particle_id;
Object();

@ -65,8 +65,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
/* ---------------------------------------------------- */
/* Dupli-Geometry */
struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update);
struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob);
struct ListBase *object_duplilist_ex(struct Scene *sce, struct Object *ob, int update, int for_render);
struct ListBase *object_duplilist(struct Scene *sce, struct Object *ob, int for_render);
void free_object_duplilist(struct ListBase *lb);
int count_duplilist(struct Object *ob);

@ -42,7 +42,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 264
#define BLENDER_SUBVERSION 0
#define BLENDER_SUBVERSION 1
/* 262 was the last editmesh release but its has compatibility code for bmesh data,
* so set the minversion to 2.61 */

@ -75,7 +75,7 @@
/* forward declarations */
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
int level, short animated, short update);
int level, short flag);
/* ******************************************************************** */
/* Animation Visualization */
@ -700,7 +700,11 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua
/* ******************************************************************** */
/* Dupli-Geometry */
static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short animated)
#define DUPLILIST_DO_UPDATE 1
#define DUPLILIST_FOR_RENDER 2
#define DUPLILIST_ANIMATED 4
static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag)
{
DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject");
@ -712,14 +716,14 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i
dob->index = index;
dob->particle_index = par_index;
dob->type = type;
dob->animated = (type == OB_DUPLIGROUP) && animated;
dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED);
ob->lay = lay;
return dob;
}
static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index,
int level, short animated, short update)
int level, short flag)
{
DupliObject *dob;
Group *group;
@ -735,13 +739,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
/* handles animated groups, and */
/* we need to check update for objects that are not in scene... */
if (update) {
if (flag & DUPLILIST_DO_UPDATE) {
/* note: update is optional because we don't always need object
* transformations to be correct. Also fixes bug [#29616]. */
group_handle_recalc_and_update(scene, ob, group);
}
animated = animated || group_is_animated(ob, group);
if (group_is_animated(ob, group))
flag |= DUPLILIST_ANIMATED;
for (go = group->gobject.first; go; go = go->next) {
/* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
@ -757,7 +762,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
mult_m4_m4m4(mat, ob->obmat, go->ob->obmat);
}
dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, animated);
dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag);
/* check the group instance and object layers match, also that the object visible flags are ok. */
if ((dob->origlay & group->layer) == 0 ||
@ -772,14 +777,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde
if (go->ob->transflag & OB_DUPLI) {
copy_m4_m4(dob->ob->obmat, dob->mat);
object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, animated, update);
object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag);
copy_m4_m4(dob->ob->obmat, dob->omat);
}
}
}
}
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short animated)
static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag)
{
extern int enable_cu_speed; /* object.c */
Object copyob;
@ -827,7 +832,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, animated);
dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag);
copy_m4_m4(dob->omat, copyob.obmat);
}
}
@ -851,8 +856,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind
typedef struct VertexDupliData {
ID *id; /* scene or group, for recursive loops */
int level;
short animated;
short update;
short flag;
ListBase *lb;
float pmat[4][4];
float obmat[4][4]; /* Only used for dupliverts inside dupligroups, where the ob->obmat is modified */
@ -896,7 +900,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
origlay = vdd->ob->lay;
dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->animated);
dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag);
/* restore the original layer so that each dupli will have proper dob->origlay */
vdd->ob->lay = origlay;
@ -908,13 +912,13 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
float tmpmat[4][4];
copy_m4_m4(tmpmat, vdd->ob->obmat);
copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */
object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->animated, vdd->update);
object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag);
copy_m4_m4(vdd->ob->obmat, tmpmat);
}
}
static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
int level, short animated, short update)
int level, short flag)
{
Object *ob, *ob_iter;
Mesh *me = par->data;
@ -942,7 +946,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
else
dm = mesh_get_derived_deform(scene, par, CD_MASK_BAREMESH);
if (G.is_rendering) {
if (flag & DUPLILIST_FOR_RENDER) {
vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0);
}
@ -992,8 +996,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
vdd.id = id;
vdd.level = level;
vdd.animated = animated;
vdd.update = update;
vdd.flag = flag;
vdd.lb = lb;
vdd.ob = ob;
vdd.scene = scene;
@ -1039,7 +1042,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl
}
static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index,
int level, short animated, short update)
int level, short flag)
{
Object *ob, *ob_iter;
Base *base = NULL;
@ -1076,8 +1079,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
mloop = dm->getLoopArray(dm);
mvert = dm->getVertArray(dm);
if (G.is_rendering) {
if (flag & DUPLILIST_FOR_RENDER) {
orco = (float(*)[3])BKE_mesh_orco_verts_get(par);
BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0);
mloopuv = me->mloopuv;
@ -1182,8 +1184,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
copy_m4_m4(tmat, obmat);
mul_m4_m4m3(obmat, tmat, mat);
dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, animated);
if (G.is_rendering) {
dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED));
if (flag & DUPLILIST_FOR_RENDER) {
w = 1.0f / (float)mp->totloop;
if (orco) {
@ -1205,7 +1207,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
float tmpmat[4][4];
copy_m4_m4(tmpmat, ob->obmat);
copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */
object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, animated, update);
object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag);
copy_m4_m4(ob->obmat, tmpmat);
}
}
@ -1226,7 +1228,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa
}
static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys,
int level, short animated, short update)
int level, short flag)
{
GroupObject *go;
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
@ -1309,7 +1311,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
/* gather list of objects or single object */
if (part->ren_as == PART_DRAW_GR) {
if (update) {
if (flag & DUPLILIST_DO_UPDATE) {
group_handle_recalc_and_update(scene, par, part->dup_group);
}
@ -1452,9 +1454,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
else
copy_m4_m4(mat, tmat);
dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, animated);
dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
copy_m4_m4(dob->omat, obcopylist[b].obmat);
if (G.is_rendering)
if (flag & DUPLILIST_FOR_RENDER)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
}
}
@ -1512,9 +1514,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
if (part->draw & PART_DRAW_GLOBAL_OB)
add_v3_v3v3(mat[3], mat[3], vec);
dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED));
copy_m4_m4(dob->omat, oldobmat);
if (G.is_rendering)
if (flag & DUPLILIST_FOR_RENDER)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
}
@ -1566,7 +1568,7 @@ static Object *find_family_object(Object **obar, char *family, char ch)
}
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short animated)
static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag)
{
Object *ob, *obar[256] = {NULL};
Curve *cu;
@ -1605,7 +1607,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde
copy_m4_m4(obmat, par->obmat);
copy_v3_v3(obmat[3], vec);
new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, animated);
new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag);
}
}
@ -1615,7 +1617,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde
/* ------------- */
static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index,
int level, short animated, short update)
int level, short flag)
{
if ((ob->transflag & OB_DUPLI) == 0)
return;
@ -1635,31 +1637,31 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
if (ob->transflag & OB_DUPLIPARTS) {
ParticleSystem *psys = ob->particlesystem.first;
for (; psys; psys = psys->next)
new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, animated, update);
new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag);
}
else if (ob->transflag & OB_DUPLIVERTS) {
if (ob->type == OB_MESH) {
vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag);
}
else if (ob->type == OB_FONT) {
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
font_duplilist(duplilist, scene, ob, par_index, level + 1, animated);
font_duplilist(duplilist, scene, ob, par_index, level + 1, flag);
}
}
}
else if (ob->transflag & OB_DUPLIFACES) {
if (ob->type == OB_MESH)
face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, animated, update);
face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag);
}
else if (ob->transflag & OB_DUPLIFRAMES) {
if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */
frames_duplilist(duplilist, scene, ob, par_index, level + 1, animated);
frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag);
}
}
else if (ob->transflag & OB_DUPLIGROUP) {
DupliObject *dob;
group_duplilist(duplilist, scene, ob, par_index, level + 1, animated, update); /* now recursive */
group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */
if (level == 0) {
for (dob = duplilist->first; dob; dob = dob->next)
@ -1671,19 +1673,24 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas
/* Returns a list of DupliObject
* note; group dupli's already set transform matrix. see note in group_duplilist() */
ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update)
ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render)
{
ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist");
int flag = 0;
if(update) flag |= DUPLILIST_DO_UPDATE;
if(for_render) flag |= DUPLILIST_FOR_RENDER;
duplilist->first = duplilist->last = NULL;
object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, 0, update);
object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag);
return duplilist;
}
/* note: previously updating was always done, this is why it defaults to be on
* but there are likely places it can be called without updating */
ListBase *object_duplilist(Scene *sce, Object *ob)
ListBase *object_duplilist(Scene *sce, Object *ob, int for_render)
{
return object_duplilist_ex(sce, ob, TRUE);
return object_duplilist_ex(sce, ob, TRUE, for_render);
}

@ -2362,7 +2362,7 @@ int BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_ma
ListBase *lb;
DupliObject *dob;
lb = object_duplilist(scene, ob);
lb = object_duplilist(scene, ob, FALSE);
for (dob = lb->first; dob; dob = dob->next) {
if ((use_hidden == FALSE) && (dob->no_draw != 0)) {
/* pass */
@ -2439,7 +2439,7 @@ void BKE_scene_foreach_display_point(
ListBase *lb;
DupliObject *dob;
lb = object_duplilist(scene, ob);
lb = object_duplilist(scene, ob, FALSE);
for (dob = lb->first; dob; dob = dob->next) {
if (dob->no_draw == 0) {
BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data);

@ -1030,7 +1030,7 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
ListBase *lb_dupli_ob;
/* don't update the dupli groups, we only wan't their pid's */
if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE))) {
if ((lb_dupli_ob = object_duplilist_ex(scene, ob, FALSE, FALSE))) {
DupliObject *dob;
for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */

@ -744,7 +744,7 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob)
* this enters eternal loop because of
* makeDispListMBall getting called inside of group_duplilist */
if ((*base)->object->dup_group == NULL) {
duplilist = object_duplilist((*scene), (*base)->object);
duplilist = object_duplilist((*scene), (*base)->object, FALSE);
dupob = duplilist->first;

@ -7038,6 +7038,15 @@ static void do_version_ntree_keying_despill_balance(void *UNUSED(data), ID *UNUS
}
}
static void do_version_ntree_tex_coord_from_dupli_264(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
{
bNode *node;
for (node = ntree->nodes.first; node; node = node->next)
if (node->type == SH_NODE_TEX_COORD)
node->flag |= NODE_OPTIONS;
}
static void do_versions(FileData *fd, Library *lib, Main *main)
{
/* WATCH IT!!!: pointers from libdata have not been converted */
@ -7995,6 +8004,18 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
if (main->versionfile < 264 || (main->versionfile == 264 && main->subversionfile < 1)) {
bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER);
bNodeTree *ntree;
if (ntreetype && ntreetype->foreach_nodetree)
ntreetype->foreach_nodetree(main, NULL, do_version_ntree_tex_coord_from_dupli_264);
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
if (ntree->type==NTREE_SHADER)
do_version_ntree_tex_coord_from_dupli_264(NULL, NULL, ntree);
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */

@ -1086,7 +1086,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base,
if (!(base->object->transflag & OB_DUPLI))
return;
lb = object_duplilist(scene, base->object);
lb = object_duplilist(scene, base->object, FALSE);
if (use_hierarchy || use_base_parent) {
dupli_gh = BLI_ghash_ptr_new("make_object_duplilist_real dupli_gh");

@ -1389,6 +1389,11 @@ static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C),
uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
}
static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
}
static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
{
uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
@ -1470,6 +1475,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_TEX_VORONOI:
ntype->uifunc = node_shader_buts_tex_voronoi;
break;
case SH_NODE_TEX_COORD:
ntype->uifunc = node_shader_buts_tex_coord;
break;
case SH_NODE_BSDF_GLOSSY:
case SH_NODE_BSDF_GLASS:
ntype->uifunc = node_shader_buts_glossy;

@ -1918,7 +1918,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas
if (base->object->restrictflag & OB_RESTRICT_VIEW) return;
tbase.flag = OB_FROMDUPLI | base->flag;
lb = object_duplilist(scene, base->object);
lb = object_duplilist(scene, base->object, FALSE);
// BLI_sortlist(lb, dupli_ob_sort); /* might be nice to have if we have a dupli list with mixed objects. */
dob = dupli_step(lb->first);
@ -2331,7 +2331,7 @@ static void gpu_update_lamps_shadows(Scene *scene, View3D *v3d)
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
ListBase *lb = object_duplilist(scene, ob);
ListBase *lb = object_duplilist(scene, ob, FALSE);
for (dob = lb->first; dob; dob = dob->next)
if (dob->ob->type == OB_LAMP)

@ -1326,7 +1326,7 @@ short view3d_opengl_select(ViewContext *vc, unsigned int *buffer, unsigned int b
Base tbase;
tbase.flag = OB_FROMDUPLI;
lb = object_duplilist(scene, base->object);
lb = object_duplilist(scene, base->object, FALSE);
for (dob = lb->first; dob; dob = dob->next) {
tbase.object = dob->ob;

@ -1708,7 +1708,7 @@ static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, c
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(scene, ob);
ListBase *lb = object_duplilist(scene, ob, FALSE);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
Object *dob = dupli_ob->ob;
@ -1914,7 +1914,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L
if (ob->transflag & OB_DUPLI) {
DupliObject *dupli_ob;
ListBase *lb = object_duplilist(scene, ob);
ListBase *lb = object_duplilist(scene, ob, FALSE);
for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
Object *dob = dupli_ob->ob;

@ -841,7 +841,7 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
if (ob->transflag & OB_DUPLI) {
DupliObject *dob;
ListBase *lb = object_duplilist(shi->gpumat->scene, ob);
ListBase *lb = object_duplilist(shi->gpumat->scene, ob, FALSE);
for (dob=lb->first; dob; dob=dob->next) {
Object *ob_iter = dob->ob;

@ -409,7 +409,7 @@ int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct Poi
/* Internal functions that cycles uses so we need to declare (tsk tsk) */
struct Mesh *rna_Object_to_mesh(struct Object *ob, struct ReportList *reports, struct Scene *sce, int apply_modifiers, int settings);
void rna_Main_meshes_remove(struct Main *bmain, struct ReportList *reports, struct Mesh *mesh);
void rna_Object_create_duplilist(struct Object *ob, struct ReportList *reports, struct Scene *sce);
void rna_Object_create_duplilist(struct Object *ob, struct ReportList *reports, struct Scene *sce, int settings);
void rna_Object_free_duplilist(struct Object *ob);
void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);

@ -1720,6 +1720,16 @@ static void def_sh_tex_wave(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Node_update");
}
static void def_sh_tex_coord(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "from_dupli", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom1", 1);
RNA_def_property_ui_text(prop, "From Dupli", "Use the parent of the dupli object if possible");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_glossy(StructRNA *srna)
{
PropertyRNA *prop;

@ -92,7 +92,7 @@ DefNode( ShaderNode, SH_NODE_TEX_MUSGRAVE, def_sh_tex_musgrave, "TE
DefNode( ShaderNode, SH_NODE_TEX_VORONOI, def_sh_tex_voronoi, "TEX_VORONOI", TexVoronoi, "Voronoi Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_CHECKER, def_sh_tex_checker, "TEX_CHECKER", TexChecker, "Checker Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_BRICK, def_sh_tex_brick, "TEX_BRICK", TexBrick, "Brick Texture", "" )
DefNode( ShaderNode, SH_NODE_TEX_COORD, 0, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode( ShaderNode, SH_NODE_TEX_COORD, def_sh_tex_coord, "TEX_COORD", TexCoord, "Texture Coordinate","" )
DefNode( CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode( CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )

@ -2572,7 +2572,16 @@ static void rna_def_dupli_object(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list");
/* TODO: DupliObject has more properties that can be wrapped */
prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_float_sdna(prop, NULL, "orco");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space");
prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "uv");
RNA_def_property_array(prop, 2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space");
}
static void rna_def_object_base(BlenderRNA *brna)

@ -337,8 +337,10 @@ static void dupli_render_particle_set(Scene *scene, Object *ob, int level, int e
dupli_render_particle_set(scene, go->ob, level + 1, enable);
}
/* When no longer needed, duplilist should be freed with Object.free_duplilist */
void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce)
void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce, int settings)
{
int for_render = settings == eModifierMode_Render;
if (!(ob->transflag & OB_DUPLI)) {
BKE_report(reports, RPT_ERROR, "Object does not have duplis");
return;
@ -353,7 +355,7 @@ void rna_Object_create_duplilist(Object *ob, ReportList *reports, Scene *sce)
}
if (G.is_rendering)
dupli_render_particle_set(sce, ob, 0, 1);
ob->duplilist = object_duplilist(sce, ob);
ob->duplilist = object_duplilist(sce, ob, for_render);
if (G.is_rendering)
dupli_render_particle_set(sce, ob, 0, 0);
/* ob->duplilist should now be freed with Object.free_duplilist */
@ -608,6 +610,7 @@ void RNA_api_object(StructRNA *srna)
"objects real matrix and layers");
parm = RNA_def_pointer(func, "scene", "Scene", "", "Scene within which to evaluate duplis");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
parm = RNA_def_enum(func, "settings", mesh_type_items, 0, "", "Generate texture coordinates for rendering");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
func = RNA_def_function(srna, "dupli_list_clear", "rna_Object_free_duplilist");

@ -57,7 +57,7 @@ void register_node_type_sh_tex_coord(bNodeTreeType *ttype)
{
static bNodeType ntype;
node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, 0);
node_type_base(ttype, &ntype, SH_NODE_TEX_COORD, "Texture Coordinate", NODE_CLASS_INPUT, NODE_OPTIONS);
node_type_compatibility(&ntype, NODE_NEW_SHADING);
node_type_socket_templates(&ntype, NULL, sh_node_tex_coord_out);
node_type_size(&ntype, 150, 60, 200);

@ -4895,7 +4895,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp
/* create list of duplis generated by this object, particle
* system need to have render settings set for dupli particles */
dupli_render_particle_set(re, ob, timeoffset, 0, 1);
lb= object_duplilist(re->scene, ob);
lb= object_duplilist(re->scene, ob, TRUE);
dupli_render_particle_set(re, ob, timeoffset, 0, 0);
for (dob= lb->first; dob; dob= dob->next) {