Object Indexer Input Shader Node

Hi,

I’m just writing a shadernode ‘ObjectIndexer’ that provides a ‘Fac’ computed from the number of an object name among others object sharing the same prefix name.
Eg :
Cube.012 => give object number 12
The factor is then computed from the total objects sharing the same prefix (eg ‘Cube’).

Because it is not currently possible to compute a ‘true’ shader with the Python ShaderNode API (ie a shader that really acts at rendering time for every object sharing the same material), the tool comes in 2 parts :

  • shaderNodeObjectIndexer.py : compute value from the scene (Total number of objects)
  • node_objectindexer.osl : really compute our Factor (and other values)

For those that have used the ‘ObjectInfo’ node, they perhaps know about its ‘Object Index’ output : it is computed from the ‘pass_index’ property of an object.
This means that you must set the pass_index property, then you can use it as a ShaderNode parameter.
My tool doesn’t set pass_index, it computes the object index from its name.

Next release will use an external spacial reference (other object that will modify the object precedence in the group) : Reference/Influence Inputs + RefLoc/InfLoc outputs.
Currently, they doesn’t work at all. Don’t use them.

How to use it :

  • On your scene, you have duplicated an object and have a scene with many copies (Cube,Cube.001,Cube.002, …)
  • on your scene, these objects share the same material (eg: Object > Make Links > Material)
    On the Node editor
  • select one of these object.
  • add a Script node, link it to node_objectindexer.osl, refresh.
  • link its Fac output to the Fac input of a ColorRamp for example.
  • load shaderNodeObjectIndexer.py on the “Text Editor”, then “Run Script” (alt+p)
  • add ‘Object Indexer’ node (from Input Shader category), link its Total output to the Total input of the osl.
  • from ‘Object Indexer’, apply ‘Auto Update’
    That’s all.

The ‘AutoUpdate’ option can be used for those that prefer to set the Total manually (ie. huge number of objects …)
Let me know if you encounter some troubles.
Hope it helps …

Thanks,

Valery


EDIT :
A very small demo video here on what could be done:

Attachments

objectindexer.zip (117 KB)

Hi everyboy,
here’s the last version of node_objectindexer.osl ; it is better to use it alone (I means w/o the python node previously posted here). Just remember to set the ‘Total’ input properly as the total number of same objects on which you want to apply this shader. I will upload a demo video on how to use every input sockets. Shortly, you can now hide/show all or part of your objects, and shift value in order to ordering your ‘clones’ differently. As you can see on the picture, a small set of objects among an array of 100 are shown. See comments on the scripts for more explanation. cu soon …
Happy blendering,
Val.

/*********************************************************************************************
 NAME : nodeObjectIndexer
 
 TYPE : Input Shader

 DESCRIPTION : output an index computed from the value found on the object name
                eg : object.012 => 12 ; don't use or set pass_index.
               objectname must be in the form : name.index (name dot index)
               If objectName has no index, it will be set to '1', otherwise its number + 1
               nodeObjectIndexer don't know anything about the scene, 
               so the total of same object must be provided from the outside or manually
               ( see nodeObjectIndexer.py )

 SOCKETS : 
     Outputs :
         ObjectNumber     : int     - suffix object number ('object.012' => 12 and 'object' => 0)
        Fac                : float - object number from 0 to 1 depending on the Total of clones
        Even            : int    - 0,1 : is the number Even or not
        Odd                : int    - 0,1 : is the number odd or not
        GreyRGB            : float - same as Fac but as a grey color
        InRange            : int    - 0,1 : is the number in the range [Lower..Upper] or not
    Inputs:
        Min                : float - lower bound of Fac ( Min <= Fac <= Max ) btw 0 and 1 (vavlue 'clamped')
        Max                : float - upper bound of Fac - btw 0) and 1 (value 'clamped') 
        Total            : int    - total number of same object
        Decal            : int    - add 'Decal' to the number of the object every 'Every' objects
        Every            : int    - see 'Decal'
        Lower            : int    - lower bound of InRange output
        Upper            : int    - upper bound of InRange output

 FORMULA : 
    1. 'Factorize' object suffix number within a range :

                 /   ObjectNumber                  \
     Fac = Min + |  -------------- * ( Max - Min ) |   
                 \      Total                      /
    
     with 0.0 <= Min <= 1.0
     and  0.1 <= Max <= 1.0

     so: [ Min <= Fac <= indexMax ]
     So, Fac is in equal part of the total number of objects inside the range.

    TODO :
     2. outputIndex from Spacial reference from other object (SNOI_OREF, SNOI_OEXT)
     2.1 Absolute
     2.2 Relative

 AUTHOR 
     Valery Seys - Paris /\

 CHANGELOG
    10/12/15 14:38    initial
    12/12/15 15:53    adding Decal/Every and Lower/Upper range
                    adding Even/Odd output

*********************************************************************************************/

int getObjectNumber() {
    string oname = "?";
    string os[2];
    int slen = 0;
    int onumber = 0;                // Seed obect has number 0

    getattribute("geom:name",oname);
    slen = split(oname, os, ".", 2);
    if ( slen > 1) {
        onumber = stoi(os[1]);
    }
    return onumber;
}

float getObjectFactor(int on, float minBound, float maxBound, int total) {

    return ( minBound + ( (float(on) / total) * (maxBound - minBound)));
}

shader node_object_indexer(
    float Min = 0.0,
    float Max = 1.0,
    int Total = 1,
    int Shift = 0,
    int Every = 1,
    int Lower = 1,
    int Upper = 1,
    output int ObjectNumber = 1,
    output float Fac = 0.5,
    output int Even = 0,
    output int Odd = 0,
    output color GreyRGB = color(0,0,0),
    output int inRange = 0
    )
{
    float minIndex = clamp(Min,0.0,1.0);
    float maxIndex = clamp(Max,0.1,1.0);
    int totalIndex = Total;
    float d = 0;
    
    if ( totalIndex <= 0 ) {
        totalIndex=1;
    }
   
       /* Outputing */
    ObjectNumber = getObjectNumber();
    if ( Shift != 0) {
        d = Shift * (floor(ObjectNumber/Every));
        ObjectNumber = mod(ObjectNumber + int(d), Total);
    }
    inRange = ( ObjectNumber >= Lower ) && ( ObjectNumber <= Upper) ? 1 : 0;
    Fac = getObjectFactor(ObjectNumber,minIndex,maxIndex,totalIndex);
    Odd = (ObjectNumber & 1) * 1;
    Even = !(ObjectNumber & 1) * 1;
    GreyRGB = color(Fac);
}


EDIT : as said, a small Video showing how to use the shader (some avsync out, sorry, I can’t do better)