float3 Camera::transform_raster_to_world(float raster_x, float raster_y)
{
	float3 D, P;
	if(type == CAMERA_PERSPECTIVE) {
		D = transform_perspective(&rastertocamera,
		                          make_float3(raster_x, raster_y, 0.0f));
		float3 Pclip = normalize(D);
		P = make_float3(0.0f, 0.0f, 0.0f);
		/* TODO(sergey): Aperture support? */
		P = transform_point(&cameratoworld, P);
		D = normalize(transform_direction(&cameratoworld, D));
		/* TODO(sergey): Clipping is conditional in kernel, and hence it could
		 * be mistakes in here, currently leading to wrong camera-in-volume
		 * detection.
		 */
		P += nearclip * D / Pclip.z;
	}
	else if(type == CAMERA_ORTHOGRAPHIC) {
		D = make_float3(0.0f, 0.0f, 1.0f);
		/* TODO(sergey): Aperture support? */
		P = transform_perspective(&rastertocamera,
		                          make_float3(raster_x, raster_y, 0.0f));
		P = transform_point(&cameratoworld, P);
		D = normalize(transform_direction(&cameratoworld, D));
	}
	else {
		assert(!"unsupported camera type");
	}
	return P;
}
Exemple #2
0
float Camera::world_to_raster_size(float3 P)
{
	if(type == CAMERA_ORTHOGRAPHIC) {
		return min(len(full_dx), len(full_dy));
	}
	else if(type == CAMERA_PERSPECTIVE) {
		/* Calculate as if point is directly ahead of the camera. */
		float3 raster = make_float3(0.5f*width, 0.5f*height, 0.0f);
		float3 Pcamera = transform_perspective(&rastertocamera, raster);

		/* dDdx */
		float3 Ddiff = transform_direction(&cameratoworld, Pcamera);
		float3 dx = len_squared(full_dx) < len_squared(full_dy) ? full_dx : full_dy;
		float3 dDdx = normalize(Ddiff + dx) - normalize(Ddiff);

		/* dPdx */
		float dist = len(transform_point(&worldtocamera, P));
		float3 D = normalize(Ddiff);
		return len(dist*dDdx - dot(dist*dDdx, D)*D);
	}
	else {
		// TODO(mai): implement for CAMERA_PANORAMA
		assert(!"pixel width calculation for panoramic projection not implemented yet");
	}

	return 1.0f;
}
Exemple #3
0
// \en Calculates intersections. Stores intersection info to intersections and returns the number of intersections.\enden \ja 交点計算を行う。交点の情報はintersectionsに格納し、交点の数を返す。 \endja 
// \en The ray is defined as the starting point o and the normalized direction vector d as in o + td, 0.0 <= t.\enden \ja レイは始点位置ベクトルo、単位方向ベクトルdから成る、o + td, 0.0 <= t として指定される。 \endja 
int attribute_component::ray_intersection (const sxsdk::custom_element_info_base_class *info, sxsdk::shape_class &shape, const sxsdk::mat4 &lw, const sxsdk::mat4 &wl, int i, const sx::vec<float,3> &o, const sx::vec<float,3> &d, sxsdk::intersection_class intersections[], sxsdk::custom_element_info_base_class *per_thread, void *) {
	{	custom_element_info__class *info = dynamic_cast<custom_element_info__class *>(per_thread);
		if (info) {
			for (int i = 0; i < 100; i++) info->data[i] = i;
		}
	}
	int n = 0;
	sxsdk::sphere_class &sphere = shape.get_sphere();
	if (info) {

		// \en Fetch the data created in the new_custom_element_info function.\enden \ja new_custom_element_infoで作成したデータを取得する。 \endja 
		const float size = dynamic_cast<const custom_size_class &>(*info).size;

		sxsdk::mat4 t = sphere.get_matrix();
		for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) t[i][j] *= size;
		t *= lw;
		sxsdk::mat4 itrans = inv(t);
		sx::vec<float,3> p2 = o * itrans; // \en Transform the starting point of the ray to the sphere primitive coordinates.\enden \ja レイの始点位置ベクトルを球プリミティブ座標系に変換する。 \endja 
		sx::vec<float,3> d2 = transform_direction(d, itrans); // \en Transform the normalized direction vector of the ray to the sphere primitive coordinates.\enden \ja レイの単位方向ベクトルを球プリミティブ座標系に変換する。 \endja 
		
		// \en Calculate the intersections between the sphere and the ray.\enden \ja 球とレイの交点計算。 \endja 
		float a = d2.x * d2.x + d2.y * d2.y + d2.z * d2.z;
		float b = p2.x * d2.x + p2.y * d2.y + p2.z * d2.z;
		float c = p2.x * p2.x + p2.y * p2.y + p2.z * p2.z - 1.0f;
		float k = b*b - a*c;
		if (k <= 0.0f) ;
		else {
			k = sqrt(k);
			float t1 = (-b + k) / a;
			float t0 = (-b - k) / a;
			//sxassert(t0 <= t1);
			if (0.0f <= t0) {
				intersections[n].t = t0;
				sx::vec<float,3> normal = p2 + d2 * t0;
				intersections[n].normal = normalize(transform_normal(itrans, normal));
				intersections[n].point = o + d * t0;
				
				// \en Merge Info.\enden \ja 融合情報 \endja 
				if (shape.has_sis()) {
					intersections[n].number_of_shapes = 2;
					//sxassert(intersections[n].shape_mixes);
					intersections[n].shape_mixes[1] = sxsdk::shape_mix_class(0.5f, shape.get_sis());
					intersections[n].shape_mixes[0] = sxsdk::shape_mix_class(0.5f, &shape);
				}
				n++;
			}
			if (0.0f <= t1) {
				intersections[n].t = t1;
				sx::vec<float,3> normal = p2 + d2 * t1;
				intersections[n].normal = normalize(transform_normal(itrans, normal));
				intersections[n].point = o + d * t1;
				
				// \en Merge Info.\enden \ja 融合情報 \endja 
				if (shape.has_sis()) {
					intersections[n].number_of_shapes = 2;
					//sxassert(intersections[n].shape_mixes);
					intersections[n].shape_mixes[1] = sxsdk::shape_mix_class(0.5f, shape.get_sis());
					intersections[n].shape_mixes[0] = sxsdk::shape_mix_class(0.5f, &shape);
				}
				n++;
			}
		}
	}
	return n;
}
void Camera::update()
{
	if(!need_update)
		return;

	/* Full viewport to camera border in the viewport. */
	Transform fulltoborder = transform_from_viewplane(viewport_camera_border);
	Transform bordertofull = transform_inverse(fulltoborder);

	/* ndc to raster */
	Transform screentocamera;
	Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull;

	/* raster to screen */
	Transform screentondc = fulltoborder * transform_from_viewplane(viewplane);

	Transform screentoraster = ndctoraster * screentondc;
	Transform rastertoscreen = transform_inverse(screentoraster);

	/* screen to camera */
	if(type == CAMERA_PERSPECTIVE)
		screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip));
	else if(type == CAMERA_ORTHOGRAPHIC)
		screentocamera = transform_inverse(transform_orthographic(nearclip, farclip));
	else
		screentocamera = transform_identity();
	
	Transform cameratoscreen = transform_inverse(screentocamera);

	rastertocamera = screentocamera * rastertoscreen;
	cameratoraster = screentoraster * cameratoscreen;

	cameratoworld = matrix;
	screentoworld = cameratoworld * screentocamera;
	rastertoworld = cameratoworld * rastertocamera;
	ndctoworld = rastertoworld * ndctoraster;

	/* note we recompose matrices instead of taking inverses of the above, this
	 * is needed to avoid inverting near degenerate matrices that happen due to
	 * precision issues with large scenes */
	worldtocamera = transform_inverse(matrix);
	worldtoscreen = cameratoscreen * worldtocamera;
	worldtondc = screentondc * worldtoscreen;
	worldtoraster = ndctoraster * worldtondc;

	/* differentials */
	if(type == CAMERA_ORTHOGRAPHIC) {
		dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
		dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
	}
	else if(type == CAMERA_PERSPECTIVE) {
		dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
		     transform_perspective(&rastertocamera, make_float3(0, 0, 0));
		dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
		     transform_perspective(&rastertocamera, make_float3(0, 0, 0));
	}
	else {
		dx = make_float3(0.0f, 0.0f, 0.0f);
		dy = make_float3(0.0f, 0.0f, 0.0f);
	}

	dx = transform_direction(&cameratoworld, dx);
	dy = transform_direction(&cameratoworld, dy);

	need_update = false;
	need_device_update = true;
	need_flags_update = true;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill the Octane Camera properties from Blender View data
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void BlenderSync::load_camera_from_view(Camera* cam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, float2& offset, bool skip_panorama) {
    float zoom;

    if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
        BL::Object b_ob = (b_v3d.lock_camera_and_layers()) ? b_scene.camera() : b_v3d.camera();

        if(b_ob) {
            cam->matrix = scene->matrix * get_transform(b_ob.matrix_world());

            // Magic zoom formula
            zoom = (float) b_rv3d.view_camera_zoom();
            zoom = (1.41421f + zoom/50.0f);
            zoom *= zoom;
            zoom = 2.0f/zoom;
            zoom *= 2.0f;

            cam->zoom = zoom;

            offset = get_float2(b_rv3d.view_camera_offset());

            load_camera_from_object(cam, b_ob, width, height, offset, skip_panorama);
        }
    } //if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA)
    else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO || b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_PERSP) {
        cam->zoom = 2.0f;

        cam->near_clip_depth    = b_v3d.clip_start();
        cam->far_clip_depth     = b_v3d.clip_end();

        cam->matrix = scene->matrix * transform_inverse(get_transform(b_rv3d.view_matrix()));

        cam->type = CAMERA_PERSPECTIVE;
        if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO)
            cam->ortho = true;
        else
            cam->ortho = false;

        PointerRNA oct_camera = RNA_pointer_get(&b_scene.ptr, "oct_view_cam");
        get_cam_settings(cam, oct_camera, true);

        cam->lens_shift_x   = 0;
        cam->lens_shift_y   = 0;

        cam->sensorwidth    = 32.0f;
        cam->sensorheight   = 18.0f;
        cam->sensor_fit     = Camera::AUTO;

        if(cam->ortho) {
            float ortho_scale;
            get_viewport_ortho_scale(cam, b_rv3d.view_distance(), b_v3d.lens(), width, height, &ortho_scale);
            cam->fov = ortho_scale * cam->zoom;
        }
        else {
            float sensor_size;
            get_camera_sensor_size(cam, width, height, &sensor_size);
            cam->fov = 2.0f * atanf((0.5f * sensor_size * cam->zoom) / b_v3d.lens()) *180.0f / M_PI_F;
        }

        // Position
        cam->look_at.x = cam->eye_point.x = cam->matrix.x.w;
        cam->look_at.y = cam->eye_point.y = cam->matrix.y.w;
        cam->look_at.z = cam->eye_point.z = cam->matrix.z.w;

        if(cam->ortho) {
            float3 dir = transform_direction(&cam->matrix, make_float3(0.0f, 0.0f, b_rv3d.view_distance()));
            cam->eye_point.x = cam->eye_point.x + dir.x;
            cam->eye_point.y = cam->eye_point.y + dir.y;
            cam->eye_point.z = cam->eye_point.z + dir.z;
        }
        else {
            float3 dir = transform_direction(&cam->matrix, make_float3(0.0f, 0.0f, -1.0f));
            cam->look_at.x = cam->look_at.x + dir.x;
            cam->look_at.y = cam->look_at.y + dir.y;
            cam->look_at.z = cam->look_at.z + dir.z;
        }
        cam->up = normalize(transform_direction(&cam->matrix, make_float3(0.0f, 1.0f, 0.0f)));

    } //else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO || b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_PERSP)

    get_camera_border(cam, b_v3d, b_rv3d, width, height);
} //load_camera_from_view()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Fill the Octane Camera properties from Blender data
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void BlenderSync::load_camera_from_object(Camera* cam, BL::Object b_ob, int width, int height, float2& offset, bool skip_panorama) {
    BL::ID b_ob_data    = b_ob.data();

    if(b_ob_data.is_a(&RNA_Camera)) {
        BL::Camera b_camera(b_ob_data);
        PointerRNA oct_camera = RNA_pointer_get(&b_camera.ptr, "octane");

        switch(b_camera.type()) {
            case BL::Camera::type_ORTHO:
                cam->type   = CAMERA_PERSPECTIVE;
                cam->ortho  = true;
                break;
            case BL::Camera::type_PANO:
                if(!skip_panorama)
                    cam->type = CAMERA_PANORAMA;
                else
                    cam->type = CAMERA_PERSPECTIVE;
                cam->ortho = false;
                break;
            case BL::Camera::type_PERSP:
            default:
                cam->type   = CAMERA_PERSPECTIVE;
                cam->ortho  = false;
                break;
        }	
        cam->near_clip_depth = b_camera.clip_start();
        cam->far_clip_depth  = b_camera.clip_end();
        cam->set_focal_depth(b_ob, b_camera);

        get_cam_settings(cam, oct_camera);

        cam->lens_shift_x   = b_camera.shift_x() / cam->zoom;
        cam->lens_shift_y   = b_camera.shift_y() / cam->zoom;

        cam->sensorwidth    = b_camera.sensor_width();
        cam->sensorheight   = b_camera.sensor_height();

        cam->offset_x = offset.x * 2.0f / cam->zoom;
        cam->offset_y = offset.y * 2.0f / cam->zoom;

        if(b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO) cam->sensor_fit = Camera::AUTO;
        else if(b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL) cam->sensor_fit = Camera::HORIZONTAL;
        else cam->sensor_fit = Camera::VERTICAL;

        if(cam->ortho) {
            float ortho_scale;
            get_camera_ortho_scale(cam, b_camera, width, height, &ortho_scale);
            cam->fov = ortho_scale * cam->zoom;
        }
        else {
            float sensor_size;
            get_camera_sensor_size(cam, width, height, &sensor_size);
            cam->fov = 2.0f * atanf((0.5f * sensor_size * cam->zoom) / b_camera.lens()) *180.0f / M_PI_F;
        }	

        // Position
        cam->eye_point.x = cam->matrix.x.w;
        cam->eye_point.y = cam->matrix.y.w;
        cam->eye_point.z = cam->matrix.z.w;

        float3 dir = transform_direction(&cam->matrix, make_float3(0.0f, 0.0f, -1.0f));
        cam->look_at.x = cam->eye_point.x + dir.x;
        cam->look_at.y = cam->eye_point.y + dir.y;
        cam->look_at.z = cam->eye_point.z + dir.z;

        cam->up = normalize(transform_direction(&cam->matrix, make_float3(0.0f, 1.0f, 0.0f)));
    }
    else {
        //TODO: Implement it for Lamp
    }
} //camera_from_object()
Exemple #7
0
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Update all (already compiled) scene meshes on render-server (finally sends one LOAD_MESH packet for global mesh and one for each scattered mesh)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void MeshManager::server_update_mesh(::OctaneEngine::OctaneClient *server, Scene *scene, Progress& progress, uint32_t frame_idx, uint32_t total_frames) {
	if(!need_update) return;
    if(total_frames <= 1)
        need_update = false;
	progress.set_status("Loading Meshes to render-server", "");

    uint64_t ulGlobalCnt    = 0;
    uint64_t ulLocalCnt     = 0;
    uint64_t ulLocalVdbCnt  = 0;
    bool global_update      = false;

    if(need_global_update) {
        global_update       = need_global_update;
        need_global_update  = false;
    }
    vector<Mesh*>::iterator it;
    for(it = scene->meshes.begin(); it != scene->meshes.end(); ++it) {
        Mesh *mesh = *it;
        if(mesh->empty) {
        	if(mesh->need_update) mesh->need_update = false;
            continue;
        }
        else if(scene->meshes_type == Mesh::GLOBAL || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::GLOBAL)) {
            if(mesh->vdb_regular_grid) ++ulLocalVdbCnt;
            else if(total_frames <= 1 && (scene->first_frame || scene->anim_mode == FULL)) {
                ++ulGlobalCnt;
                if(mesh->need_update && !global_update) global_update = true;
            }
            continue;
        }
        if(!mesh->need_update
           || (!scene->first_frame
               && (scene->anim_mode == CAM_ONLY
                   || (scene->anim_mode == MOVABLE_PROXIES
                       && scene->meshes_type != Mesh::RESHAPABLE_PROXY && (scene->meshes_type != Mesh::AS_IS || mesh->mesh_type != Mesh::RESHAPABLE_PROXY)))))
            continue;

        if(mesh->vdb_regular_grid) ++ulLocalVdbCnt;
        else ++ulLocalCnt;

		if(progress.get_cancel()) return;
	}

    bool interrupted = false;

    if(ulLocalCnt) {
        char            **mesh_names                    = new char*[ulLocalCnt];
        uint64_t        *used_shaders_size              = new uint64_t[ulLocalCnt];
        uint64_t        *used_objects_size              = new uint64_t[ulLocalCnt];
        vector<string>  *shader_names                   = new vector<string>[ulLocalCnt];
        vector<string>  *object_names                   = new vector<string>[ulLocalCnt];
        float3          **points                        = new float3*[ulLocalCnt];
        uint64_t        *points_size                    = new uint64_t[ulLocalCnt];
        float3          **normals                       = new float3*[ulLocalCnt];
        uint64_t        *normals_size                   = new uint64_t[ulLocalCnt];
        int             **points_indices                = new int*[ulLocalCnt];
        int             **normals_indices               = new int*[ulLocalCnt];
        uint64_t        *points_indices_size            = new uint64_t[ulLocalCnt];
        uint64_t        *normals_indices_size           = new uint64_t[ulLocalCnt];
        int             **vert_per_poly                 = new int*[ulLocalCnt];
        uint64_t        *vert_per_poly_size             = new uint64_t[ulLocalCnt];
        int             **poly_mat_index                = new int*[ulLocalCnt];
        int             **poly_obj_index                = new int*[ulLocalCnt];
        float3          **uvs                           = new float3*[ulLocalCnt];
        uint64_t        *uvs_size                       = new uint64_t[ulLocalCnt];
        int             **uv_indices                    = new int*[ulLocalCnt];
        uint64_t        *uv_indices_size                = new uint64_t[ulLocalCnt];
        bool            *open_subd_enable               = new bool[ulLocalCnt];
        int32_t         *open_subd_scheme               = new int32_t[ulLocalCnt];
        int32_t         *open_subd_level                = new int32_t[ulLocalCnt];
        float           *open_subd_sharpness            = new float[ulLocalCnt];
        int32_t         *open_subd_bound_interp         = new int32_t[ulLocalCnt];
        uint64_t        *open_subd_crease_indices_cnt   = new uint64_t[ulLocalCnt];
        int             **open_subd_crease_indices      = new int*[ulLocalCnt];
        float           **open_subd_crease_sharpnesses  = new float*[ulLocalCnt];
        float           *general_vis                    = new float[ulLocalCnt];
        bool            *cam_vis                        = new bool[ulLocalCnt];
        bool            *shadow_vis                     = new bool[ulLocalCnt];
        int32_t         *rand_color_seed                = new int32_t[ulLocalCnt];
        bool            *reshapable                     = new bool[ulLocalCnt];
        int32_t         *layer_number                   = new int32_t[ulLocalCnt];
        int32_t         *baking_group_id                = new int32_t[ulLocalCnt];
        float           *max_smooth_angle               = new float[ulLocalCnt];

        float3          **hair_points                   = new float3*[ulLocalCnt];
        uint64_t        *hair_points_size               = new uint64_t[ulLocalCnt];
        uint64_t        *hair_ws_size                   = new uint64_t[ulLocalCnt];
        int32_t         **vert_per_hair                 = new int32_t*[ulLocalCnt];
        uint64_t        *vert_per_hair_size             = new uint64_t[ulLocalCnt];
        float           **hair_thickness                = new float*[ulLocalCnt];
        int32_t         **hair_mat_indices              = new int32_t*[ulLocalCnt];
        float2          **hair_uvs                      = new float2*[ulLocalCnt];
        float2          **hair_ws                       = new float2*[ulLocalCnt];
        int32_t         *hair_interpolation             = new int32_t[ulLocalCnt];

        uint64_t i = 0;
        vector<Mesh*>::iterator it;
        for(it = scene->meshes.begin(); it != scene->meshes.end(); ++it) {
            Mesh *mesh = *it;
            if(mesh->vdb_regular_grid) continue;
            if(mesh->empty || !mesh->need_update
               || (scene->meshes_type == Mesh::GLOBAL || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::GLOBAL))
               || (!scene->first_frame
                   && (scene->anim_mode == CAM_ONLY
                       || (scene->anim_mode == MOVABLE_PROXIES
                           && scene->meshes_type != Mesh::RESHAPABLE_PROXY && (scene->meshes_type != Mesh::AS_IS || mesh->mesh_type != Mesh::RESHAPABLE_PROXY))))) continue;

            if(scene->meshes_type == Mesh::SCATTER || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::SCATTER))
                progress.set_status("Loading Meshes to render-server", string("Scatter: ") + mesh->nice_name.c_str());
            else if(scene->meshes_type == Mesh::MOVABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::MOVABLE_PROXY))
                progress.set_status("Loading Meshes to render-server", string("Movable: ") + mesh->nice_name.c_str());
            else if(scene->meshes_type == Mesh::RESHAPABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::RESHAPABLE_PROXY))
                progress.set_status("Loading Meshes to render-server", string("Reshapable: ") + mesh->nice_name.c_str());

            used_shaders_size[i] = mesh->used_shaders.size();
            for(size_t n=0; n<used_shaders_size[i]; ++n) {
                shader_names[i].push_back(scene->shaders[mesh->used_shaders[n]]->name);
            }

            used_objects_size[i] = 1;
            object_names[i].push_back("__" + mesh->name);

            mesh_names[i]                   = (char*)mesh->name.c_str();
            points[i]                       = &mesh->points[0];
            points_size[i]                  = mesh->points.size();
            normals[i]                      = &mesh->normals[0];
            normals_size[i]                 = mesh->normals.size();
            points_indices[i]               = &mesh->points_indices[0];
            normals_indices[i]              = &mesh->points_indices[0];
            points_indices_size[i]          = mesh->points_indices.size();
            normals_indices_size[i]         = 0;//mesh->points_indices.size();
            vert_per_poly[i]                = &mesh->vert_per_poly[0];
            vert_per_poly_size[i]           = mesh->vert_per_poly.size();
            poly_mat_index[i]               = &mesh->poly_mat_index[0];
            poly_obj_index[i]               = &mesh->poly_obj_index[0];
            uvs[i]                          = &mesh->uvs[0];
            uvs_size[i]                     = mesh->uvs.size();
            uv_indices[i]                   = &mesh->uv_indices[0];
            uv_indices_size[i]              = mesh->uv_indices.size();
            open_subd_enable[i]             = mesh->open_subd_enable;
            open_subd_scheme[i]             = mesh->open_subd_scheme;
            open_subd_level[i]              = mesh->open_subd_level;
            open_subd_sharpness[i]          = mesh->open_subd_sharpness;
            open_subd_bound_interp[i]       = mesh->open_subd_bound_interp;
            open_subd_crease_indices_cnt[i] = mesh->open_subd_crease_indices.size() / 2;
            if(open_subd_crease_indices_cnt[i]) {
                open_subd_crease_indices[i]     = &mesh->open_subd_crease_indices[0];
                open_subd_crease_sharpnesses[i] = &mesh->open_subd_crease_sharpnesses[0];
            }
            else {
                open_subd_crease_indices[i]     = nullptr;
                open_subd_crease_sharpnesses[i] = nullptr;
            }
            general_vis[i]                  = mesh->vis_general;
            cam_vis[i]                      = mesh->vis_cam;
            shadow_vis[i]                   = mesh->vis_shadow;
            rand_color_seed[i]              = mesh->rand_color_seed;
            reshapable[i]                   = (scene->meshes_type == Mesh::RESHAPABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::RESHAPABLE_PROXY));
            layer_number[i]                 = (scene->kernel->oct_node->bLayersEnable ? mesh->layer_number : 1);
            baking_group_id[i]              = mesh->baking_group_id;
            max_smooth_angle[i]             = mesh->max_smooth_angle;

            hair_points_size[i]             = mesh->hair_points.size();
            hair_ws_size[i]                 = mesh->hair_interpolation == (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_NONE ? mesh->hair_ws.size() : 0;
            hair_points[i]                  = hair_points_size[i] ? &mesh->hair_points[0] : 0;
            vert_per_hair_size[i]           = mesh->vert_per_hair.size();
            vert_per_hair[i]                = vert_per_hair_size[i] ? &mesh->vert_per_hair[0] : 0;
            hair_thickness[i]               = hair_points_size[i] ? &mesh->hair_thickness[0] : 0;
            hair_mat_indices[i]             = vert_per_hair_size[i] ? &mesh->hair_mat_indices[0] : 0;
            hair_uvs[i]                     = vert_per_hair_size[i] ? &mesh->hair_uvs[0] : 0;
            hair_ws[i]                      = hair_ws_size[i] ? &mesh->hair_ws[0] : 0;
            hair_interpolation[i]           = mesh->hair_interpolation == (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_NONE ? (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_DEFAULT : mesh->hair_interpolation;

            if(mesh->need_update
               && (total_frames <= 1 || !reshapable[i]))
                mesh->need_update = false;
    		if(progress.get_cancel()) {
                interrupted = true;
                break;
            }
            ++i;
	    }
        if(i && !interrupted) {
            progress.set_status("Loading Meshes to render-server", "Transferring...");
            server->uploadMesh(false, frame_idx, total_frames, ulLocalCnt, mesh_names,
                                        used_shaders_size,
                                        used_objects_size,
                                        shader_names,
                                        object_names,
                                        (::OctaneEngine::float_3**)points,
                                        points_size,
                                        (::OctaneEngine::float_3**)normals,
                                        normals_size,
                                        points_indices,
                                        normals_indices,
                                        points_indices_size,
                                        normals_indices_size,
                                        vert_per_poly,
                                        vert_per_poly_size,
                                        poly_mat_index,
                                        poly_obj_index,
                                        (::OctaneEngine::float_3**)uvs,
                                        uvs_size,
                                        uv_indices,
                                        uv_indices_size,
                                        (::OctaneEngine::float_3**)hair_points, hair_points_size, hair_ws_size,
                                        vert_per_hair, vert_per_hair_size,
                                        hair_thickness, hair_mat_indices, (::OctaneEngine::float_2**)hair_uvs, (::OctaneEngine::float_2**)hair_ws, hair_interpolation,
                                        open_subd_enable,
                                        open_subd_scheme,
                                        open_subd_level,
                                        open_subd_sharpness,
                                        open_subd_bound_interp,
                                        open_subd_crease_indices_cnt,
                                        open_subd_crease_indices,
                                        open_subd_crease_sharpnesses,
                                        layer_number,
                                        baking_group_id,
                                        general_vis,
                                        cam_vis,
                                        shadow_vis,
                                        rand_color_seed,
                                        reshapable,
                                        max_smooth_angle);
        }
        delete[] mesh_names;
        delete[] used_shaders_size;
        delete[] used_objects_size;
        delete[] shader_names;
        delete[] object_names;
        delete[] points;
        delete[] points_size;
        delete[] normals;
        delete[] normals_size;
        delete[] points_indices;
        delete[] normals_indices;
        delete[] points_indices_size;
        delete[] normals_indices_size;
        delete[] vert_per_poly;
        delete[] vert_per_poly_size;
        delete[] poly_mat_index;
        delete[] poly_obj_index;
        delete[] uvs;
        delete[] uvs_size;
        delete[] uv_indices;
        delete[] uv_indices_size;
        delete[] open_subd_enable;
        delete[] open_subd_scheme;
        delete[] open_subd_level;
        delete[] open_subd_sharpness;
        delete[] open_subd_bound_interp;
        delete[] open_subd_crease_indices_cnt;
        delete[] open_subd_crease_indices;
        delete[] open_subd_crease_sharpnesses;
        delete[] general_vis;
        delete[] cam_vis;
        delete[] shadow_vis;
        delete[] rand_color_seed;
        delete[] reshapable;
        delete[] layer_number;
        delete[] baking_group_id;
        delete[] max_smooth_angle;
        delete[] hair_interpolation;

        delete[] hair_points_size;
        delete[] hair_ws_size;
        delete[] vert_per_hair_size;
        delete[] hair_points;
        delete[] vert_per_hair;
        delete[] hair_thickness;
        delete[] hair_mat_indices;
        delete[] hair_uvs;
        delete[] hair_ws;
    }

    if(ulLocalVdbCnt && !interrupted) {
        uint64_t i = 0;
        vector<Mesh*>::iterator it;
        for(it = scene->meshes.begin(); it != scene->meshes.end(); ++it) {
            Mesh *mesh = *it;
            if(!mesh->vdb_regular_grid) continue;
            if(mesh->empty || !mesh->need_update
               //|| (scene->meshes_type == Mesh::GLOBAL || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::GLOBAL))
               || (!scene->first_frame
                   && (scene->anim_mode == CAM_ONLY
                       || (scene->anim_mode == MOVABLE_PROXIES
                           && scene->meshes_type != Mesh::RESHAPABLE_PROXY && (scene->meshes_type != Mesh::AS_IS || mesh->mesh_type != Mesh::RESHAPABLE_PROXY))))) continue;

            if(scene->meshes_type == Mesh::SCATTER || scene->meshes_type == Mesh::GLOBAL || scene->meshes_type == Mesh::GLOBAL || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::SCATTER))
                progress.set_status("Loading Volumes to render-server", string("Scatter: ") + mesh->nice_name.c_str());
            else if(scene->meshes_type == Mesh::MOVABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::MOVABLE_PROXY))
                progress.set_status("Loading Volumes to render-server", string("Movable: ") + mesh->nice_name.c_str());
            else if(scene->meshes_type == Mesh::RESHAPABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::RESHAPABLE_PROXY))
                progress.set_status("Loading Volumes to render-server", string("Reshapable: ") + mesh->nice_name.c_str());

            ::OctaneEngine::OctaneVolume volume;

            volume.sName                = mesh->name;
            volume.pfRegularGrid        = mesh->vdb_regular_grid;
            volume.iGridSize            = mesh->vdb_grid_size;
            volume.f3Resolution         = {mesh->vdb_resolution.x, mesh->vdb_resolution.y, mesh->vdb_resolution.z};
            volume.gridMatrix           = mesh->vdb_grid_matrix;
            volume.fISO                 = mesh->vdb_iso;
            volume.iAbsorptionOffset    = mesh->vdb_absorption_offset;
            volume.fAbsorptionScale     = mesh->vdb_absorption_scale;
            volume.iEmissionOffset      = mesh->vdb_emission_offset;
            volume.fEmissionScale       = mesh->vdb_emission_scale;
            volume.iScatterOffset       = mesh->vdb_scatter_offset;
            volume.fScatterScale        = mesh->vdb_scatter_scale;
            volume.iVelocityOffsetX     = mesh->vdb_velocity_x_offset;
            volume.iVelocityOffsetY     = mesh->vdb_velocity_y_offset;
            volume.iVelocityOffsetZ     = mesh->vdb_velocity_z_offset;
            volume.fVelocityScale       = mesh->vdb_velocity_scale;

            volume.fGenVisibility       = mesh->vis_general;
            volume.bCamVisibility       = mesh->vis_cam;
            volume.bShadowVisibility    = mesh->vis_shadow;
            volume.iRandomColorSeed     = mesh->rand_color_seed;
            volume.iLayerNumber         = (scene->kernel->oct_node->bLayersEnable ? mesh->layer_number : 1);
            volume.iBakingGroupId       = mesh->baking_group_id;

            if(mesh->used_shaders.size())
                volume.sMedium = scene->shaders[mesh->used_shaders[0]]->name;

            if(mesh->need_update && (total_frames <= 1 || !(scene->meshes_type == Mesh::RESHAPABLE_PROXY || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type == Mesh::RESHAPABLE_PROXY))))
                mesh->need_update = false;
    		if(progress.get_cancel()) {
                interrupted = true;
                break;
            }
            ++i;

            progress.set_status("Loading Volumes to render-server", "Transferring...");
            server->uploadVolume(&volume);
        }
    }

    if(global_update && !interrupted) {
        progress.set_status("Loading global Mesh to render-server", "");
        uint64_t obj_cnt = 0;
        for(map<std::string, vector<Object*> >::const_iterator obj_it = scene->objects.begin(); obj_it != scene->objects.end(); ++obj_it) {
            Mesh* mesh = obj_it->second.size() > 0 ? obj_it->second[0]->mesh : 0;
            if(mesh->vdb_regular_grid) continue;

            if(!mesh || mesh->empty
               || (!scene->first_frame && scene->anim_mode != FULL)
               || (scene->meshes_type == Mesh::SCATTER || scene->meshes_type == Mesh::MOVABLE_PROXY || scene->meshes_type == Mesh::RESHAPABLE_PROXY)
               || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type != Mesh::GLOBAL)) continue;

            for(vector<Object*>::const_iterator it = obj_it->second.begin(); it != obj_it->second.end(); ++it) {
    		    Object *mesh_object = *it;
                if(!mesh_object->visibility) continue;
                ++obj_cnt;
            }
        }
        char* name = "__global";
        if(obj_cnt > 0) {
            uint64_t        *used_shaders_size              = new uint64_t[obj_cnt];
            uint64_t        *used_objects_size              = new uint64_t[obj_cnt];
            vector<string>  *shader_names                   = new vector<string>[obj_cnt];
            vector<string>  *object_names                   = new vector<string>[obj_cnt];
            float3          **points                        = new float3*[obj_cnt];
            for(int k = 0; k < obj_cnt; ++k) points[k] = 0;
            uint64_t        *points_size                    = new uint64_t[obj_cnt];
            float3          **normals                       = new float3*[obj_cnt];
            for(int k = 0; k < obj_cnt; ++k) normals[k] = 0;
            uint64_t        *normals_size                   = new uint64_t[obj_cnt];
            int             **points_indices                = new int*[obj_cnt];
            int             **normals_indices               = new int*[obj_cnt];
            uint64_t        *points_indices_size            = new uint64_t[obj_cnt];
            uint64_t        *normals_indices_size           = new uint64_t[obj_cnt];
            int             **vert_per_poly                 = new int*[obj_cnt];
            uint64_t        *vert_per_poly_size             = new uint64_t[obj_cnt];
            int             **poly_mat_index                = new int*[obj_cnt];
            int             **poly_obj_index                = new int*[obj_cnt];
            float3          **uvs                           = new float3*[obj_cnt];
            uint64_t        *uvs_size                       = new uint64_t[obj_cnt];
            int             **uv_indices                    = new int*[obj_cnt];
            uint64_t        *uv_indices_size                = new uint64_t[obj_cnt];
            bool            *open_subd_enable               = new bool[obj_cnt];
            int32_t         *open_subd_scheme               = new int32_t[obj_cnt];
            int32_t         *open_subd_level                = new int32_t[obj_cnt];
            float           *open_subd_sharpness            = new float[obj_cnt];
            int32_t         *open_subd_bound_interp         = new int32_t[obj_cnt];
            uint64_t        *open_subd_crease_indices_cnt   = new uint64_t[obj_cnt];
            int             **open_subd_crease_indices      = new int*[obj_cnt];
            float           **open_subd_crease_sharpnesses  = new float*[obj_cnt];
            float           *general_vis                    = new float[obj_cnt];
            bool            *cam_vis                        = new bool[obj_cnt];
            bool            *shadow_vis                     = new bool[obj_cnt];
            int32_t         *rand_color_seed                = new int32_t[obj_cnt];
            bool            *reshapable                     = new bool[obj_cnt];
            int32_t         *layer_number                   = new int32_t[obj_cnt];
            int32_t         *baking_group_id                = new int32_t[obj_cnt];
            float           *max_smooth_angle               = new float[obj_cnt];

            float3          **hair_points                   = new float3*[obj_cnt];
            uint64_t        *hair_points_size               = new uint64_t[obj_cnt];
            uint64_t        *hair_ws_size                   = new uint64_t[obj_cnt];
            int32_t         **vert_per_hair                 = new int32_t*[obj_cnt];
            uint64_t        *vert_per_hair_size             = new uint64_t[obj_cnt];
            float           **hair_thickness                = new float*[obj_cnt];
            int32_t         **hair_mat_indices              = new int32_t*[obj_cnt];
            float2          **hair_uvs                      = new float2*[obj_cnt];
            int32_t         *hair_interpolation             = new int32_t[obj_cnt];
            float2          **hair_ws                       = new float2*[obj_cnt];

            obj_cnt = 0;
            bool hair_present = false;
            for(map<std::string, vector<Object*> >::const_iterator obj_it = scene->objects.begin(); obj_it != scene->objects.end(); ++obj_it) {
                Mesh* mesh = obj_it->second.size() > 0 ? obj_it->second[0]->mesh : 0;
                if(mesh->vdb_regular_grid) continue;

                if(!mesh || mesh->empty
                   || (!scene->first_frame && scene->anim_mode != FULL)
                   || (scene->meshes_type == Mesh::SCATTER || scene->meshes_type == Mesh::MOVABLE_PROXY || scene->meshes_type == Mesh::RESHAPABLE_PROXY)
                   || (scene->meshes_type == Mesh::AS_IS && mesh->mesh_type != oct::Mesh::GLOBAL)) continue;

                for(vector<Object*>::const_iterator it = obj_it->second.begin(); it != obj_it->second.end(); ++it) {
    		        Object *mesh_object = *it;
                    if(!mesh_object->visibility) continue;

                    Transform &tfm = mesh_object->tfm;

                    used_shaders_size[obj_cnt] = mesh_object->used_shaders.size();
                    for(size_t n=0; n<used_shaders_size[obj_cnt]; ++n) {
                        shader_names[obj_cnt].push_back(scene->shaders[mesh_object->used_shaders[n]]->name);
                    }

                    used_objects_size[obj_cnt] = 1;
                    object_names[obj_cnt].push_back("__" + mesh->name);

                    size_t points_cnt             = mesh->points.size();
                    points[obj_cnt]               = new float3[points_cnt];
                    float3 *p                     = &mesh->points[0];
                    for(size_t k=0; k<points_cnt; ++k) points[obj_cnt][k] = transform_point(&tfm, p[k]);
                    points_size[obj_cnt]          = points_cnt;

                    size_t norm_cnt               = mesh->normals.size();
                    normals[obj_cnt]              = new float3[norm_cnt];
                    float3 *n                     = &mesh->normals[0];
                    for(size_t k=0; k<norm_cnt; ++k) normals[obj_cnt][k] = transform_direction(&tfm, n[k]);
                    normals_size[obj_cnt]         = norm_cnt;

                    points_indices[obj_cnt]                 = &mesh->points_indices[0];
                    normals_indices[obj_cnt]                = &mesh->points_indices[0];
                    points_indices_size[obj_cnt]            = mesh->points_indices.size();
                    normals_indices_size[obj_cnt]           = 0;
                    vert_per_poly[obj_cnt]                  = &mesh->vert_per_poly[0];
                    vert_per_poly_size[obj_cnt]             = mesh->vert_per_poly.size();
                    poly_mat_index[obj_cnt]                 = &mesh->poly_mat_index[0];
                    poly_obj_index[obj_cnt]                 = &mesh->poly_obj_index[0];
                    uvs[obj_cnt]                            = &mesh->uvs[0];
                    uvs_size[obj_cnt]                       = mesh->uvs.size();
                    uv_indices[obj_cnt]                     = &mesh->uv_indices[0];
                    uv_indices_size[obj_cnt]                = mesh->uv_indices.size();
                    open_subd_enable[obj_cnt]               = mesh->open_subd_enable;
                    open_subd_scheme[obj_cnt]               = mesh->open_subd_scheme;
                    open_subd_level[obj_cnt]                = mesh->open_subd_level;
                    open_subd_sharpness[obj_cnt]            = mesh->open_subd_sharpness;
                    open_subd_bound_interp[obj_cnt]         = mesh->open_subd_bound_interp;
                    open_subd_crease_indices_cnt[obj_cnt]   = mesh->open_subd_crease_indices.size() / 2;
                    if(open_subd_crease_indices_cnt[obj_cnt]) {
                        open_subd_crease_indices[obj_cnt]       = &mesh->open_subd_crease_indices[0];
                        open_subd_crease_sharpnesses[obj_cnt]   = &mesh->open_subd_crease_sharpnesses[0];
                    }
                    else {
                        open_subd_crease_indices[obj_cnt]     = nullptr;
                        open_subd_crease_sharpnesses[obj_cnt] = nullptr;
                    }
                    general_vis[obj_cnt]                    = mesh->vis_general;
                    cam_vis[obj_cnt]                        = mesh->vis_cam;
                    shadow_vis[obj_cnt]                     = mesh->vis_shadow;
                    rand_color_seed[obj_cnt]                = mesh->rand_color_seed;
                    reshapable[obj_cnt]                     = false;
                    layer_number[obj_cnt]                   = (scene->kernel->oct_node->bLayersEnable ? mesh->layer_number : 1);
                    baking_group_id[obj_cnt]                = mesh->baking_group_id;
                    max_smooth_angle[obj_cnt]               = mesh->max_smooth_angle;

                    hair_points_size[obj_cnt]               = mesh->hair_points.size();
                    hair_ws_size[obj_cnt]                   = mesh->hair_interpolation == (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_NONE ? mesh->hair_ws.size() : 0;
                    hair_points[obj_cnt]                    = hair_points_size[obj_cnt] ? &mesh->hair_points[0] : 0;
                    vert_per_hair_size[obj_cnt]             = mesh->vert_per_hair.size();
                    vert_per_hair[obj_cnt]                  = vert_per_hair_size[obj_cnt] ? &mesh->vert_per_hair[0] : 0;
                    hair_thickness[obj_cnt]                 = hair_points_size[obj_cnt] ? &mesh->hair_thickness[0] : 0;
                    hair_mat_indices[obj_cnt]               = vert_per_hair_size[obj_cnt] ? &mesh->hair_mat_indices[0] : 0;
                    hair_uvs[obj_cnt]                       = vert_per_hair_size[obj_cnt] ? &mesh->hair_uvs[0] : 0;
                    hair_interpolation[obj_cnt]             = mesh->hair_interpolation == (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_NONE ? (int32_t)::Octane::HairInterpolationType::HAIR_INTERP_DEFAULT : mesh->hair_interpolation;
                    hair_ws[obj_cnt]                        = hair_ws_size[obj_cnt] ? &mesh->hair_ws[0] : 0;

        	        if(mesh->need_update) mesh->need_update = false;
    		        if(progress.get_cancel()) {
                        interrupted = true;
                        break;
                    }
                    ++obj_cnt;

                    if(!hair_present && mesh->hair_points.size()) hair_present = true;
                }
            }
            if(obj_cnt && !interrupted) {
                if(hair_present) fprintf(stderr, "Octane: WARNING: hair can't be rendered on \"Global\" mesh\n");
            
                progress.set_status("Loading global Mesh to render-server", string("Transferring..."));
                server->uploadMesh(true, frame_idx, total_frames, obj_cnt, &name,
                                            used_shaders_size,
                                            used_objects_size,
                                            shader_names,
                                            object_names,
                                            (::OctaneEngine::float_3**)points,
                                            points_size,
                                            (::OctaneEngine::float_3**)normals,
                                            normals_size,
                                            points_indices,
                                            normals_indices,
                                            points_indices_size,
                                            normals_indices_size,
                                            vert_per_poly,
                                            vert_per_poly_size,
                                            poly_mat_index,
                                            poly_obj_index,
                                            (::OctaneEngine::float_3**)uvs,
                                            uvs_size,
                                            uv_indices,
                                            uv_indices_size,
                                            (::OctaneEngine::float_3**)hair_points, hair_points_size, hair_ws_size,
                                            vert_per_hair, vert_per_hair_size,
                                            hair_thickness, hair_mat_indices, (::OctaneEngine::float_2**)hair_uvs, (::OctaneEngine::float_2**)hair_ws, hair_interpolation,
                                            open_subd_enable,
                                            open_subd_scheme,
                                            open_subd_level,
                                            open_subd_sharpness,
                                            open_subd_bound_interp,
                                            open_subd_crease_indices_cnt,
                                            open_subd_crease_indices,
                                            open_subd_crease_sharpnesses,
                                            layer_number,
                                            baking_group_id,
                                            general_vis,
                                            cam_vis,
                                            shadow_vis,
                                            rand_color_seed,
                                            reshapable,
                                            max_smooth_angle);
                server->uploadLayerMap(true, "__global_lm", name, static_cast< ::OctaneEngine::int32_t>(obj_cnt), layer_number, baking_group_id, general_vis, cam_vis, shadow_vis, static_cast< ::OctaneEngine::int32_t*>(rand_color_seed));
            }
            delete[] used_shaders_size;
            delete[] used_objects_size;
            delete[] shader_names;
            delete[] object_names;
            for(int k = 0; k < obj_cnt; ++k) {
                if(points[k]) delete[] points[k];
            }
            delete[] points;
            delete[] points_size;
            for(int k = 0; k < obj_cnt; ++k) {
                if(normals[k]) delete[] normals[k];
            }
            delete[] normals;
            delete[] normals_size;
            delete[] points_indices;
            delete[] normals_indices;
            delete[] points_indices_size;
            delete[] normals_indices_size;
            delete[] vert_per_poly;
            delete[] vert_per_poly_size;
            delete[] poly_mat_index;
            delete[] poly_obj_index;
            delete[] uvs;
            delete[] uvs_size;
            delete[] uv_indices;
            delete[] uv_indices_size;
            delete[] open_subd_enable;
            delete[] open_subd_scheme;
            delete[] open_subd_level;
            delete[] open_subd_sharpness;
            delete[] open_subd_bound_interp;
            delete[] open_subd_crease_indices_cnt;
            delete[] open_subd_crease_indices;
            delete[] open_subd_crease_sharpnesses;
            delete[] general_vis;
            delete[] cam_vis;
            delete[] shadow_vis;
            delete[] rand_color_seed;
            delete[] reshapable;
            delete[] layer_number;
            delete[] baking_group_id;
            delete[] max_smooth_angle;

            delete[] hair_points_size;
            delete[] hair_ws_size;
            delete[] vert_per_hair_size;
            delete[] hair_points;
            delete[] vert_per_hair;
            delete[] hair_thickness;
            delete[] hair_mat_indices;
            delete[] hair_uvs;
            delete[] hair_ws;
            delete[] hair_interpolation;
        }
        else ulGlobalCnt = 0;
    }
    std::string cur_name("__global");
    if(!ulGlobalCnt && scene->anim_mode == FULL) server->deleteMesh(true, cur_name);
	//need_update = false;
} //server_update_mesh()