void TubeRendererThread::run()
{
    int numThreads = GLFunctions::idealThreadCount;

    int chunkSize = m_data.size() / numThreads;

    int begin = m_id * chunkSize;
    int end = m_id * chunkSize + chunkSize;

    if ( m_id == numThreads - 1 )
    {
        end = m_data.size();
    }

    // for all voxels:
    for ( int i = begin; i < end; ++i )
    {
        QVector<float> fib = m_data[i];
        QVector<float> extra = m_extraData[i];

        if ( fib.size() < 9 )
        {
            printf( "fib with size < 3 detected" );
            continue;
        }

        int numFloats = fib.size();
        QVector3D lineStart( fib[0], fib[1], fib[2] );
        QVector3D lineEnd( fib[numFloats-3], fib[numFloats-2], fib[numFloats-1] );

        QVector3D globalColor( fabs( lineStart.x() - lineEnd.x() ), fabs( lineStart.y() - lineEnd.y() ), fabs( lineStart.z() - lineEnd.z() ) );
        globalColor.normalize();

        // push back the first vertex, done seperately because of nomal calculation
        QVector3D localColor( fib[0] - fib[3], fib[1] - fib[4], fib[2] - fib[5] );
        localColor.normalize();

        m_verts->push_back( fib[0] );
        m_verts->push_back( fib[1] );
        m_verts->push_back( fib[2] );
        m_verts->push_back( localColor.x() );
        m_verts->push_back( localColor.y() );
        m_verts->push_back( localColor.z() );
        m_verts->push_back( globalColor.x() );
        m_verts->push_back( globalColor.y() );
        m_verts->push_back( globalColor.z() );
        m_verts->push_back( extra.first() );
        m_verts->push_back( 1.0 );

        m_verts->push_back( fib[0] );
        m_verts->push_back( fib[1] );
        m_verts->push_back( fib[2] );
        m_verts->push_back( localColor.x() );
        m_verts->push_back( localColor.y() );
        m_verts->push_back( localColor.z() );
        m_verts->push_back( globalColor.x() );
        m_verts->push_back( globalColor.y() );
        m_verts->push_back( globalColor.z() );
        m_verts->push_back( extra.first() );
        m_verts->push_back( -1.0 );

        for ( int k = 1; k < fib.size() / 3 - 1; ++k )
        {
            QVector3D localColor( fib[k*3-3] - fib[k*3+3], fib[k*3-2] - fib[k*3+4], fib[k*3-1] - fib[k*3+5] );
            localColor.normalize();

            m_verts->push_back( fib[k*3] );
            m_verts->push_back( fib[k*3+1] );
            m_verts->push_back( fib[k*3+2] );
            m_verts->push_back( localColor.x() );
            m_verts->push_back( localColor.y() );
            m_verts->push_back( localColor.z() );
            m_verts->push_back( globalColor.x() );
            m_verts->push_back( globalColor.y() );
            m_verts->push_back( globalColor.z() );
            m_verts->push_back( extra[k] );
            m_verts->push_back( 1.0 );

            m_verts->push_back( fib[k*3] );
            m_verts->push_back( fib[k*3+1] );
            m_verts->push_back( fib[k*3+2] );
            m_verts->push_back( localColor.x() );
            m_verts->push_back( localColor.y() );
            m_verts->push_back( localColor.z() );
            m_verts->push_back( globalColor.x() );
            m_verts->push_back( globalColor.y() );
            m_verts->push_back( globalColor.z() );
            m_verts->push_back( extra[k] );
            m_verts->push_back( -1.0 );
        }

        QVector3D localColor2( fib[numFloats-6] - fib[numFloats-3], fib[numFloats-5] - fib[numFloats-2], fib[numFloats-4] - fib[numFloats-1] );
        localColor.normalize();
        // push back the last vertex, done seperately because of nomal calculation
        m_verts->push_back( fib[numFloats-3] );
        m_verts->push_back( fib[numFloats-2] );
        m_verts->push_back( fib[numFloats-1] );
        m_verts->push_back( localColor2.x() );
        m_verts->push_back( localColor2.y() );
        m_verts->push_back( localColor2.z() );
        m_verts->push_back( globalColor.x() );
        m_verts->push_back( globalColor.y() );
        m_verts->push_back( globalColor.z() );
        m_verts->push_back( extra.last() );
        m_verts->push_back( 1.0 );

        m_verts->push_back( fib[numFloats-3] );
        m_verts->push_back( fib[numFloats-2] );
        m_verts->push_back( fib[numFloats-1] );
        m_verts->push_back( localColor2.x() );
        m_verts->push_back( localColor2.y() );
        m_verts->push_back( localColor2.z() );
        m_verts->push_back( globalColor.x() );
        m_verts->push_back( globalColor.y() );
        m_verts->push_back( globalColor.z() );
        m_verts->push_back( extra.last() );
        m_verts->push_back( -1.0 );
    }
}
Example #2
0
void FiberRenderer::initGeometry()
{
    if ( m_isInitialized )
    {
        return;
    }
    qDebug() << "create fiber vbo's...";

    std::vector<float>verts;

    try
    {
        verts.reserve( m_numPoints * 6 );
    }
    catch ( std::bad_alloc& )
    {
        qCritical() << "***error*** failed to allocate enough memory for vbo";
        exit ( 0 );
    }


    for ( unsigned int i = 0; i < m_fibs->size(); ++i )
    {
        Fib fib = m_fibs->at(i);

        if ( fib.length() < 2 )
        {
            printf( "fib with size < 2 detected" );
            continue;
        }

        QVector3D lineStart = fib.firstVert();
        QVector3D lineEnd = fib.lastVert();

        // push back the first vertex, done seperately because of nomal calculation
        verts.push_back( lineStart.x() );
        verts.push_back( lineStart.y() );
        verts.push_back( lineStart.z() );

        QVector3D secondVert = fib.getVert( 1 );

        QVector3D localColor( lineStart.x() - secondVert.x(), lineStart.y() - secondVert.y(), lineStart.z() - secondVert.z() );
        localColor.normalize();

        verts.push_back( localColor.x() );
        verts.push_back( localColor.y() );
        verts.push_back( localColor.z() );

        for ( unsigned int k = 1; k < fib.length() - 1; ++k )
        {
            verts.push_back( fib[k].x() );
            verts.push_back( fib[k].y() );
            verts.push_back( fib[k].z() );

            QVector3D localColor( fib[k-1].x() - fib[k+1].x(), fib[k-1].y() - fib[k+1].y(), fib[k-1].z() - fib[k+1].z() );
            localColor.normalize();

            verts.push_back( localColor.x() );
            verts.push_back( localColor.y() );
            verts.push_back( localColor.z() );

        }

        // push back the last vertex, done seperately because of nomal calculation
        verts.push_back( lineEnd.x() );
        verts.push_back( lineEnd.y() );
        verts.push_back( lineEnd.z() );

        QVector3D sec2last = fib[ fib.length() - 2 ];
        QVector3D localColor2( sec2last.x() - lineEnd.x(), sec2last.y() - lineEnd.y(), sec2last.z() - lineEnd.z() );
        localColor.normalize();

        verts.push_back( localColor2.x() );
        verts.push_back( localColor2.y() );
        verts.push_back( localColor2.z() );
    }

    glBindBuffer( GL_ARRAY_BUFFER, vbo );
    glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof(GLfloat), verts.data(), GL_STATIC_DRAW );
    glBindBuffer( GL_ARRAY_BUFFER, 0 );
    verts.clear();

    m_pointsPerLine.resize( m_fibs->size() );
    m_startIndexes.resize( m_fibs->size() );

    int currentStart = 0;
    for ( unsigned int i = 0; i < m_fibs->size(); ++i )
    {
        m_pointsPerLine[i] = m_fibs->at( i ).length();
        m_startIndexes[i] = currentStart;
        currentStart += m_pointsPerLine[i];
    }

    updateExtraData( 0 );

    qDebug() << "create fiber vbo's done";

    m_numPoints = verts.size() / 6;

    m_isInitialized = true;
}
Example #3
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

