void init_LUMINANCE_UBYTE(
        vl::Actor* actor,
        vl::Image* img,
        vl::fvec3 scale = vl::fvec3(10.0f, 10, 10.0f),
        int threshold_min = 32,
        int threshold_max = 255,
        const TF& transfer_func = TransferRGBA_255() )
    {
        if (img->type() != vl::IT_UNSIGNED_BYTE || img->format() != vl::IF_LUMINANCE)
        {
            vl::Log::error("init_LUMINANCE_UBYTE() error:\n" + img->print() );
            return;
        }

        vl::ref<vl::Geometry> geometry;
        vl::ref<vl::ArrayFloat3> points;
        vl::ref<vl::DrawElementsUInt> draw_elements;
        vl::ref<vl::ArrayFloat3> eye_space_points;

        eye_space_points = new vl::ArrayFloat3;
        geometry = new vl::Geometry;
        points = new vl::ArrayFloat3;
        vl::ref<vl::ArrayFloat3> norms = new vl::ArrayFloat3;
        draw_elements = new vl::DrawElementsUInt(vl::PT_POINTS);
        vl::ref<vl::ArrayUByte4> color = new vl::ArrayUByte4;

        geometry->setVertexArray( points.get() );
        geometry->setNormalArray( norms.get() );
        geometry->setColorArray( color.get() );
        geometry->drawCalls()->push_back( draw_elements.get() );

        int point_count = 0;
        for(int index = 0, z=0; z<img->depth(); ++z)
        {
            for(int y=0; y<img->height(); ++y)
            {
                for(int x=0; x<img->width(); ++x, ++index)
                {
                    int val = img->pixels()[ x + y*img->pitch() + z*img->height()*img->pitch() ];
                    if ( val >= threshold_min && val <= threshold_max)
                        ++point_count;
                }
            }
        }

#ifndef NDEBUG
        vl::Log::print(vl::Say("original points = %6.0nK\n") << img->depth() * img->height() * img->width() / 1000.0f );
        vl::Log::print(vl::Say("accepted points = %6.0nK\n") << point_count / 1000.0f);
        vl::Log::print(vl::Say("simplif. ratio  = %n%%\n") << (1.0f - (float)point_count / (img->depth() * img->height() * img->width())) * 100.0f );
#endif

        points->resize( point_count );
        norms->resize( point_count );
        draw_elements->indexBuffer()->resize( point_count );
        color->resize( point_count );

        for(int index = 0, z=0; z<img->depth(); ++z)
        {
            for(int y=0; y<img->height(); ++y)
            {
                for(int x=0; x<img->width(); ++x)
                {
                    int val = img->pixels()[ x + y*img->pitch() + z*img->height()*img->pitch() ];

                    if ( val >= threshold_min && val <= threshold_max)
                    {
                        float tx = (float)x / ( img->width() -1 );
                        float ty = (float)y / ( img->height()-1 );
                        float tz = (float)z / ( img->depth() -1 );

                        points->at(index) = vl::fvec3(tx*scale.x() - scale.x()*0.5f, ty*scale.y() - scale.y()*0.5f, tz*scale.z() - scale.z()*0.5f);

                        // compute normal
                        int x1 = x-1;
                        int x2 = x+1;
                        int y1 = y-1;
                        int y2 = y+1;
                        int z1 = z-1;
                        int z2 = z+1;
                        x2 = x2 > img->width()  -1 ? img->width() -1 : x2;
                        y2 = y2 > img->height() -1 ? img->height()-1 : y2;
                        z2 = z2 > img->depth()  -1 ? img->depth() -1 : z2;
                        x1 = x1 < 0 ? 0 : x1;
                        y1 = y1 < 0 ? 0 : y1;
                        z1 = z1 < 0 ? 0 : z1;
                        float vx1 = img->pixels()[ x1 + y*img->pitch() + z*img->height()*img->pitch() ];
                        float vx2 = img->pixels()[ x2 + y*img->pitch() + z*img->height()*img->pitch() ];
                        float vy1 = img->pixels()[ x + y1*img->pitch() + z*img->height()*img->pitch() ];
                        float vy2 = img->pixels()[ x + y2*img->pitch() + z*img->height()*img->pitch() ];
                        float vz1 = img->pixels()[ x + y*img->pitch() + z1*img->height()*img->pitch() ];
                        float vz2 = img->pixels()[ x + y*img->pitch() + z2*img->height()*img->pitch() ];

                        vl::fvec3 normal(vx1-vx2, vy1-vy2, vz1-vz2);
                        normal.normalize();
                        norms->at(index) = normal;

                        unsigned char r=0,g=0,b=0,a=0;
                        transfer_func(img->pixels()[x + y*img->pitch() + z*img->height()*img->pitch()], r,g,b,a);
                        color->at(index) = vl::ubvec4(r,g,b,a);

                        draw_elements->indexBuffer()->at(index) = index;

                        ++index;
                    }
                }
            }
        }

        actor->setLod(0, geometry.get());
        geometry->setDisplayListEnabled(false);
        geometry->setBufferObjectEnabled(true);

        if (vl::Has_GL_ARB_vertex_buffer_object)
        {
            color->bufferObject()->setBufferData(vl::BU_STATIC_DRAW);
            points->bufferObject()->setBufferData(vl::BU_STATIC_DRAW);
            norms->bufferObject()->setBufferData(vl::BU_STATIC_DRAW);
            draw_elements->indexBuffer()->bufferObject()->setBufferData(vl::BU_DYNAMIC_DRAW);
        }

        eye_space_points->resize( points->size() );
    }
vl::fvec3 CoreFunctions::getNewPointPosition(vl::fvec3 pPoint1, vl::fvec3 pPoint2, float pValueX)
{
	float maxDistance;
	float partDistance;
	float multiplier;
	float valueY;
	float valueZ;
	
	if (pPoint1.x() > pPoint2.x())
	{
		vl::fvec3 tmpPoint = pPoint1;
		pPoint1 = pPoint2;
		pPoint2 = tmpPoint;
	}

	maxDistance = computeDistance(pPoint1.x(), pPoint2.x());
	partDistance = computeDistance(pPoint1.x(), pValueX);
	multiplier = partDistance / maxDistance;

	maxDistance = computeDistance(pPoint1.y(), pPoint2.y());
	partDistance = maxDistance * multiplier;
	if (pPoint1.y() < pPoint2.y())
	{
		valueY = pPoint1.y() + partDistance;
	}
	else 
	{
		valueY = pPoint1.y() - partDistance;
	}

	maxDistance = computeDistance(pPoint1.z(), pPoint2.z());
	partDistance = maxDistance * multiplier;
	if (pPoint1.z() < pPoint2.z())
	{
		valueZ = pPoint1.z() + partDistance;
	}
	else 
	{
		valueZ = pPoint1.z() - partDistance;
	}

	return vl::fvec3(pValueX, valueY, valueZ);
}