2
$\begingroup$

In the OSL spec, there is a an optional parameter in a trace call for a 'traceset'.

I would like to restrict a trace to only hit the same object. The solution I have right now is to get the object name and test the trace object name after it hits like this:

// start OSL code fragment string thisobjname = ""; getattribute("geom:name",thisobjname); int hit = trace(P, ((_var_42 - 0.5) * 2.0), ); string hitobjname = ""; getmessage("trace","geom:name",hitobjname); if( hit && hitobjname==thisobjname) printf("trace hit the same object"); // end OSL code fragment

I tried the following, but it does not work.

// start OSL code fragment string thisobjname = ""; getattribute("geom:name",thisobjname); int hit = trace(P, ((_var_42 - 0.5) * 2.0), "traceset", thisobjname ); string hitobjname = ""; getmessage("trace","geom:name",hitobjname); if( hit) printf("trace hit the same object"); // end OSL code fragment

How does the 'traceset' need to be formatted to work? Is there something else wrong?

$\endgroup$
0
1
$\begingroup$

I have traced this back to the OSL code where the 'traceset' is accepted and passed out to the compiled 'oso' file. This is further passed to Cycles to be executed and does indeed include the 'traceset' string.

However, on picking through the Cycles source code I came across the only reference to 'traceset' in the following function (trace) :

bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg,
    const OSL::Vec3 &P, const OSL::Vec3 &dPdx,
    const OSL::Vec3 &dPdy, const OSL::Vec3 &R,
    const OSL::Vec3 &dRdx, const OSL::Vec3 &dRdy)
{
    /* todo: options.shader support, maybe options.traceset */
    ShaderData *sd = (ShaderData *)(sg->renderstate);

    /* setup ray */
    Ray ray;

    ray.P = TO_FLOAT3(P);
    ray.D = TO_FLOAT3(R);
    ray.t = (options.maxdist == 1.0e30f)? FLT_MAX: options.maxdist - options.mindist;
    ray.time = sd->time;

    if(options.mindist == 0.0f) {
        /* avoid self-intersections */
        if(ray.P == sd->P) {
            bool transmit = (dot(sd->Ng, ray.D) < 0.0f);
            ray.P = ray_offset(sd->P, (transmit)? -sd->Ng: sd->Ng);
        }
    }
    else {
        /* offset for minimum distance */
        ray.P += options.mindist*ray.D;
    }

    /* ray differentials */
    ray.dP.dx = TO_FLOAT3(dPdx);
    ray.dP.dy = TO_FLOAT3(dPdy);
    ray.dD.dx = TO_FLOAT3(dRdx);
    ray.dD.dy = TO_FLOAT3(dRdy);

    /* allocate trace data */
    OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata;
    tracedata->ray = ray;
    tracedata->setup = false;
    tracedata->init = true;
    tracedata->sd.osl_globals = sd->osl_globals;

    /* raytrace */
    return scene_intersect(sd->osl_globals, ray, PATH_RAY_ALL_VISIBILITY, &tracedata->isect, NULL, 0.0f, 0.0f);
}

Note the comment /* todo: options.shader support, maybe options.traceset */ - this is the only mention in Cycles source of 'traceset'. So, although the 'traceset' is passed into Cycles from the OSL shader it is not actually processed. This would seem to show that the 'traceset' option of the OSL 'trace' call has not yet been implemented.

$\endgroup$
2
  • $\begingroup$ This is great investigation! Which version of the Blender was this source code from? $\endgroup$ – Ed Tate Apr 21 '18 at 14:44
  • $\begingroup$ Thanks @EdTate. It was the latest Cycles and latest OSL so, presumably, all Blender versions. $\endgroup$ – Rich Sedman Apr 21 '18 at 14:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.