/* @param background_color this is not ambient light */
void raytracing(void* args)
{
    arg *data = (arg*) args;
    point3 u, v, w, d;
    color object_color = { 0.0, 0.0, 0.0 };

    const viewpoint *view = (*data).View;
    color back = { 0.0 , 0.1 , 0.1 };
    uint8_t *pixels = data->pixels;
    int start_j,end_j;

    /*	Separate to count the pixels  */
    if(pthread_equal(pthread_self(),THREAD[0])) {
        start_j = 0;
        end_j = 128;
    } else if(pthread_equal(pthread_self(),THREAD[1])) {
        start_j = 128;
        end_j = 256;
    } else if(pthread_equal(pthread_self(),THREAD[2])) {
        start_j = 256;
        end_j = 384;
    } else if(pthread_equal(pthread_self(),THREAD[3])) {
        start_j = 384;
        end_j = 512;
    }

    /* calculate u, v, w */
    calculateBasisVectors(u, v, w, view);

    idx_stack stk;

    int factor = sqrt(SAMPLES);

    #pragma omp parallel for num_threads(64)	\
    private(stk), private(d),	\
    private(object_color)
    for (int j = start_j ; j < end_j; j++) {
        for (int i = 0 ; i < (*data).row; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, u, v, w,
                                i * factor + s / factor,
                                j * factor + s % factor,
                                view,
                                (*data).row * factor, (*data).col * factor);
                if (ray_color(view->vrp, 0.0, d, &stk,(*data).rectangulars,
                              (*data).spheres, (*data).lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += back[0];
                    g += back[1];
                    b += back[2];
                }
                pixels[((i + (j * (*data).row)) * 3) + 0] = r * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 1] = g * 255 / SAMPLES;
                pixels[((i + (j * (*data).row)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
}
Example #4
0
static unsigned int ray_color(const point3 e, double t,
                              const point3 d,
                              idx_stack *stk,
                              const rectangular_node rectangulars,
                              const sphere_node spheres,
                              const light_node lights,
                              color object_color, int bounces_left)
{
    rectangular_node hit_rec = NULL, light_hit_rec = NULL;
    sphere_node hit_sphere = NULL, light_hit_sphere = NULL;
    double diffuse, specular;
    point3 l, _l, r, rr;
    object_fill fill;

    color reflection_part;
    color refraction_part;
    /* might be a reflection ray, so check how many times we've bounced */
    if (bounces_left == 0) {
        SET_COLOR(object_color, 0.0, 0.0, 0.0);
        return 0;
    }

    /* check for intersection with a sphere or a rectangular */
    intersection ip= ray_hit_object(e, d, t, MAX_DISTANCE, rectangulars,
                                    &hit_rec, spheres, &hit_sphere);
    if (!hit_rec && !hit_sphere)
        return 0;

    /* pick the fill of the object that was hit */
    fill = hit_rec ?
           hit_rec->element.rectangular_fill :
           hit_sphere->element.sphere_fill;

    void *hit_obj = hit_rec ? (void *) hit_rec : (void *) hit_sphere;

    /* assume it is a shadow */
    SET_COLOR(object_color, 0.0, 0.0, 0.0);

    for (light_node light = lights; light; light = light->next) {
        /* calculate the intersection vector pointing at the light */
        subtract_vector(ip.point, light->element.position, l);
        multiply_vector(l, -1, _l);
        normalize(_l);
        /* check for intersection with an object. use ignore_me
         * because we don't care about this normal
        */
        ray_hit_object(ip.point, _l, MIN_DISTANCE, length(l),
                       rectangulars, &light_hit_rec,
                       spheres, &light_hit_sphere);
        /* the light was not block by itself(lit object) */
        if (light_hit_rec || light_hit_sphere)
            continue;

        compute_specular_diffuse(&diffuse, &specular, d, l,
                                 ip.normal, fill.phong_power);

        localColor(object_color, light->element.light_color,
                   diffuse, specular, &fill);
    }

    reflection(r, d, ip.normal);
    double idx = idx_stack_top(stk).idx, idx_pass = fill.index_of_refraction;
    if (idx_stack_top(stk).obj == hit_obj) {
        idx_stack_pop(stk);
        idx_pass = idx_stack_top(stk).idx;
    } else {
        idx_stack_element e = { .obj = hit_obj,
                                .idx = fill.index_of_refraction
                              };
        idx_stack_push(stk, e);
    }

    refraction(rr, d, ip.normal, idx, idx_pass);
    double R = (fill.T > 0.1) ?
               fresnel(d, rr, ip.normal, idx, idx_pass) :
               1.0;

    /* totalColor = localColor +
                    mix((1-fill.Kd) * fill.R * reflection, T * refraction, R)
     */
    if (fill.R > 0) {
        /* if we hit something, add the color */
        int old_top = stk->top;
        if (ray_color(ip.point, MIN_DISTANCE, r, stk, rectangulars, spheres,
                      lights, reflection_part,
                      bounces_left - 1)) {
            multiply_vector(reflection_part, R * (1.0 - fill.Kd) * fill.R,
                            reflection_part);
            add_vector(object_color, reflection_part,
                       object_color);
        }
        stk->top = old_top;
    }
    /* calculate refraction ray */
    if ((length(rr) > 0.0) && (fill.T > 0.0) &&
            (fill.index_of_refraction > 0.0)) {
        normalize(rr);
        if (ray_color(ip.point, MIN_DISTANCE, rr, stk,rectangulars, spheres,
                      lights, refraction_part,
                      bounces_left - 1)) {
            multiply_vector(refraction_part, (1 - R) * fill.T,
                            refraction_part);
            add_vector(object_color, refraction_part,
                       object_color);
        }
    }

    protect_color_overflow(object_color);
    return 1;
}

static void *parallel (void* range1)
{
    Thread_range *range = (Thread_range *)range1;

    point3 d;
    idx_stack stk;
    color object_color = { 0.0, 0.0, 0.0 };

    for (int j = range->height1; j < range->height2; j++) {
        for (int i = 0; i < range->ptr->width; i++) {
            double r = 0, g = 0, b = 0;
            /* MSAA */
            for (int s = 0; s < SAMPLES; s++) {
                idx_stack_init(&stk);
                rayConstruction(d, range->ptr->u,
				range->ptr->v, range->ptr->w,
                                i * range->ptr->factor + s / range->ptr->factor,
                                j * range->ptr->factor + s % range->ptr->factor,
                                range->ptr->view,
                                range->ptr->width * range->ptr->factor, 
				range->ptr->height * range->ptr->factor);
                if (ray_color(range->ptr->view->vrp, 0.0, d,
			      &(stk), range->ptr->rectangulars,
			      range->ptr->spheres,
                              range->ptr->lights, object_color,
                              MAX_REFLECTION_BOUNCES)) {
                    r += object_color[0];
                    g += object_color[1];
                    b += object_color[2];
                } else {
                    r += range->ptr->background_color[0];
                    g += range->ptr->background_color[1];
                    b += range->ptr->background_color[2];
                }
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 0] = r * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 1] = g * 255 / SAMPLES;
                range->ptr->pixels[((i + (j * range->ptr->width)) * 3) + 2] = b * 255 / SAMPLES;
            }
        }
    }
	return NULL;
}