예제 #1
0
void BlenderSync::sync_world(bool update_all)
{
	Background *background = scene->background;
	Background prevbackground = *background;

	BL::World b_world = b_scene.world();

	if(world_recalc || update_all || b_world.ptr.data != world_map) {
		Shader *shader = scene->shaders[scene->default_background];
		ShaderGraph *graph = new ShaderGraph();

		/* create nodes */
		if(b_world && b_world.use_nodes() && b_world.node_tree()) {
			PtrSockMap sock_to_node;
			BL::ShaderNodeTree b_ntree(b_world.node_tree());

			add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
		}
		else if(b_world) {
			ShaderNode *closure, *out;

			closure = graph->add(new BackgroundNode());
			closure->input("Color")->value = get_float3(b_world.horizon_color());
			out = graph->output();

			graph->connect(closure->output("Background"), out->input("Surface"));
		}

		/* AO */
		if(b_world) {
			BL::WorldLighting b_light = b_world.light_settings();

			if(b_light.use_ambient_occlusion())
				background->ao_factor = b_light.ao_factor();
			else
				background->ao_factor = 0.0f;

			background->ao_distance = b_light.distance();
		}

		shader->set_graph(graph);
		shader->tag_update(scene);
	}

	PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
	background->transparent = get_boolean(cscene, "film_transparent");
	background->use = render_layer.use_background;

	if(background->modified(prevbackground))
		background->tag_update(scene);
}
예제 #2
0
static void mikk_get_texture_coordinate(const SMikkTSpaceContext *context, float uv[2], const int face_num, const int vert_num)
{
	MikkUserData *userdata = (MikkUserData*)context->m_pUserData;
	BL::MeshTextureFace tf = userdata->layer.data[face_num];
	float3 tfuv;
	
	switch (vert_num) {
		case 0:
			tfuv = get_float3(tf.uv1());
			break;
		case 1:
			tfuv = get_float3(tf.uv2());
			break;
		case 2:
			tfuv = get_float3(tf.uv3());
			break;
		default:
			tfuv = get_float3(tf.uv4());
			break;
	}
	
	uv[0] = tfuv.x;
	uv[1] = tfuv.y;
}
예제 #3
0
void BlenderSync::sync_lamps(bool update_all)
{
	shader_map.set_default(scene->shaders[scene->default_light]);

	/* lamp loop */
	BL::BlendData::lamps_iterator b_lamp;

	for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
		Shader *shader;
		
		/* test if we need to sync */
		if(shader_map.sync(&shader, *b_lamp) || update_all) {
			ShaderGraph *graph = new ShaderGraph();

			/* create nodes */
			if(b_lamp->use_nodes() && b_lamp->node_tree()) {
				shader->name = b_lamp->name().c_str();

				PtrSockMap sock_to_node;
				BL::ShaderNodeTree b_ntree(b_lamp->node_tree());

				add_nodes(scene, b_data, b_scene, graph, b_ntree, sock_to_node);
			}
			else {
				ShaderNode *closure, *out;
				float strength = 1.0f;

				if(b_lamp->type() == BL::Lamp::type_POINT ||
				   b_lamp->type() == BL::Lamp::type_SPOT ||
				   b_lamp->type() == BL::Lamp::type_AREA)
				{
					strength = 100.0f;
				}

				closure = graph->add(new EmissionNode());
				closure->input("Color")->value = get_float3(b_lamp->color());
				closure->input("Strength")->value.x = strength;
				out = graph->output();

				graph->connect(closure->output("Emission"), out->input("Surface"));
			}

			shader->set_graph(graph);
			shader->tag_update(scene);
		}
	}
}
void BlenderSync::sync_lamps(bool update_all)
{
	shader_map.set_default(scene->default_light);

	/* lamp loop */
	BL::BlendData::lamps_iterator b_lamp;

	for(b_data.lamps.begin(b_lamp); b_lamp != b_data.lamps.end(); ++b_lamp) {
		Shader *shader;

		/* test if we need to sync */
		if(shader_map.sync(&shader, *b_lamp) || update_all) {
			ShaderGraph *graph = new ShaderGraph();

			/* create nodes */
			if(b_lamp->use_nodes() && b_lamp->node_tree()) {
				shader->name = b_lamp->name().c_str();

				BL::ShaderNodeTree b_ntree(b_lamp->node_tree());

				add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
			}
			else {
				float strength = 1.0f;

				if(b_lamp->type() == BL::Lamp::type_POINT ||
				   b_lamp->type() == BL::Lamp::type_SPOT ||
				   b_lamp->type() == BL::Lamp::type_AREA)
				{
					strength = 100.0f;
				}

				EmissionNode *emission = new EmissionNode();
				emission->color = get_float3(b_lamp->color());
				emission->strength = strength;
				graph->add(emission);

				ShaderNode *out = graph->output();
				graph->connect(emission->output("Emission"), out->input("Surface"));
			}

			shader->set_graph(graph);
			shader->tag_update(scene);
		}
	}
}
예제 #5
0
void BlenderSync::sync_materials(bool update_all)
{
	shader_map.set_default(scene->shaders[scene->default_surface]);

	/* material loop */
	BL::BlendData::materials_iterator b_mat;

	for(b_data.materials.begin(b_mat); b_mat != b_data.materials.end(); ++b_mat) {
		Shader *shader;

		/* test if we need to sync */
		if(shader_map.sync(&shader, *b_mat) || update_all) {
			ShaderGraph *graph = new ShaderGraph();

			shader->name = b_mat->name().c_str();
			shader->pass_id = b_mat->pass_index();

			/* create nodes */
			if(b_mat->use_nodes() && b_mat->node_tree()) {
				BL::ShaderNodeTree b_ntree(b_mat->node_tree());

				add_nodes(scene, b_engine, b_data, b_scene, !preview, graph, b_ntree);
			}
			else {
				ShaderNode *closure, *out;

				closure = graph->add(new DiffuseBsdfNode());
				closure->input("Color")->value = get_float3(b_mat->diffuse_color());
				out = graph->output();

				graph->connect(closure->output("BSDF"), out->input("Surface"));
			}

			/* settings */
			PointerRNA cmat = RNA_pointer_get(&b_mat->ptr, "cycles");
			shader->use_mis = get_boolean(cmat, "sample_as_light");
			shader->use_transparent_shadow = get_boolean(cmat, "use_transparent_shadow");
			shader->heterogeneous_volume = !get_boolean(cmat, "homogeneous_volume");
			shader->volume_sampling_method = (VolumeSampling)RNA_enum_get(&cmat, "volume_sampling");
			shader->volume_interpolation_method = (VolumeInterpolation)RNA_enum_get(&cmat, "volume_interpolation");

			shader->set_graph(graph);
			shader->tag_update(scene);
		}
	}
}
예제 #6
0
static void create_subd_mesh(Scene *scene,
                             Mesh *mesh,
                             BL::Mesh& b_mesh,
                             PointerRNA *cmesh,
                             const vector<uint>& used_shaders)
{
	/* create subd mesh */
	SubdMesh sdmesh;

	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		sdmesh.add_vert(get_float3(v->co()));

	/* create faces */
	BL::Mesh::tessfaces_iterator f;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0) ? 3: 4;
		//int shader = used_shaders[f->material_index()];

		if(n == 4)
			sdmesh.add_face(vi[0], vi[1], vi[2], vi[3]);
		else
			sdmesh.add_face(vi[0], vi[1], vi[2]);
	}

	/* finalize subd mesh */
	sdmesh.finish();

	/* parameters */
	bool need_ptex = mesh->need_attribute(scene, ATTR_STD_PTEX_FACE_ID) ||
	                 mesh->need_attribute(scene, ATTR_STD_PTEX_UV);

	SubdParams sdparams(mesh, used_shaders[0], true, need_ptex);
	sdparams.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
	//scene->camera->update();
	//sdparams.camera = scene->camera;

	/* tesselate */
	DiagSplit dsplit(sdparams);
	sdmesh.tessellate(&dsplit);
}
예제 #7
0
static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
{
  if (scene->need_motion() == Scene::MOTION_NONE)
    return;

  BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);

  if (!b_fluid_domain)
    return;

  /* If the mesh has modifiers following the fluid domain we can't export motion. */
  if (b_fluid_domain.fluid_mesh_vertices.length() != mesh->verts.size())
    return;

  /* Find or add attribute */
  float3 *P = &mesh->verts[0];
  Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

  if (!attr_mP) {
    attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
  }

  /* Only export previous and next frame, we don't have any in between data. */
  float motion_times[2] = {-1.0f, 1.0f};
  for (int step = 0; step < 2; step++) {
    float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
    float3 *mP = attr_mP->data_float3() + step * mesh->verts.size();

    BL::DomainFluidSettings::fluid_mesh_vertices_iterator fvi;
    int i = 0;

    for (b_fluid_domain.fluid_mesh_vertices.begin(fvi);
         fvi != b_fluid_domain.fluid_mesh_vertices.end();
         ++fvi, ++i) {
      mP[i] = P[i] + get_float3(fvi->velocity()) * relative_time;
    }
  }
}
예제 #8
0
static void set_default_value(ShaderInput *input,
                              SocketType b_sock,
                              BL::BlendData b_data,
                              BL::ID b_id)
{
	/* TODO(sergey): Use static assert to check SocketType is either BL::NodeSocket
	 * or BL::NodeSocketInterface.
	 */
	/* copy values for non linked inputs */
	switch(input->type) {
	case SHADER_SOCKET_FLOAT: {
		input->set(get_float(b_sock.ptr, "default_value"));
		break;
	}
	case SHADER_SOCKET_INT: {
		input->set((float)get_int(b_sock.ptr, "default_value"));
		break;
	}
	case SHADER_SOCKET_COLOR: {
		input->set(float4_to_float3(get_float4(b_sock.ptr, "default_value")));
		break;
	}
	case SHADER_SOCKET_NORMAL:
	case SHADER_SOCKET_POINT:
	case SHADER_SOCKET_VECTOR: {
		input->set(get_float3(b_sock.ptr, "default_value"));
		break;
	}
	case SHADER_SOCKET_STRING: {
		input->set((ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
		break;
	}
	
	case SHADER_SOCKET_CLOSURE:
	case SHADER_SOCKET_UNDEFINED:
		break;
	}
}
static void set_default_value(ShaderInput *input,
                              BL::NodeSocket& b_sock,
                              BL::BlendData& b_data,
                              BL::ID& b_id)
{
	Node *node = input->parent;
	const SocketType& socket = input->socket_type;

	/* copy values for non linked inputs */
	switch(input->type()) {
		case SocketType::FLOAT: {
			node->set(socket, get_float(b_sock.ptr, "default_value"));
			break;
		}
		case SocketType::INT: {
			node->set(socket, get_int(b_sock.ptr, "default_value"));
			break;
		}
		case SocketType::COLOR: {
			node->set(socket, float4_to_float3(get_float4(b_sock.ptr, "default_value")));
			break;
		}
		case SocketType::NORMAL:
		case SocketType::POINT:
		case SocketType::VECTOR: {
			node->set(socket, get_float3(b_sock.ptr, "default_value"));
			break;
		}
		case SocketType::STRING: {
			node->set(socket, (ustring)blender_absolute_path(b_data, b_id, get_string(b_sock.ptr, "default_value")));
			break;
		}
		default:
			break;
	}
}
예제 #10
0
CCL_NAMESPACE_BEGIN

/* Utilities */

bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object)
{
	/* test if this dupli was generated from a particle sytem */
	BL::ParticleSystem b_psys = b_dup.particle_system();
	if(!b_psys)
		return false;

	/* test if we need particle data */
	if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE))
		return false;

	/* don't handle child particles yet */
	BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup.persistent_id();

	if(persistent_id[0] >= b_psys.particles.length())
		return false;

	/* find particle system */
	ParticleSystemKey key(b_ob, persistent_id);
	ParticleSystem *psys;

	bool first_use = !particle_system_map.is_used(key);
	bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key);

	/* no update needed? */
	if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update)
		return true;

	/* first time used in this sync loop? clear and tag update */
	if(first_use) {
		psys->particles.clear();
		psys->tag_update(scene);
	}

	/* add particle */
	BL::Particle b_pa = b_psys.particles[persistent_id[0]];
	Particle pa;
	
	pa.index = persistent_id[0];
	pa.age = b_scene.frame_current() - b_pa.birth_time();
	pa.lifetime = b_pa.lifetime();
	pa.location = get_float3(b_pa.location());
	pa.rotation = get_float4(b_pa.rotation());
	pa.size = b_pa.size();
	pa.velocity = get_float3(b_pa.velocity());
	pa.angular_velocity = get_float3(b_pa.angular_velocity());

	psys->particles.push_back(pa);

	if (object->particle_index != psys->particles.size() - 1)
		scene->object_manager->tag_update(scene);
	object->particle_system = psys;
	object->particle_index = psys->particles.size() - 1;

	/* return that this object has particle data */
	return true;
}
예제 #11
0
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* create vertices */
	BL::Mesh::vertices_iterator v;

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		mesh->verts.push_back(get_float3(v->co()));

	/* create vertex normals */
	Attribute *attr_N = mesh->attributes.add(Attribute::STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N= get_float3(v->normal());

	/* create faces */
	BL::Mesh::faces_iterator f;
	vector<int> nverts;

	for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0)? 3: 4;
		int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
		int shader = used_shaders[mi];
		bool smooth = f->use_smooth();

		mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);

		if(n == 4)
			mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);

		nverts.push_back(n);
	}

	/* create generated coordinates. todo: we should actually get the orco
	   coordinates from modifiers, for now we use texspace loc/size which
	   is available in the api. */
	if(mesh_need_attribute(scene, mesh, Attribute::STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(Attribute::STD_GENERATED);
		float3 loc = get_float3(b_mesh.texspace_location());
		float3 size = get_float3(b_mesh.texspace_size());

		if(size.x != 0.0f) size.x = 0.5f/size.x;
		if(size.y != 0.0f) size.y = 0.5f/size.y;
		if(size.z != 0.0f) size.z = 0.5f/size.z;

		loc = loc*size - make_float3(0.5f, 0.5f, 0.5f);

		float3 *fdata = attr->data_float3();
		BL::Mesh::vertices_iterator v;
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			fdata[i++] = get_float3(v->co())*size - loc;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::vertex_colors_iterator l;

		for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
			if(!mesh_need_attribute(scene, mesh, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name().c_str()), TypeDesc::TypeColor, Attribute::CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
				fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
				fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
				fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));

				if(nverts[i] == 4) {
					fdata[3] = fdata[0];
					fdata[4] = fdata[2];
					fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
					fdata += 6;
				}
				else
					fdata += 3;
			}
		}
	}

	/* create uv map attributes */
	{
		BL::Mesh::uv_textures_iterator l;

		for(b_mesh.uv_textures.begin(l); l != b_mesh.uv_textures.end(); ++l) {
			Attribute::Standard std = (l->active_render())? Attribute::STD_UV: Attribute::STD_NONE;
			ustring name = ustring(l->name().c_str());

			if(!(mesh_need_attribute(scene, mesh, name) || mesh_need_attribute(scene, mesh, std)))
				continue;

			Attribute *attr;

			if(l->active_render())
				attr = mesh->attributes.add(std, name);
			else
				attr = mesh->attributes.add(name, TypeDesc::TypePoint, Attribute::CORNER);

			BL::MeshTextureFaceLayer::data_iterator t;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
				fdata[0] =  get_float3(t->uv1());
				fdata[1] =  get_float3(t->uv2());
				fdata[2] =  get_float3(t->uv3());
				fdata += 3;

				if(nverts[i] == 4) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv3());
					fdata[2] =  get_float3(t->uv4());
					fdata += 3;
				}
			}
		}
	}
}
예제 #12
0
void BlenderSync::sync_light(BL::Object &b_parent,
                             int persistent_id[OBJECT_PERSISTENT_ID_SIZE],
                             BL::Object &b_ob,
                             BL::Object &b_ob_instance,
                             int random_id,
                             Transform &tfm,
                             bool *use_portal)
{
  /* test if we need to sync */
  Light *light;
  ObjectKey key(b_parent, persistent_id, b_ob_instance);

  if (!light_map.sync(&light, b_ob, b_parent, key)) {
    if (light->is_portal)
      *use_portal = true;
    return;
  }

  BL::Light b_light(b_ob.data());

  /* type */
  switch (b_light.type()) {
    case BL::Light::type_POINT: {
      BL::PointLight b_point_light(b_light);
      light->size = b_point_light.shadow_soft_size();
      light->type = LIGHT_POINT;
      break;
    }
    case BL::Light::type_SPOT: {
      BL::SpotLight b_spot_light(b_light);
      light->size = b_spot_light.shadow_soft_size();
      light->type = LIGHT_SPOT;
      light->spot_angle = b_spot_light.spot_size();
      light->spot_smooth = b_spot_light.spot_blend();
      break;
    }
    /* Hemi were removed from 2.8 */
    // case BL::Light::type_HEMI: {
    //  light->type = LIGHT_DISTANT;
    //  light->size = 0.0f;
    //  break;
    // }
    case BL::Light::type_SUN: {
      BL::SunLight b_sun_light(b_light);
      light->size = b_sun_light.shadow_soft_size();
      light->type = LIGHT_DISTANT;
      break;
    }
    case BL::Light::type_AREA: {
      BL::AreaLight b_area_light(b_light);
      light->size = 1.0f;
      light->axisu = transform_get_column(&tfm, 0);
      light->axisv = transform_get_column(&tfm, 1);
      light->sizeu = b_area_light.size();
      switch (b_area_light.shape()) {
        case BL::AreaLight::shape_SQUARE:
          light->sizev = light->sizeu;
          light->round = false;
          break;
        case BL::AreaLight::shape_RECTANGLE:
          light->sizev = b_area_light.size_y();
          light->round = false;
          break;
        case BL::AreaLight::shape_DISK:
          light->sizev = light->sizeu;
          light->round = true;
          break;
        case BL::AreaLight::shape_ELLIPSE:
          light->sizev = b_area_light.size_y();
          light->round = true;
          break;
      }
      light->type = LIGHT_AREA;
      break;
    }
  }

  /* strength */
  light->strength = get_float3(b_light.color());
  light->strength *= BL::PointLight(b_light).energy();

  /* location and (inverted!) direction */
  light->co = transform_get_column(&tfm, 3);
  light->dir = -transform_get_column(&tfm, 2);
  light->tfm = tfm;

  /* shader */
  vector<Shader *> used_shaders;
  find_shader(b_light, used_shaders, scene->default_light);
  light->shader = used_shaders[0];

  /* shadow */
  PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
  PointerRNA clight = RNA_pointer_get(&b_light.ptr, "cycles");
  light->cast_shadow = get_boolean(clight, "cast_shadow");
  light->use_mis = get_boolean(clight, "use_multiple_importance_sampling");

  int samples = get_int(clight, "samples");
  if (get_boolean(cscene, "use_square_samples"))
    light->samples = samples * samples;
  else
    light->samples = samples;

  light->max_bounces = get_int(clight, "max_bounces");

  if (b_ob != b_ob_instance) {
    light->random_id = random_id;
  }
  else {
    light->random_id = hash_int_2d(hash_string(b_ob.name().c_str()), 0);
  }

  if (light->type == LIGHT_AREA)
    light->is_portal = get_boolean(clight, "is_portal");
  else
    light->is_portal = false;

  if (light->is_portal)
    *use_portal = true;

  /* visibility */
  uint visibility = object_ray_visibility(b_ob);
  light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0;
  light->use_glossy = (visibility & PATH_RAY_GLOSSY) != 0;
  light->use_transmission = (visibility & PATH_RAY_TRANSMIT) != 0;
  light->use_scatter = (visibility & PATH_RAY_VOLUME_SCATTER) != 0;

  /* tag */
  light->tag_update(scene);
}
예제 #13
0
static void create_mesh(Scene *scene,
                        Mesh *mesh,
                        BL::Mesh& b_mesh,
                        const vector<uint>& used_shaders)
{
	/* count vertices and faces */
	int numverts = b_mesh.vertices.length();
	int numfaces = b_mesh.tessfaces.length();
	int numtris = 0;
	bool use_loop_normals = b_mesh.use_auto_smooth();

	BL::Mesh::vertices_iterator v;
	BL::Mesh::tessfaces_iterator f;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		numtris += (vi[3] == 0)? 1: 2;
	}

	/* reserve memory */
	mesh->reserve(numverts, numtris, 0, 0);

	/* create vertex coordinates and normals */
	int i = 0;
	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i)
		mesh->verts[i] = get_float3(v->co());

	Attribute *attr_N = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N = get_float3(v->normal());
	N = attr_N->data_float3();

	/* create generated coordinates from undeformed coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		float3 *generated = attr->data_float3();
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			generated[i++] = get_float3(v->undeformed_co())*size - loc;
	}

	/* Create needed vertex attributes. */
	attr_create_pointiness(scene, mesh, b_mesh);

	/* create faces */
	vector<int> nverts(numfaces);
	vector<int> face_flags(numfaces, FACE_FLAG_NONE);
	int fi = 0, ti = 0;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0)? 3: 4;
		int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
		int shader = used_shaders[mi];
		bool smooth = f->use_smooth() || use_loop_normals;

		/* split vertices if normal is different
		 *
		 * note all vertex attributes must have been set here so we can split
		 * and copy attributes in split_vertex without remapping later */
		if(use_loop_normals) {
			BL::Array<float, 12> loop_normals = f->split_normals();

			for(int i = 0; i < n; i++) {
				float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);

				if(N[vi[i]] != loop_N) {
					int new_vi = mesh->split_vertex(vi[i]);

					/* set new normal and vertex index */
					N = attr_N->data_float3();
					N[new_vi] = loop_N;
					vi[i] = new_vi;
				}
			}
		}

		/* create triangles */
		if(n == 4) {
			if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
			   is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
			{
				mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth);
				mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth);
				face_flags[fi] |= FACE_FLAG_DIVIDE_24;
			}
			else {
				mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);
				mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth);
				face_flags[fi] |= FACE_FLAG_DIVIDE_13;
			}
		}
		else
			mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);

		nverts[fi] = n;
	}

	/* Create all needed attributes.
	 * The calculate functions will check whether they're needed or not.
	 */
	attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags);
	attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags);

	/* for volume objects, create a matrix to transform from object space to
	 * mesh texture space. this does not work with deformations but that can
	 * probably only be done well with a volume grid mapping of coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
		Transform *tfm = attr->data_transform();

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		*tfm = transform_translate(-loc)*transform_scale(size);
	}
}
예제 #14
0
/* Create vertex pointiness attributes. */
static void attr_create_pointiness(Scene *scene,
                                   Mesh *mesh,
                                   BL::Mesh& b_mesh)
{
	if(mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
		const int numverts = b_mesh.vertices.length();
		Attribute *attr = mesh->attributes.add(ATTR_STD_POINTINESS);
		float *data = attr->data_float();
		int *counter = new int[numverts];
		float *raw_data = new float[numverts];
		float3 *edge_accum = new float3[numverts];

		/* Calculate pointiness using single ring neighborhood. */
		memset(counter, 0, sizeof(int) * numverts);
		memset(raw_data, 0, sizeof(float) * numverts);
		memset(edge_accum, 0, sizeof(float3) * numverts);
		BL::Mesh::edges_iterator e;
		int i = 0;
		for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
			int v0 = b_mesh.edges[i].vertices()[0],
			    v1 = b_mesh.edges[i].vertices()[1];
			float3 co0 = get_float3(b_mesh.vertices[v0].co()),
			       co1 = get_float3(b_mesh.vertices[v1].co());
			float3 edge = normalize(co1 - co0);
			edge_accum[v0] += edge;
			edge_accum[v1] += -edge;
			++counter[v0];
			++counter[v1];
		}
		i = 0;
		BL::Mesh::vertices_iterator v;
		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i) {
			if(counter[i] > 0) {
				float3 normal = get_float3(b_mesh.vertices[i].normal());
				float angle = safe_acosf(dot(normal, edge_accum[i] / counter[i]));
				raw_data[i] = angle * M_1_PI_F;
			}
			else {
				raw_data[i] = 0.0f;
			}
		}

		/* Blur vertices to approximate 2 ring neighborhood. */
		memset(counter, 0, sizeof(int) * numverts);
		memcpy(data, raw_data, sizeof(float) * numverts);
		i = 0;
		for(b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++i) {
			int v0 = b_mesh.edges[i].vertices()[0],
			    v1 = b_mesh.edges[i].vertices()[1];
			data[v0] += raw_data[v1];
			data[v1] += raw_data[v0];
			++counter[v0];
			++counter[v1];
		}
		for(i = 0; i < numverts; ++i) {
			data[i] /= counter[i] + 1;
		}

		delete [] counter;
		delete [] raw_data;
		delete [] edge_accum;
	}
}
예제 #15
0
static ShaderNode *add_node(Scene *scene,
                            BL::RenderEngine& b_engine,
                            BL::BlendData& b_data,
                            BL::Scene& b_scene,
                            const bool background,
                            ShaderGraph *graph,
                            BL::ShaderNodeTree& b_ntree,
                            BL::ShaderNode& b_node)
{
	ShaderNode *node = NULL;

	/* existing blender nodes */
	if(b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
		BL::ShaderNodeRGBCurve b_curve_node(b_node);
		BL::CurveMapping mapping(b_curve_node.mapping());
		RGBCurvesNode *curves = new RGBCurvesNode();
		curvemapping_color_to_array(mapping,
		                            curves->curves,
		                            RAMP_TABLE_SIZE,
		                            true);
		curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
		node = curves;
	}
	if(b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
		BL::ShaderNodeVectorCurve b_curve_node(b_node);
		BL::CurveMapping mapping(b_curve_node.mapping());
		VectorCurvesNode *curves = new VectorCurvesNode();
		curvemapping_color_to_array(mapping,
		                            curves->curves,
		                            RAMP_TABLE_SIZE,
		                            false);
		curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
		node = curves;
	}
	else if(b_node.is_a(&RNA_ShaderNodeValToRGB)) {
		RGBRampNode *ramp = new RGBRampNode();
		BL::ShaderNodeValToRGB b_ramp_node(b_node);
		BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
		colorramp_to_array(b_color_ramp, ramp->ramp, RAMP_TABLE_SIZE);
		ramp->interpolate = b_color_ramp.interpolation() != BL::ColorRamp::interpolation_CONSTANT;
		node = ramp;
	}
	else if(b_node.is_a(&RNA_ShaderNodeRGB)) {
		ColorNode *color = new ColorNode();
		color->value = get_node_output_rgba(b_node, "Color");
		node = color;
	}
	else if(b_node.is_a(&RNA_ShaderNodeValue)) {
		ValueNode *value = new ValueNode();
		value->value = get_node_output_value(b_node, "Value");
		node = value;
	}
	else if(b_node.is_a(&RNA_ShaderNodeCameraData)) {
		node = new CameraNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeInvert)) {
		node = new InvertNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeGamma)) {
		node = new GammaNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
		node = new BrightContrastNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeMixRGB)) {
		BL::ShaderNodeMixRGB b_mix_node(b_node);
		MixNode *mix = new MixNode();
		mix->type = MixNode::type_enum[b_mix_node.blend_type()];
		/* Tag if it's Mix */
		if(b_mix_node.blend_type() == 0) 
			mix->special_type = SHADER_SPECIAL_TYPE_MIX_RGB;

		mix->use_clamp = b_mix_node.use_clamp();
		node = mix;
	}
	else if(b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
		node = new SeparateRGBNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
		node = new CombineRGBNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
		node = new SeparateHSVNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
		node = new CombineHSVNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
		node = new SeparateXYZNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
		node = new CombineXYZNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
		node = new HSVNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
		node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
	}
	else if(b_node.is_a(&RNA_ShaderNodeMath)) {
		BL::ShaderNodeMath b_math_node(b_node);
		MathNode *math = new MathNode();
		math->type = MathNode::type_enum[b_math_node.operation()];
		math->use_clamp = b_math_node.use_clamp();
		node = math;
	}
	else if(b_node.is_a(&RNA_ShaderNodeVectorMath)) {
		BL::ShaderNodeVectorMath b_vector_math_node(b_node);
		VectorMathNode *vmath = new VectorMathNode();
		vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
		node = vmath;
	}
	else if(b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
		BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
		VectorTransformNode *vtransform = new VectorTransformNode();
		vtransform->type = VectorTransformNode::type_enum[b_vector_transform_node.vector_type()];
		vtransform->convert_from = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_from()];
		vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()];
		node = vtransform;
	}
	else if(b_node.is_a(&RNA_ShaderNodeNormal)) {
		BL::Node::outputs_iterator out_it;
		b_node.outputs.begin(out_it);

		NormalNode *norm = new NormalNode();
		norm->direction = get_node_output_vector(b_node, "Normal");
		node = norm;
	}
	else if(b_node.is_a(&RNA_ShaderNodeMapping)) {
		BL::ShaderNodeMapping b_mapping_node(b_node);
		MappingNode *mapping = new MappingNode();

		get_tex_mapping(&mapping->tex_mapping, b_mapping_node);

		node = mapping;
	}
	else if(b_node.is_a(&RNA_ShaderNodeFresnel)) {
		node = new FresnelNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
		node = new LayerWeightNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeAddShader)) {
		node = new AddClosureNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeMixShader)) {
		node = new MixClosureNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeAttribute)) {
		BL::ShaderNodeAttribute b_attr_node(b_node);
		AttributeNode *attr = new AttributeNode();
		attr->attribute = b_attr_node.attribute_name();
		node = attr;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBackground)) {
		node = new BackgroundNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeHoldout)) {
		node = new HoldoutNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
		BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
		AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();

		switch(b_aniso_node.distribution()) {
			case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
				aniso->distribution = ustring("Beckmann");
				break;
			case BL::ShaderNodeBsdfAnisotropic::distribution_GGX:
				aniso->distribution = ustring("GGX");
				break;
			case BL::ShaderNodeBsdfAnisotropic::distribution_ASHIKHMIN_SHIRLEY:
				aniso->distribution = ustring("Ashikhmin-Shirley");
				break;
		}

		node = aniso;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
		node = new DiffuseBsdfNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
		BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);

		SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();

		switch(b_subsurface_node.falloff()) {
			case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
				subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
				break;
			case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
				subsurface->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
				break;
			case BL::ShaderNodeSubsurfaceScattering::falloff_BURLEY:
				subsurface->closure = CLOSURE_BSSRDF_BURLEY_ID;
				break;
		}

		node = subsurface;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
		BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
		GlossyBsdfNode *glossy = new GlossyBsdfNode();
		
		switch(b_glossy_node.distribution()) {
			case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
				glossy->distribution = ustring("Sharp");
				break;
			case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
				glossy->distribution = ustring("Beckmann");
				break;
			case BL::ShaderNodeBsdfGlossy::distribution_GGX:
				glossy->distribution = ustring("GGX");
				break;
			case BL::ShaderNodeBsdfGlossy::distribution_ASHIKHMIN_SHIRLEY:
				glossy->distribution = ustring("Ashikhmin-Shirley");
				break;
		}
		node = glossy;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
		BL::ShaderNodeBsdfGlass b_glass_node(b_node);
		GlassBsdfNode *glass = new GlassBsdfNode();
		switch(b_glass_node.distribution()) {
			case BL::ShaderNodeBsdfGlass::distribution_SHARP:
				glass->distribution = ustring("Sharp");
				break;
			case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
				glass->distribution = ustring("Beckmann");
				break;
			case BL::ShaderNodeBsdfGlass::distribution_GGX:
				glass->distribution = ustring("GGX");
				break;
		}
		node = glass;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
		BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
		RefractionBsdfNode *refraction = new RefractionBsdfNode();
		switch(b_refraction_node.distribution()) {
			case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
				refraction->distribution = ustring("Sharp");
				break;
			case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
				refraction->distribution = ustring("Beckmann");
				break;
			case BL::ShaderNodeBsdfRefraction::distribution_GGX:
				refraction->distribution = ustring("GGX");
				break;
		}
		node = refraction;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
		BL::ShaderNodeBsdfToon b_toon_node(b_node);
		ToonBsdfNode *toon = new ToonBsdfNode();
		switch(b_toon_node.component()) {
			case BL::ShaderNodeBsdfToon::component_DIFFUSE:
				toon->component = ustring("Diffuse");
				break;
			case BL::ShaderNodeBsdfToon::component_GLOSSY:
				toon->component = ustring("Glossy");
				break;
		}
		node = toon;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
		BL::ShaderNodeBsdfHair b_hair_node(b_node);
		HairBsdfNode *hair = new HairBsdfNode();
		switch(b_hair_node.component()) {
			case BL::ShaderNodeBsdfHair::component_Reflection:
				hair->component = ustring("Reflection");
				break;
			case BL::ShaderNodeBsdfHair::component_Transmission:
				hair->component = ustring("Transmission");
				break;
		}
		node = hair;
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
		node = new TranslucentBsdfNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
		node = new TransparentBsdfNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
		node = new VelvetBsdfNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeEmission)) {
		node = new EmissionNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
		node = new AmbientOcclusionNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
		node = new ScatterVolumeNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
		node = new AbsorptionVolumeNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
		node = new GeometryNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeWireframe)) {
		BL::ShaderNodeWireframe b_wireframe_node(b_node);
		WireframeNode *wire = new WireframeNode();
		wire->use_pixel_size = b_wireframe_node.use_pixel_size();
		node = wire;
	}
	else if(b_node.is_a(&RNA_ShaderNodeWavelength)) {
		node = new WavelengthNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBlackbody)) {
		node = new BlackbodyNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeLightPath)) {
		node = new LightPathNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
		node = new LightFalloffNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
		node = new ObjectInfoNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
		node = new ParticleInfoNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeHairInfo)) {
		node = new HairInfoNode();
	}
	else if(b_node.is_a(&RNA_ShaderNodeBump)) {
		BL::ShaderNodeBump b_bump_node(b_node);
		BumpNode *bump = new BumpNode();
		bump->invert = b_bump_node.invert();
		node = bump;
	}
	else if(b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
		if(scene->shader_manager->use_osl()) {
			/* create script node */
			BL::ShaderNodeScript b_script_node(b_node);
			OSLScriptNode *script_node = new OSLScriptNode();

			OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
			string bytecode_hash = b_script_node.bytecode_hash();

			/* Gather additional information from the shader, such as
			 * input/output type info needed for proper node construction.
			 */
			OSL::OSLQuery query;

			if(!bytecode_hash.empty()) {
				query.open_bytecode(b_script_node.bytecode());
			}
			else {
				!OSLShaderManager::osl_query(query, b_script_node.filepath());
			}
			/* TODO(sergey): Add proper query info error parsing. */

			/* Generate inputs/outputs from node sockets
			 *
			 * Note: the node sockets are generated from OSL parameters,
			 * so the names match those of the corresponding parameters exactly.
			 *
			 * Note 2: ShaderInput/ShaderOutput store shallow string copies only!
			 * Socket names must be stored in the extra lists instead. */
			BL::Node::inputs_iterator b_input;

			for(b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
				script_node->input_names.push_back(ustring(b_input->name()));
				ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(),
				                                            convert_osl_socket_type(query, *b_input));
				set_default_value(input, *b_input, b_data, b_ntree);
			}

			BL::Node::outputs_iterator b_output;

			for(b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
				script_node->output_names.push_back(ustring(b_output->name()));
				script_node->add_output(script_node->output_names.back().c_str(),
				                        convert_osl_socket_type(query, *b_output));
			}

			/* load bytecode or filepath */
			if(!bytecode_hash.empty()) {
				/* loaded bytecode if not already done */
				if(!manager->shader_test_loaded(bytecode_hash))
					manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());

				script_node->bytecode_hash = bytecode_hash;
			}
			else {
				/* set filepath */
				script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
			}

			node = script_node;
		}
#else
		(void)b_data;
		(void)b_ntree;
#endif
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexImage)) {
		BL::ShaderNodeTexImage b_image_node(b_node);
		BL::Image b_image(b_image_node.image());
		BL::ImageUser b_image_user(b_image_node.image_user());
		ImageTextureNode *image = new ImageTextureNode();
		if(b_image) {
			/* builtin images will use callback-based reading because
			 * they could only be loaded correct from blender side
			 */
			bool is_builtin = b_image.packed_file() ||
			                  b_image.source() == BL::Image::source_GENERATED ||
			                  b_image.source() == BL::Image::source_MOVIE ||
			                  b_engine.is_preview();

			if(is_builtin) {
				/* for builtin images we're using image datablock name to find an image to
				 * read pixels from later
				 *
				 * also store frame number as well, so there's no differences in handling
				 * builtin names for packed images and movies
				 */
				int scene_frame = b_scene.frame_current();
				int image_frame = image_user_frame_number(b_image_user,
				                                          scene_frame);
				image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
				image->builtin_data = b_image.ptr.data;
			}
			else {
				image->filename = image_user_file_path(b_image_user,
				                                       b_image,
				                                       b_scene.frame_current());
				image->builtin_data = NULL;
			}

			image->animated = b_image_node.image_user().use_auto_refresh();
			image->use_alpha = b_image.use_alpha();

			/* TODO(sergey): Does not work properly when we change builtin type. */
			if(b_image.is_updated()) {
				scene->image_manager->tag_reload_image(
				        image->filename,
				        image->builtin_data,
				        (InterpolationType)b_image_node.interpolation(),
				        (ExtensionType)b_image_node.extension());
			}
		}
		image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
		image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
		image->interpolation = (InterpolationType)b_image_node.interpolation();
		image->extension = (ExtensionType)b_image_node.extension();
		image->projection_blend = b_image_node.projection_blend();
		BL::TexMapping b_texture_mapping(b_image_node.texture_mapping());
		get_tex_mapping(&image->tex_mapping, b_texture_mapping);
		node = image;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
		BL::ShaderNodeTexEnvironment b_env_node(b_node);
		BL::Image b_image(b_env_node.image());
		BL::ImageUser b_image_user(b_env_node.image_user());
		EnvironmentTextureNode *env = new EnvironmentTextureNode();
		if(b_image) {
			bool is_builtin = b_image.packed_file() ||
			                  b_image.source() == BL::Image::source_GENERATED ||
			                  b_image.source() == BL::Image::source_MOVIE ||
			                  b_engine.is_preview();

			if(is_builtin) {
				int scene_frame = b_scene.frame_current();
				int image_frame = image_user_frame_number(b_image_user,
				                                          scene_frame);
				env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
				env->builtin_data = b_image.ptr.data;
			}
			else {
				env->filename = image_user_file_path(b_image_user,
				                                     b_image,
				                                     b_scene.frame_current());
				env->animated = b_env_node.image_user().use_auto_refresh();
				env->builtin_data = NULL;
			}

			env->use_alpha = b_image.use_alpha();

			/* TODO(sergey): Does not work properly when we change builtin type. */
			if(b_image.is_updated()) {
				scene->image_manager->tag_reload_image(env->filename,
				                                       env->builtin_data,
				                                       (InterpolationType)b_env_node.interpolation(),
				                                       EXTENSION_REPEAT);
			}
		}
		env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
		env->interpolation = (InterpolationType)b_env_node.interpolation();
		env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
		BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
		get_tex_mapping(&env->tex_mapping, b_texture_mapping);
		node = env;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexGradient)) {
		BL::ShaderNodeTexGradient b_gradient_node(b_node);
		GradientTextureNode *gradient = new GradientTextureNode();
		gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
		BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
		get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
		node = gradient;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
		BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
		VoronoiTextureNode *voronoi = new VoronoiTextureNode();
		voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
		BL::TexMapping b_texture_mapping(b_voronoi_node.texture_mapping());
		get_tex_mapping(&voronoi->tex_mapping, b_texture_mapping);
		node = voronoi;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexMagic)) {
		BL::ShaderNodeTexMagic b_magic_node(b_node);
		MagicTextureNode *magic = new MagicTextureNode();
		magic->depth = b_magic_node.turbulence_depth();
		BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
		get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
		node = magic;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexWave)) {
		BL::ShaderNodeTexWave b_wave_node(b_node);
		WaveTextureNode *wave = new WaveTextureNode();
		wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
		wave->profile = WaveTextureNode::profile_enum[(int)b_wave_node.wave_profile()];
		BL::TexMapping b_texture_mapping(b_wave_node.texture_mapping());
		get_tex_mapping(&wave->tex_mapping, b_texture_mapping);
		node = wave;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexChecker)) {
		BL::ShaderNodeTexChecker b_checker_node(b_node);
		CheckerTextureNode *checker = new CheckerTextureNode();
		BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
		get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
		node = checker;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexBrick)) {
		BL::ShaderNodeTexBrick b_brick_node(b_node);
		BrickTextureNode *brick = new BrickTextureNode();
		brick->offset = b_brick_node.offset();
		brick->offset_frequency = b_brick_node.offset_frequency();
		brick->squash = b_brick_node.squash();
		brick->squash_frequency = b_brick_node.squash_frequency();
		BL::TexMapping b_texture_mapping(b_brick_node.texture_mapping());
		get_tex_mapping(&brick->tex_mapping, b_texture_mapping);
		node = brick;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexNoise)) {
		BL::ShaderNodeTexNoise b_noise_node(b_node);
		NoiseTextureNode *noise = new NoiseTextureNode();
		BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
		get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
		node = noise;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
		BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
		MusgraveTextureNode *musgrave = new MusgraveTextureNode();
		musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
		BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
		get_tex_mapping(&musgrave->tex_mapping, b_texture_mapping);
		node = musgrave;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexCoord)) {
		BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
		TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
		tex_coord->from_dupli = b_tex_coord_node.from_dupli();
		if(b_tex_coord_node.object()) {
			tex_coord->use_transform = true;
			tex_coord->ob_tfm = get_transform(b_tex_coord_node.object().matrix_world());
		}
		node = tex_coord;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexSky)) {
		BL::ShaderNodeTexSky b_sky_node(b_node);
		SkyTextureNode *sky = new SkyTextureNode();
		sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
		sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
		sky->turbidity = b_sky_node.turbidity();
		sky->ground_albedo = b_sky_node.ground_albedo();
		BL::TexMapping b_texture_mapping(b_sky_node.texture_mapping());
		get_tex_mapping(&sky->tex_mapping, b_texture_mapping);
		node = sky;
	}
	else if(b_node.is_a(&RNA_ShaderNodeNormalMap)) {
		BL::ShaderNodeNormalMap b_normal_map_node(b_node);
		NormalMapNode *nmap = new NormalMapNode();
		nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
		nmap->attribute = b_normal_map_node.uv_map();
		node = nmap;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTangent)) {
		BL::ShaderNodeTangent b_tangent_node(b_node);
		TangentNode *tangent = new TangentNode();
		tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
		tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
		tangent->attribute = b_tangent_node.uv_map();
		node = tangent;
	}
	else if(b_node.is_a(&RNA_ShaderNodeUVMap)) {
		BL::ShaderNodeUVMap b_uvmap_node(b_node);
		UVMapNode *uvm = new UVMapNode();
		uvm->attribute = b_uvmap_node.uv_map();
		uvm->from_dupli = b_uvmap_node.from_dupli();
		node = uvm;
	}
	else if(b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
		BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
		PointDensityTextureNode *point_density = new PointDensityTextureNode();
		point_density->filename = b_point_density_node.name();
		point_density->space =
		        PointDensityTextureNode::space_enum[(int)b_point_density_node.space()];
		point_density->interpolation =
		        (InterpolationType)b_point_density_node.interpolation();
		point_density->builtin_data = b_point_density_node.ptr.data;

		/* 1 - render settings, 0 - vewport settings. */
		int settings = background ? 1 : 0;

		/* TODO(sergey): Use more proper update flag. */
		if(true) {
			b_point_density_node.cache_point_density(b_scene, settings);
			scene->image_manager->tag_reload_image(
			        point_density->filename,
			        point_density->builtin_data,
			        point_density->interpolation,
			        EXTENSION_CLIP);
		}
		node = point_density;

		/* Transformation form world space to texture space.
		 *
		 * NOTE: Do this after the texture is cached, this is because getting
		 * min/max will need to access this cache.
		 */
		BL::Object b_ob(b_point_density_node.object());
		if(b_ob) {
			float3 loc, size;
			point_density_texture_space(b_scene,
			                            b_point_density_node,
			                            settings,
			                            loc,
			                            size);
			point_density->tfm =
			        transform_translate(-loc) * transform_scale(size) *
			        transform_inverse(get_transform(b_ob.matrix_world()));
		}
	}

	if(node)
		graph->add(node);

	return node;
}
예제 #16
0
static void create_mesh(Scene *scene,
                        Mesh *mesh,
                        BL::Mesh &b_mesh,
                        const vector<Shader *> &used_shaders,
                        bool subdivision = false,
                        bool subdivide_uvs = true)
{
  /* count vertices and faces */
  int numverts = b_mesh.vertices.length();
  int numfaces = (!subdivision) ? b_mesh.loop_triangles.length() : b_mesh.polygons.length();
  int numtris = 0;
  int numcorners = 0;
  int numngons = 0;
  bool use_loop_normals = b_mesh.use_auto_smooth() &&
                          (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);

  /* If no faces, create empty mesh. */
  if (numfaces == 0) {
    return;
  }

  if (!subdivision) {
    numtris = numfaces;
  }
  else {
    BL::Mesh::polygons_iterator p;
    for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
      numngons += (p->loop_total() == 4) ? 0 : 1;
      numcorners += p->loop_total();
    }
  }

  /* allocate memory */
  mesh->reserve_mesh(numverts, numtris);
  mesh->reserve_subd_faces(numfaces, numngons, numcorners);

  /* create vertex coordinates and normals */
  BL::Mesh::vertices_iterator v;
  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
    mesh->add_vertex(get_float3(v->co()));

  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
  Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL);
  float3 *N = attr_N->data_float3();

  for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
    *N = get_float3(v->normal());
  N = attr_N->data_float3();

  /* create generated coordinates from undeformed coordinates */
  const bool need_default_tangent = (subdivision == false) && (b_mesh.uv_layers.length() == 0) &&
                                    (mesh->need_attribute(scene, ATTR_STD_UV_TANGENT));
  if (mesh->need_attribute(scene, ATTR_STD_GENERATED) || need_default_tangent) {
    Attribute *attr = attributes.add(ATTR_STD_GENERATED);
    attr->flags |= ATTR_SUBDIVIDED;

    float3 loc, size;
    mesh_texture_space(b_mesh, loc, size);

    float3 *generated = attr->data_float3();
    size_t i = 0;

    for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v) {
      generated[i++] = get_float3(v->undeformed_co()) * size - loc;
    }
  }

  /* create faces */
  if (!subdivision) {
    BL::Mesh::loop_triangles_iterator t;

    for (b_mesh.loop_triangles.begin(t); t != b_mesh.loop_triangles.end(); ++t) {
      BL::MeshPolygon p = b_mesh.polygons[t->polygon_index()];
      int3 vi = get_int3(t->vertices());

      int shader = clamp(p.material_index(), 0, used_shaders.size() - 1);
      bool smooth = p.use_smooth() || use_loop_normals;

      if (use_loop_normals) {
        BL::Array<float, 9> loop_normals = t->split_normals();
        for (int i = 0; i < 3; i++) {
          N[vi[i]] = make_float3(
              loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);
        }
      }

      /* Create triangles.
       *
       * NOTE: Autosmooth is already taken care about.
       */
      mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
    }
  }
  else {
    BL::Mesh::polygons_iterator p;
    vector<int> vi;

    for (b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
      int n = p->loop_total();
      int shader = clamp(p->material_index(), 0, used_shaders.size() - 1);
      bool smooth = p->use_smooth() || use_loop_normals;

      vi.resize(n);
      for (int i = 0; i < n; i++) {
        /* NOTE: Autosmooth is already taken care about. */
        vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();
      }

      /* create subd faces */
      mesh->add_subd_face(&vi[0], n, shader, smooth);
    }
  }

  /* Create all needed attributes.
   * The calculate functions will check whether they're needed or not.
   */
  attr_create_pointiness(scene, mesh, b_mesh, subdivision);
  attr_create_vertex_color(scene, mesh, b_mesh, subdivision);

  if (subdivision) {
    attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
  }
  else {
    attr_create_uv_map(scene, mesh, b_mesh);
  }

  /* for volume objects, create a matrix to transform from object space to
   * mesh texture space. this does not work with deformations but that can
   * probably only be done well with a volume grid mapping of coordinates */
  if (mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
    Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
    Transform *tfm = attr->data_transform();

    float3 loc, size;
    mesh_texture_space(b_mesh, loc, size);

    *tfm = transform_translate(-loc) * transform_scale(size);
  }
}
예제 #17
0
/* Create vertex color attributes. */
static void attr_create_vertex_color(Scene *scene,
                                     Mesh *mesh,
                                     BL::Mesh& b_mesh,
                                     const vector<int>& nverts,
                                     const vector<int>& face_flags,
                                     bool subdivision)
{
	if(subdivision) {
		BL::Mesh::vertex_colors_iterator l;

		for(b_mesh.vertex_colors.begin(l); l != b_mesh.vertex_colors.end(); ++l) {
			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->subd_attributes.add(ustring(l->name().c_str()),
			                                            TypeDesc::TypeColor,
			                                            ATTR_ELEMENT_CORNER_BYTE);

			BL::Mesh::polygons_iterator p;
			uchar4 *cdata = attr->data_uchar4();

			for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
				int n = p->loop_total();
				for(int i = 0; i < n; i++) {
					float3 color = get_float3(l->data[p->loop_start() + i].color());
					*(cdata++) = color_float_to_byte(color_srgb_to_scene_linear(color));
				}
			}
		}
	}
	else {
		BL::Mesh::tessface_vertex_colors_iterator l;
		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->attributes.add(ustring(l->name().c_str()),
			                                       TypeDesc::TypeColor,
			                                       ATTR_ELEMENT_CORNER_BYTE);

			BL::MeshColorLayer::data_iterator c;
			uchar4 *cdata = attr->data_uchar4();
			size_t i = 0;

			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
				int tri_a[3], tri_b[3];
				face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);

				uchar4 colors[4];
				colors[0] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color1())));
				colors[1] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color2())));
				colors[2] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color3())));
				if(nverts[i] == 4) {
					colors[3] = color_float_to_byte(color_srgb_to_scene_linear(get_float3(c->color4())));
				}

				cdata[0] = colors[tri_a[0]];
				cdata[1] = colors[tri_a[1]];
				cdata[2] = colors[tri_a[2]];

				if(nverts[i] == 4) {
					cdata[3] = colors[tri_b[0]];
					cdata[4] = colors[tri_b[1]];
					cdata[5] = colors[tri_b[2]];
					cdata += 6;
				}
				else
					cdata += 3;
			}
		}
	}
}
예제 #18
0
static float3 get_node_output_rgba(BL::Node b_node, const string& name)
{
	BL::NodeSocketRGBA sock(get_node_output(b_node, name));
	return get_float3(sock.default_value());
}
예제 #19
0
static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node)
{
	ShaderNode *node = NULL;

	switch(b_node.type()) {
		/* not supported */
		case BL::ShaderNode::type_GEOMETRY: break;
		case BL::ShaderNode::type_MATERIAL: break;
		case BL::ShaderNode::type_MATERIAL_EXT: break;
		case BL::ShaderNode::type_OUTPUT: break;
		case BL::ShaderNode::type_SQUEEZE: break;
		case BL::ShaderNode::type_TEXTURE: break;
		case BL::ShaderNode::type_FRAME: break;
		/* handled outside this function */
		case BL::ShaderNode::type_GROUP: break;
		/* existing blender nodes */
		case BL::ShaderNode::type_REROUTE: {
			BL::Node::inputs_iterator b_input;
			b_node.inputs.begin(b_input);
			BL::Node::outputs_iterator b_output;
			b_node.outputs.begin(b_output);
			ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type()));
			node = proxy;
			break;
		}
		case BL::ShaderNode::type_CURVE_VEC: {
			BL::ShaderNodeVectorCurve b_curve_node(b_node);
			VectorCurvesNode *curves = new VectorCurvesNode();
			curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false);
			node = curves;
			break;
		}
		case BL::ShaderNode::type_CURVE_RGB: {
			BL::ShaderNodeRGBCurve b_curve_node(b_node);
			RGBCurvesNode *curves = new RGBCurvesNode();
			curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
			node = curves;
			break;
		}
		case BL::ShaderNode::type_VALTORGB: {
			RGBRampNode *ramp = new RGBRampNode();
			BL::ShaderNodeValToRGB b_ramp_node(b_node);
			colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
			node = ramp;
			break;
		}
		case BL::ShaderNode::type_RGB: {
			ColorNode *color = new ColorNode();
			color->value = get_node_output_rgba(b_node, "Color");
			node = color;
			break;
		}
		case BL::ShaderNode::type_VALUE: {
			ValueNode *value = new ValueNode();
			value->value = get_node_output_value(b_node, "Value");
			node = value;
			break;
		}
		case BL::ShaderNode::type_CAMERA: {
			node = new CameraNode();
			break;
		}
		case BL::ShaderNode::type_INVERT: {
			node = new InvertNode();
			break;
		}
		case BL::ShaderNode::type_GAMMA: {
			node = new GammaNode();
			break;
		}
		case BL::ShaderNode::type_BRIGHTCONTRAST: {
			node = new BrightContrastNode();
			break;
		}
		case BL::ShaderNode::type_MIX_RGB: {
			BL::ShaderNodeMixRGB b_mix_node(b_node);
			MixNode *mix = new MixNode();
			mix->type = MixNode::type_enum[b_mix_node.blend_type()];
			mix->use_clamp = b_mix_node.use_clamp();
			node = mix;
			break;
		}
		case BL::ShaderNode::type_SEPRGB: {
			node = new SeparateRGBNode();
			break;
		}
		case BL::ShaderNode::type_COMBRGB: {
			node = new CombineRGBNode();
			break;
		}
		case BL::ShaderNode::type_HUE_SAT: {
			node = new HSVNode();
			break;
		}
		case BL::ShaderNode::type_RGBTOBW: {
			node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
			break;
		}
		case BL::ShaderNode::type_MATH: {
			BL::ShaderNodeMath b_math_node(b_node);
			MathNode *math = new MathNode();
			math->type = MathNode::type_enum[b_math_node.operation()];
			math->use_clamp = b_math_node.use_clamp();
			node = math;
			break;
		}
		case BL::ShaderNode::type_VECT_MATH: {
			BL::ShaderNodeVectorMath b_vector_math_node(b_node);
			VectorMathNode *vmath = new VectorMathNode();
			vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
			node = vmath;
			break;
		}
		case BL::ShaderNode::type_NORMAL: {
			BL::Node::outputs_iterator out_it;
			b_node.outputs.begin(out_it);
			BL::NodeSocketVectorNone vec_sock(*out_it);

			NormalNode *norm = new NormalNode();
			norm->direction = get_float3(vec_sock.default_value());

			node = norm;
			break;
		}
		case BL::ShaderNode::type_MAPPING: {
			BL::ShaderNodeMapping b_mapping_node(b_node);
			MappingNode *mapping = new MappingNode();

			get_tex_mapping(&mapping->tex_mapping, b_mapping_node);

			node = mapping;
			break;
		}

		/* new nodes */
		case BL::ShaderNode::type_OUTPUT_MATERIAL:
		case BL::ShaderNode::type_OUTPUT_WORLD:
		case BL::ShaderNode::type_OUTPUT_LAMP: {
			node = graph->output();
			break;
		}
		case BL::ShaderNode::type_FRESNEL: {
			node = new FresnelNode();
			break;
		}
		case BL::ShaderNode::type_LAYER_WEIGHT: {
			node = new LayerWeightNode();
			break;
		}
		case BL::ShaderNode::type_ADD_SHADER: {
			node = new AddClosureNode();
			break;
		}
		case BL::ShaderNode::type_MIX_SHADER: {
			node = new MixClosureNode();
			break;
		}
		case BL::ShaderNode::type_ATTRIBUTE: {
			BL::ShaderNodeAttribute b_attr_node(b_node);
			AttributeNode *attr = new AttributeNode();
			attr->attribute = b_attr_node.attribute_name();
			node = attr;
			break;
		}
		case BL::ShaderNode::type_BACKGROUND: {
			node = new BackgroundNode();
			break;
		}
		case BL::ShaderNode::type_HOLDOUT: {
			node = new HoldoutNode();
			break;
		}
		case BL::ShaderNode::type_BSDF_ANISOTROPIC: {
			node = new WardBsdfNode();
			break;
		}
		case BL::ShaderNode::type_BSDF_DIFFUSE: {
			node = new DiffuseBsdfNode();
			break;
		}
		case BL::ShaderNode::type_BSDF_GLOSSY: {
			BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
			GlossyBsdfNode *glossy = new GlossyBsdfNode();

			switch(b_glossy_node.distribution()) {
				case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
					glossy->distribution = ustring("Sharp");
					break;
				case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
					glossy->distribution = ustring("Beckmann");
					break;
				case BL::ShaderNodeBsdfGlossy::distribution_GGX:
					glossy->distribution = ustring("GGX");
					break;
			}
			node = glossy;
			break;
		}
		case BL::ShaderNode::type_BSDF_GLASS: {
			BL::ShaderNodeBsdfGlass b_glass_node(b_node);
			GlassBsdfNode *glass = new GlassBsdfNode();
			switch(b_glass_node.distribution()) {
				case BL::ShaderNodeBsdfGlass::distribution_SHARP:
					glass->distribution = ustring("Sharp");
					break;
				case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
					glass->distribution = ustring("Beckmann");
					break;
				case BL::ShaderNodeBsdfGlass::distribution_GGX:
					glass->distribution = ustring("GGX");
					break;
			}
			node = glass;
			break;
		}
		case BL::ShaderNode::type_BSDF_REFRACTION: {
			BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
			RefractionBsdfNode *refraction = new RefractionBsdfNode();
			switch(b_refraction_node.distribution()) {
				case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
					refraction->distribution = ustring("Sharp");
					break;
				case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
					refraction->distribution = ustring("Beckmann");
					break;
				case BL::ShaderNodeBsdfRefraction::distribution_GGX:
					refraction->distribution = ustring("GGX");
					break;
			}
			node = refraction;
			break;
		}
		case BL::ShaderNode::type_BSDF_TRANSLUCENT: {
			node = new TranslucentBsdfNode();
			break;
		}
		case BL::ShaderNode::type_BSDF_TRANSPARENT: {
			node = new TransparentBsdfNode();
			break;
		}
		case BL::ShaderNode::type_BSDF_VELVET: {
			node = new VelvetBsdfNode();
			break;
		}
		case BL::ShaderNode::type_EMISSION: {
			node = new EmissionNode();
			break;
		}
		case BL::ShaderNode::type_AMBIENT_OCCLUSION: {
			node = new AmbientOcclusionNode();
			break;
		}
		case BL::ShaderNode::type_VOLUME_ISOTROPIC: {
			node = new IsotropicVolumeNode();
			break;
		}
		case BL::ShaderNode::type_VOLUME_TRANSPARENT: {
			node = new TransparentVolumeNode();
			break;
		}
		case BL::ShaderNode::type_NEW_GEOMETRY: {
			node = new GeometryNode();
			break;
		}
		case BL::ShaderNode::type_LIGHT_PATH: {
			node = new LightPathNode();
			break;
		}
		case BL::ShaderNode::type_LIGHT_FALLOFF: {
			node = new LightFalloffNode();
			break;
		}
		case BL::ShaderNode::type_OBJECT_INFO: {
			node = new ObjectInfoNode();
			break;
		}
		case BL::ShaderNode::type_PARTICLE_INFO: {
			node = new ParticleInfoNode();
			break;
		}
		case BL::ShaderNode::type_HAIR_INFO: {
			node = new HairInfoNode();
			break;
		}
		case BL::ShaderNode::type_BUMP: {
			node = new BumpNode();
			break;
		}
		case BL::ShaderNode::type_SCRIPT: {
#ifdef WITH_OSL
			if(!scene->shader_manager->use_osl())
				break;

			/* create script node */
			BL::ShaderNodeScript b_script_node(b_node);
			OSLScriptNode *script_node = new OSLScriptNode();
			
			/* Generate inputs/outputs from node sockets
			 *
			 * Note: the node sockets are generated from OSL parameters,
			 * so the names match those of the corresponding parameters exactly.
			 *
			 * Note 2: ShaderInput/ShaderOutput store shallow string copies only!
			 * Socket names must be stored in the extra lists instead. */
			BL::Node::inputs_iterator b_input;

			for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
				script_node->input_names.push_back(ustring(b_input->name()));
				ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(), convert_socket_type(b_input->type()));
				set_default_value(input, *b_input, b_data, b_ntree);
			}

			BL::Node::outputs_iterator b_output;

			for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
				script_node->output_names.push_back(ustring(b_output->name()));
				script_node->add_output(script_node->output_names.back().c_str(), convert_socket_type(b_output->type()));
			}

			/* load bytecode or filepath */
			OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
			string bytecode_hash = b_script_node.bytecode_hash();

			if(!bytecode_hash.empty()) {
				/* loaded bytecode if not already done */
				if(!manager->shader_test_loaded(bytecode_hash))
					manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());

				script_node->bytecode_hash = bytecode_hash;
			}
			else {
				/* set filepath */
				script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
			}
			
			node = script_node;
#endif

			break;
		}
		case BL::ShaderNode::type_TEX_IMAGE: {
			BL::ShaderNodeTexImage b_image_node(b_node);
			BL::Image b_image(b_image_node.image());
			ImageTextureNode *image = new ImageTextureNode();
			if(b_image) {
				/* builtin images will use callback-based reading because
				 * they could only be loaded correct from blender side
				 */
				bool is_builtin = b_image.packed_file() ||
				                  b_image.source() == BL::Image::source_GENERATED ||
				                  b_image.source() == BL::Image::source_MOVIE;

				if(is_builtin) {
					/* for builtin images we're using image datablock name to find an image to
					 * read pixels from later
					 *
					 * also store frame number as well, so there's no differences in handling
					 * builtin names for packed images and movies
					 */
					int scene_frame = b_scene.frame_current();
					int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
					image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
					image->is_builtin = true;
				}
				else {
					image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
					image->is_builtin = false;
				}

				image->animated = b_image_node.image_user().use_auto_refresh();
			}
			image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
			image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
			image->projection_blend = b_image_node.projection_blend();
			get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
			node = image;
			break;
		}
		case BL::ShaderNode::type_TEX_ENVIRONMENT: {
			BL::ShaderNodeTexEnvironment b_env_node(b_node);
			BL::Image b_image(b_env_node.image());
			EnvironmentTextureNode *env = new EnvironmentTextureNode();
			if(b_image) {
				bool is_builtin = b_image.packed_file() ||
				                  b_image.source() == BL::Image::source_GENERATED ||
				                  b_image.source() == BL::Image::source_MOVIE;

				if(is_builtin) {
					int scene_frame = b_scene.frame_current();
					int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
					env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
					env->is_builtin = true;
				}
				else {
					env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
					env->animated = b_env_node.image_user().use_auto_refresh();
				}
			}
			env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
			env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
			get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
			node = env;
			break;
		}
		case BL::ShaderNode::type_TEX_GRADIENT: {
			BL::ShaderNodeTexGradient b_gradient_node(b_node);
			GradientTextureNode *gradient = new GradientTextureNode();
			gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
			get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
			node = gradient;
			break;
		}
		case BL::ShaderNode::type_TEX_VORONOI: {
			BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
			VoronoiTextureNode *voronoi = new VoronoiTextureNode();
			voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
			get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
			node = voronoi;
			break;
		}
		case BL::ShaderNode::type_TEX_MAGIC: {
			BL::ShaderNodeTexMagic b_magic_node(b_node);
			MagicTextureNode *magic = new MagicTextureNode();
			magic->depth = b_magic_node.turbulence_depth();
			get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
			node = magic;
			break;
		}
		case BL::ShaderNode::type_TEX_WAVE: {
			BL::ShaderNodeTexWave b_wave_node(b_node);
			WaveTextureNode *wave = new WaveTextureNode();
			wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
			get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
			node = wave;
			break;
		}
		case BL::ShaderNode::type_TEX_CHECKER: {
			BL::ShaderNodeTexChecker b_checker_node(b_node);
			CheckerTextureNode *checker = new CheckerTextureNode();
			get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
			node = checker;
			break;
		}
		case BL::ShaderNode::type_TEX_BRICK: {
			BL::ShaderNodeTexBrick b_brick_node(b_node);
			BrickTextureNode *brick = new BrickTextureNode();
			brick->offset = b_brick_node.offset();
			brick->offset_frequency = b_brick_node.offset_frequency();
			brick->squash = b_brick_node.squash();
			brick->squash_frequency = b_brick_node.squash_frequency();
			get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
			node = brick;
			break;
		}
		case BL::ShaderNode::type_TEX_NOISE: {
			BL::ShaderNodeTexNoise b_noise_node(b_node);
			NoiseTextureNode *noise = new NoiseTextureNode();
			get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
			node = noise;
			break;
		}
		case BL::ShaderNode::type_TEX_MUSGRAVE: {
			BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
			MusgraveTextureNode *musgrave = new MusgraveTextureNode();
			musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
			get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
			node = musgrave;
			break;
		}
		case BL::ShaderNode::type_TEX_COORD: {
			BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
			TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
			tex_coord->from_dupli = b_tex_coord_node.from_dupli();
			node = tex_coord;
			break;
		}
		case BL::ShaderNode::type_TEX_SKY: {
			BL::ShaderNodeTexSky b_sky_node(b_node);
			SkyTextureNode *sky = new SkyTextureNode();
			sky->sun_direction = get_float3(b_sky_node.sun_direction());
			sky->turbidity = b_sky_node.turbidity();
			get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
			node = sky;
			break;
		}
		case BL::ShaderNode::type_NORMAL_MAP: {
			BL::ShaderNodeNormalMap b_normal_map_node(b_node);
			NormalMapNode *nmap = new NormalMapNode();
			nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
			nmap->attribute = b_normal_map_node.uv_map();
			node = nmap;
			break;
		}
		case BL::ShaderNode::type_TANGENT: {
			BL::ShaderNodeTangent b_tangent_node(b_node);
			TangentNode *tangent = new TangentNode();
			tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
			tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
			tangent->attribute = b_tangent_node.uv_map();
			node = tangent;
			break;
		}
	}

	if(node && node != graph->output())
		graph->add(node);

	return node;
}
예제 #20
0
static void create_mesh(Scene *scene,
                        Mesh *mesh,
                        BL::Mesh& b_mesh,
                        const vector<Shader*>& used_shaders,
                        bool subdivision=false,
                        bool subdivide_uvs=true)
{
	/* count vertices and faces */
	int numverts = b_mesh.vertices.length();
	int numfaces = (!subdivision) ? b_mesh.tessfaces.length() : b_mesh.polygons.length();
	int numtris = 0;
	int numcorners = 0;
	int numngons = 0;
	bool use_loop_normals = b_mesh.use_auto_smooth() && (mesh->subdivision_type != Mesh::SUBDIVISION_CATMULL_CLARK);

	BL::Mesh::vertices_iterator v;
	BL::Mesh::tessfaces_iterator f;
	BL::Mesh::polygons_iterator p;

	if(!subdivision) {
		for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
			int4 vi = get_int4(f->vertices_raw());
			numtris += (vi[3] == 0)? 1: 2;
		}
	}
	else {
		for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
			numngons += (p->loop_total() == 4)? 0: 1;
			numcorners += p->loop_total();
		}
	}

	/* allocate memory */
	mesh->reserve_mesh(numverts, numtris);
	mesh->reserve_subd_faces(numfaces, numngons, numcorners);

	/* create vertex coordinates and normals */
	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
		mesh->add_vertex(get_float3(v->co()));

	AttributeSet& attributes = (subdivision)? mesh->subd_attributes: mesh->attributes;
	Attribute *attr_N = attributes.add(ATTR_STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N = get_float3(v->normal());
	N = attr_N->data_float3();

	/* create generated coordinates from undeformed coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
		Attribute *attr = attributes.add(ATTR_STD_GENERATED);
		attr->flags |= ATTR_SUBDIVIDED;

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		float3 *generated = attr->data_float3();
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			generated[i++] = get_float3(v->undeformed_co())*size - loc;
	}

	/* Create needed vertex attributes. */
	attr_create_pointiness(scene, mesh, b_mesh, subdivision);

	/* create faces */
	vector<int> nverts(numfaces);
	vector<int> face_flags(numfaces, FACE_FLAG_NONE);
	int fi = 0;

	if(!subdivision) {
		for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
			int4 vi = get_int4(f->vertices_raw());
			int n = (vi[3] == 0)? 3: 4;
			int shader = clamp(f->material_index(), 0, used_shaders.size()-1);
			bool smooth = f->use_smooth() || use_loop_normals;

			/* split vertices if normal is different
			 *
			 * note all vertex attributes must have been set here so we can split
			 * and copy attributes in split_vertex without remapping later */
			if(use_loop_normals) {
				BL::Array<float, 12> loop_normals = f->split_normals();

				for(int i = 0; i < n; i++) {
					float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);

					if(N[vi[i]] != loop_N) {
						int new_vi = mesh->split_vertex(vi[i]);

						/* set new normal and vertex index */
						N = attr_N->data_float3();
						N[new_vi] = loop_N;
						vi[i] = new_vi;
					}
				}
			}

			/* create triangles */
			if(n == 4) {
				if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
				   is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]])))
				{
					mesh->add_triangle(vi[0], vi[1], vi[3], shader, smooth);
					mesh->add_triangle(vi[2], vi[3], vi[1], shader, smooth);
					face_flags[fi] |= FACE_FLAG_DIVIDE_24;
				}
				else {
					mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
					mesh->add_triangle(vi[0], vi[2], vi[3], shader, smooth);
					face_flags[fi] |= FACE_FLAG_DIVIDE_13;
				}
			}
			else {
				mesh->add_triangle(vi[0], vi[1], vi[2], shader, smooth);
			}

			nverts[fi] = n;
		}
	}
	else {
		vector<int> vi;

		for(b_mesh.polygons.begin(p); p != b_mesh.polygons.end(); ++p) {
			int n = p->loop_total();
			int shader = clamp(p->material_index(), 0, used_shaders.size()-1);
			bool smooth = p->use_smooth() || use_loop_normals;

			vi.reserve(n);
			for(int i = 0; i < n; i++) {
				vi[i] = b_mesh.loops[p->loop_start() + i].vertex_index();

				/* split vertices if normal is different
				 *
				 * note all vertex attributes must have been set here so we can split
				 * and copy attributes in split_vertex without remapping later */
				if(use_loop_normals) {
					float3 loop_N = get_float3(b_mesh.loops[p->loop_start() + i].normal());

					if(N[vi[i]] != loop_N) {
						int new_vi = mesh->split_vertex(vi[i]);

						/* set new normal and vertex index */
						N = attr_N->data_float3();
						N[new_vi] = loop_N;
						vi[i] = new_vi;
					}
				}
			}

			/* create subd faces */
			mesh->add_subd_face(&vi[0], n, shader, smooth);
		}
	}

	/* Create all needed attributes.
	 * The calculate functions will check whether they're needed or not.
	 */
	attr_create_vertex_color(scene, mesh, b_mesh, nverts, face_flags, subdivision);
	attr_create_uv_map(scene, mesh, b_mesh, nverts, face_flags, subdivision, subdivide_uvs);

	/* for volume objects, create a matrix to transform from object space to
	 * mesh texture space. this does not work with deformations but that can
	 * probably only be done well with a volume grid mapping of coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
		Transform *tfm = attr->data_transform();

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		*tfm = transform_translate(-loc)*transform_scale(size);
	}
}
예제 #21
0
static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders)
{
	/* count vertices and faces */
	int numverts = b_mesh.vertices.length();
	int numfaces = b_mesh.tessfaces.length();
	int numtris = 0;
	bool use_loop_normals = b_mesh.use_auto_smooth();

	BL::Mesh::vertices_iterator v;
	BL::Mesh::tessfaces_iterator f;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
		int4 vi = get_int4(f->vertices_raw());
		numtris += (vi[3] == 0)? 1: 2;
	}

	/* reserve memory */
	mesh->reserve(numverts, numtris, 0, 0);

	/* create vertex coordinates and normals */
	int i = 0;
	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++i)
		mesh->verts[i] = get_float3(v->co());

	Attribute *attr_N = mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
	float3 *N = attr_N->data_float3();

	for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v, ++N)
		*N = get_float3(v->normal());
	N = attr_N->data_float3();

	/* create generated coordinates from undeformed coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED);

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		float3 *generated = attr->data_float3();
		size_t i = 0;

		for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end(); ++v)
			generated[i++] = get_float3(v->undeformed_co())*size - loc;
	}

	/* create faces */
	vector<int> nverts(numfaces);
	int fi = 0, ti = 0;

	for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f, ++fi) {
		int4 vi = get_int4(f->vertices_raw());
		int n = (vi[3] == 0)? 3: 4;
		int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
		int shader = used_shaders[mi];
		bool smooth = f->use_smooth();

		/* split vertices if normal is different
		 *
		 * note all vertex attributes must have been set here so we can split
		 * and copy attributes in split_vertex without remapping later */
		if(use_loop_normals) {
			BL::Array<float, 12> loop_normals = f->split_normals();

			for(int i = 0; i < n; i++) {
				float3 loop_N = make_float3(loop_normals[i * 3], loop_normals[i * 3 + 1], loop_normals[i * 3 + 2]);

				if(N[vi[i]] != loop_N) {
					int new_vi = mesh->split_vertex(vi[i]);

					/* set new normal and vertex index */
					N = attr_N->data_float3();
					N[new_vi] = loop_N;
					vi[i] = new_vi;
				}
			}
		}

		/* create triangles */
		if(n == 4) {
			if(is_zero(cross(mesh->verts[vi[1]] - mesh->verts[vi[0]], mesh->verts[vi[2]] - mesh->verts[vi[0]])) ||
				is_zero(cross(mesh->verts[vi[2]] - mesh->verts[vi[0]], mesh->verts[vi[3]] - mesh->verts[vi[0]]))) {
				mesh->set_triangle(ti++, vi[0], vi[1], vi[3], shader, smooth);
				mesh->set_triangle(ti++, vi[2], vi[3], vi[1], shader, smooth);
			}
			else {
				mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);
				mesh->set_triangle(ti++, vi[0], vi[2], vi[3], shader, smooth);
			}
		}
		else
			mesh->set_triangle(ti++, vi[0], vi[1], vi[2], shader, smooth);

		nverts[fi] = n;
	}

	/* create vertex color attributes */
	{
		BL::Mesh::tessface_vertex_colors_iterator l;

		for(b_mesh.tessface_vertex_colors.begin(l); l != b_mesh.tessface_vertex_colors.end(); ++l) {
			if(!mesh->need_attribute(scene, ustring(l->name().c_str())))
				continue;

			Attribute *attr = mesh->attributes.add(
				ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER);

			BL::MeshColorLayer::data_iterator c;
			float3 *fdata = attr->data_float3();
			size_t i = 0;

			for(l->data.begin(c); c != l->data.end(); ++c, ++i) {
				fdata[0] = color_srgb_to_scene_linear(get_float3(c->color1()));
				fdata[1] = color_srgb_to_scene_linear(get_float3(c->color2()));
				fdata[2] = color_srgb_to_scene_linear(get_float3(c->color3()));

				if(nverts[i] == 4) {
					fdata[3] = fdata[0];
					fdata[4] = fdata[2];
					fdata[5] = color_srgb_to_scene_linear(get_float3(c->color4()));
					fdata += 6;
				}
				else
					fdata += 3;
			}
		}
	}

	/* create uv map attributes */
	{
		BL::Mesh::tessface_uv_textures_iterator l;

		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
			bool active_render = l->active_render();
			AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
			ustring name = ustring(l->name().c_str());

			/* UV map */
			if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
				Attribute *attr;

				if(active_render)
					attr = mesh->attributes.add(std, name);
				else
					attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);

				BL::MeshTextureFaceLayer::data_iterator t;
				float3 *fdata = attr->data_float3();
				size_t i = 0;

				for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
					fdata[0] =  get_float3(t->uv1());
					fdata[1] =  get_float3(t->uv2());
					fdata[2] =  get_float3(t->uv3());
					fdata += 3;

					if(nverts[i] == 4) {
						fdata[0] =  get_float3(t->uv1());
						fdata[1] =  get_float3(t->uv3());
						fdata[2] =  get_float3(t->uv4());
						fdata += 3;
					}
				}
			}

			/* UV tangent */
			std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
			name = ustring((string(l->name().c_str()) + ".tangent").c_str());

			if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
				std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
				name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
				bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));

				mikk_compute_tangents(b_mesh, *l, mesh, nverts, need_sign, active_render);
			}
		}
	}

	/* for volume objects, create a matrix to transform from object space to
	 * mesh texture space. this does not work with deformations but that can
	 * probably only be done well with a volume grid mapping of coordinates */
	if(mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
		Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
		Transform *tfm = attr->data_transform();

		float3 loc, size;
		mesh_texture_space(b_mesh, loc, size);

		*tfm = transform_translate(-loc)*transform_scale(size);
	}
}
예제 #22
0
void BlenderSync::sync_mesh_motion(BL::Depsgraph &b_depsgraph,
                                   BL::Object &b_ob,
                                   Object *object,
                                   float motion_time)
{
  /* ensure we only sync instanced meshes once */
  Mesh *mesh = object->mesh;

  if (mesh_motion_synced.find(mesh) != mesh_motion_synced.end())
    return;

  mesh_motion_synced.insert(mesh);

  /* ensure we only motion sync meshes that also had mesh synced, to avoid
   * unnecessary work and to ensure that its attributes were clear */
  if (mesh_synced.find(mesh) == mesh_synced.end())
    return;

  /* Find time matching motion step required by mesh. */
  int motion_step = mesh->motion_step(motion_time);
  if (motion_step < 0) {
    return;
  }

  /* skip empty meshes */
  const size_t numverts = mesh->verts.size();
  const size_t numkeys = mesh->curve_keys.size();

  if (!numverts && !numkeys)
    return;

  /* skip objects without deforming modifiers. this is not totally reliable,
   * would need a more extensive check to see which objects are animated */
  BL::Mesh b_mesh(PointerRNA_NULL);

  /* fluid motion is exported immediate with mesh, skip here */
  BL::DomainFluidSettings b_fluid_domain = object_fluid_domain_find(b_ob);
  if (b_fluid_domain)
    return;

  if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) {
    /* get derived mesh */
    b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE);
  }

  if (!b_mesh) {
    /* if we have no motion blur on this frame, but on other frames, copy */
    if (numverts) {
      /* triangles */
      Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

      if (attr_mP) {
        Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
        Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
        float3 *P = &mesh->verts[0];
        float3 *N = (attr_N) ? attr_N->data_float3() : NULL;

        memcpy(attr_mP->data_float3() + motion_step * numverts, P, sizeof(float3) * numverts);
        if (attr_mN)
          memcpy(attr_mN->data_float3() + motion_step * numverts, N, sizeof(float3) * numverts);
      }
    }

    if (numkeys) {
      /* curves */
      Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

      if (attr_mP) {
        float3 *keys = &mesh->curve_keys[0];
        memcpy(attr_mP->data_float3() + motion_step * numkeys, keys, sizeof(float3) * numkeys);
      }
    }

    return;
  }

  /* TODO(sergey): Perform preliminary check for number of verticies. */
  if (numverts) {
    /* Find attributes. */
    Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
    Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
    Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
    bool new_attribute = false;
    /* Add new attributes if they don't exist already. */
    if (!attr_mP) {
      attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
      if (attr_N)
        attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);

      new_attribute = true;
    }
    /* Load vertex data from mesh. */
    float3 *mP = attr_mP->data_float3() + motion_step * numverts;
    float3 *mN = (attr_mN) ? attr_mN->data_float3() + motion_step * numverts : NULL;
    /* NOTE: We don't copy more that existing amount of vertices to prevent
     * possible memory corruption.
     */
    BL::Mesh::vertices_iterator v;
    int i = 0;
    for (b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) {
      mP[i] = get_float3(v->co());
      if (mN)
        mN[i] = get_float3(v->normal());
    }
    if (new_attribute) {
      /* In case of new attribute, we verify if there really was any motion. */
      if (b_mesh.vertices.length() != numverts ||
          memcmp(mP, &mesh->verts[0], sizeof(float3) * numverts) == 0) {
        /* no motion, remove attributes again */
        if (b_mesh.vertices.length() != numverts) {
          VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name();
        }
        else {
          VLOG(1) << "No actual deformation motion for object " << b_ob.name();
        }
        mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
        if (attr_mN)
          mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
      }
      else if (motion_step > 0) {
        VLOG(1) << "Filling deformation motion for object " << b_ob.name();
        /* motion, fill up previous steps that we might have skipped because
         * they had no motion, but we need them anyway now */
        float3 *P = &mesh->verts[0];
        float3 *N = (attr_N) ? attr_N->data_float3() : NULL;
        for (int step = 0; step < motion_step; step++) {
          memcpy(attr_mP->data_float3() + step * numverts, P, sizeof(float3) * numverts);
          if (attr_mN)
            memcpy(attr_mN->data_float3() + step * numverts, N, sizeof(float3) * numverts);
        }
      }
    }
    else {
      if (b_mesh.vertices.length() != numverts) {
        VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name()
                << " at time " << motion_step;
        memcpy(mP, &mesh->verts[0], sizeof(float3) * numverts);
        if (mN != NULL) {
          memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts);
        }
      }
    }
  }

  /* hair motion */
  if (numkeys)
    sync_curves(mesh, b_mesh, b_ob, true, motion_step);

  /* free derived mesh */
  free_object_to_mesh(b_data, b_ob, b_mesh);
}
예제 #23
0
static void attr_create_pointiness(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
{
  if (!mesh->need_attribute(scene, ATTR_STD_POINTINESS)) {
    return;
  }
  const int num_verts = b_mesh.vertices.length();
  if (num_verts == 0) {
    return;
  }
  /* STEP 1: Find out duplicated vertices and point duplicates to a single
   *         original vertex.
   */
  vector<int> sorted_vert_indeices(num_verts);
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    sorted_vert_indeices[vert_index] = vert_index;
  }
  VertexAverageComparator compare(mesh->verts);
  sort(sorted_vert_indeices.begin(), sorted_vert_indeices.end(), compare);
  /* This array stores index of the original vertex for the given vertex
   * index.
   */
  vector<int> vert_orig_index(num_verts);
  for (int sorted_vert_index = 0; sorted_vert_index < num_verts; ++sorted_vert_index) {
    const int vert_index = sorted_vert_indeices[sorted_vert_index];
    const float3 &vert_co = mesh->verts[vert_index];
    bool found = false;
    for (int other_sorted_vert_index = sorted_vert_index + 1; other_sorted_vert_index < num_verts;
         ++other_sorted_vert_index) {
      const int other_vert_index = sorted_vert_indeices[other_sorted_vert_index];
      const float3 &other_vert_co = mesh->verts[other_vert_index];
      /* We are too far away now, we wouldn't have duplicate. */
      if ((other_vert_co.x + other_vert_co.y + other_vert_co.z) -
              (vert_co.x + vert_co.y + vert_co.z) >
          3 * FLT_EPSILON) {
        break;
      }
      /* Found duplicate. */
      if (len_squared(other_vert_co - vert_co) < FLT_EPSILON) {
        found = true;
        vert_orig_index[vert_index] = other_vert_index;
        break;
      }
    }
    if (!found) {
      vert_orig_index[vert_index] = vert_index;
    }
  }
  /* Make sure we always points to the very first orig vertex. */
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    int orig_index = vert_orig_index[vert_index];
    while (orig_index != vert_orig_index[orig_index]) {
      orig_index = vert_orig_index[orig_index];
    }
    vert_orig_index[vert_index] = orig_index;
  }
  sorted_vert_indeices.free_memory();
  /* STEP 2: Calculate vertex normals taking into account their possible
   *         duplicates which gets "welded" together.
   */
  vector<float3> vert_normal(num_verts, make_float3(0.0f, 0.0f, 0.0f));
  /* First we accumulate all vertex normals in the original index. */
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    const float3 normal = get_float3(b_mesh.vertices[vert_index].normal());
    const int orig_index = vert_orig_index[vert_index];
    vert_normal[orig_index] += normal;
  }
  /* Then we normalize the accumulated result and flush it to all duplicates
   * as well.
   */
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    const int orig_index = vert_orig_index[vert_index];
    vert_normal[vert_index] = normalize(vert_normal[orig_index]);
  }
  /* STEP 3: Calculate pointiness using single ring neighborhood. */
  vector<int> counter(num_verts, 0);
  vector<float> raw_data(num_verts, 0.0f);
  vector<float3> edge_accum(num_verts, make_float3(0.0f, 0.0f, 0.0f));
  BL::Mesh::edges_iterator e;
  EdgeMap visited_edges;
  int edge_index = 0;
  memset(&counter[0], 0, sizeof(int) * counter.size());
  for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
    const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
              v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
    if (visited_edges.exists(v0, v1)) {
      continue;
    }
    visited_edges.insert(v0, v1);
    float3 co0 = get_float3(b_mesh.vertices[v0].co()), co1 = get_float3(b_mesh.vertices[v1].co());
    float3 edge = normalize(co1 - co0);
    edge_accum[v0] += edge;
    edge_accum[v1] += -edge;
    ++counter[v0];
    ++counter[v1];
  }
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    const int orig_index = vert_orig_index[vert_index];
    if (orig_index != vert_index) {
      /* Skip duplicates, they'll be overwritten later on. */
      continue;
    }
    if (counter[vert_index] > 0) {
      const float3 normal = vert_normal[vert_index];
      const float angle = safe_acosf(dot(normal, edge_accum[vert_index] / counter[vert_index]));
      raw_data[vert_index] = angle * M_1_PI_F;
    }
    else {
      raw_data[vert_index] = 0.0f;
    }
  }
  /* STEP 3: Blur vertices to approximate 2 ring neighborhood. */
  AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes;
  Attribute *attr = attributes.add(ATTR_STD_POINTINESS);
  float *data = attr->data_float();
  memcpy(data, &raw_data[0], sizeof(float) * raw_data.size());
  memset(&counter[0], 0, sizeof(int) * counter.size());
  edge_index = 0;
  visited_edges.clear();
  for (b_mesh.edges.begin(e); e != b_mesh.edges.end(); ++e, ++edge_index) {
    const int v0 = vert_orig_index[b_mesh.edges[edge_index].vertices()[0]],
              v1 = vert_orig_index[b_mesh.edges[edge_index].vertices()[1]];
    if (visited_edges.exists(v0, v1)) {
      continue;
    }
    visited_edges.insert(v0, v1);
    data[v0] += raw_data[v1];
    data[v1] += raw_data[v0];
    ++counter[v0];
    ++counter[v1];
  }
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    data[vert_index] /= counter[vert_index] + 1;
  }
  /* STEP 4: Copy attribute to the duplicated vertices. */
  for (int vert_index = 0; vert_index < num_verts; ++vert_index) {
    const int orig_index = vert_orig_index[vert_index];
    data[vert_index] = data[orig_index];
  }
}
static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::ShaderNode b_node)
{
	ShaderNode *node = NULL;

	/* existing blender nodes */
	if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
		BL::ShaderNodeRGBCurve b_curve_node(b_node);
		RGBCurvesNode *curves = new RGBCurvesNode();
		curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, true);
		node = curves;
	}
	if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
		BL::ShaderNodeVectorCurve b_curve_node(b_node);
		VectorCurvesNode *curves = new VectorCurvesNode();
		curvemapping_color_to_array(b_curve_node.mapping(), curves->curves, RAMP_TABLE_SIZE, false);
		node = curves;
	}
	else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
		RGBRampNode *ramp = new RGBRampNode();
		BL::ShaderNodeValToRGB b_ramp_node(b_node);
		colorramp_to_array(b_ramp_node.color_ramp(), ramp->ramp, RAMP_TABLE_SIZE);
		ramp->interpolate = b_ramp_node.color_ramp().interpolation() != BL::ColorRamp::interpolation_CONSTANT;
		node = ramp;
	}
	else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
		ColorNode *color = new ColorNode();
		color->value = get_node_output_rgba(b_node, "Color");
		node = color;
	}
	else if (b_node.is_a(&RNA_ShaderNodeValue)) {
		ValueNode *value = new ValueNode();
		value->value = get_node_output_value(b_node, "Value");
		node = value;
	}
	else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
		node = new CameraNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
		node = new InvertNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
		node = new GammaNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
		node = new BrightContrastNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
		BL::ShaderNodeMixRGB b_mix_node(b_node);
		MixNode *mix = new MixNode();
		mix->type = MixNode::type_enum[b_mix_node.blend_type()];
			mix->use_clamp = b_mix_node.use_clamp();
		node = mix;
	}
	else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
		node = new SeparateRGBNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
		node = new CombineRGBNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
		node = new SeparateHSVNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
		node = new CombineHSVNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
		node = new HSVNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
		node = new ConvertNode(SHADER_SOCKET_COLOR, SHADER_SOCKET_FLOAT);
	}
	else if (b_node.is_a(&RNA_ShaderNodeMath)) {
		BL::ShaderNodeMath b_math_node(b_node);
		MathNode *math = new MathNode();
		math->type = MathNode::type_enum[b_math_node.operation()];
			math->use_clamp = b_math_node.use_clamp();
		node = math;
	}
	else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
		BL::ShaderNodeVectorMath b_vector_math_node(b_node);
		VectorMathNode *vmath = new VectorMathNode();
		vmath->type = VectorMathNode::type_enum[b_vector_math_node.operation()];
		node = vmath;
	}
	else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
		BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
		VectorTransformNode *vtransform = new VectorTransformNode();
		vtransform->type = VectorTransformNode::type_enum[b_vector_transform_node.type()];
		vtransform->convert_from = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_from()];
		vtransform->convert_to = VectorTransformNode::convert_space_enum[b_vector_transform_node.convert_to()];
		node = vtransform;
	}
	else if (b_node.is_a(&RNA_ShaderNodeNormal)) {
		BL::Node::outputs_iterator out_it;
		b_node.outputs.begin(out_it);
		
		NormalNode *norm = new NormalNode();
		norm->direction = get_node_output_vector(b_node, "Normal");
		node = norm;
	}
	else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
		BL::ShaderNodeMapping b_mapping_node(b_node);
		MappingNode *mapping = new MappingNode();
		
		get_tex_mapping(&mapping->tex_mapping, b_mapping_node);
		
		node = mapping;
	}
	else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
		node = new FresnelNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
		node = new LayerWeightNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
		node = new AddClosureNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
		node = new MixClosureNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
		BL::ShaderNodeAttribute b_attr_node(b_node);
		AttributeNode *attr = new AttributeNode();
		attr->attribute = b_attr_node.attribute_name();
		node = attr;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
		node = new BackgroundNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
		node = new HoldoutNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
		node = new WardBsdfNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
		node = new DiffuseBsdfNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
		BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);

		SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();

		switch(b_subsurface_node.falloff()) {
		case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
			subsurface->closure = CLOSURE_BSSRDF_CUBIC_ID;
			break;
		case BL::ShaderNodeSubsurfaceScattering::falloff_GAUSSIAN:
			subsurface->closure = CLOSURE_BSSRDF_GAUSSIAN_ID;
			break;
		}

		node = subsurface;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
		BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
		GlossyBsdfNode *glossy = new GlossyBsdfNode();
		
		switch(b_glossy_node.distribution()) {
		case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
			glossy->distribution = ustring("Sharp");
			break;
		case BL::ShaderNodeBsdfGlossy::distribution_BECKMANN:
			glossy->distribution = ustring("Beckmann");
			break;
		case BL::ShaderNodeBsdfGlossy::distribution_GGX:
			glossy->distribution = ustring("GGX");
			break;
		}
		node = glossy;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
		BL::ShaderNodeBsdfGlass b_glass_node(b_node);
		GlassBsdfNode *glass = new GlassBsdfNode();
		switch(b_glass_node.distribution()) {
		case BL::ShaderNodeBsdfGlass::distribution_SHARP:
			glass->distribution = ustring("Sharp");
			break;
		case BL::ShaderNodeBsdfGlass::distribution_BECKMANN:
			glass->distribution = ustring("Beckmann");
			break;
		case BL::ShaderNodeBsdfGlass::distribution_GGX:
			glass->distribution = ustring("GGX");
			break;
		}
		node = glass;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
		BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
		RefractionBsdfNode *refraction = new RefractionBsdfNode();
		switch(b_refraction_node.distribution()) {
			case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
				refraction->distribution = ustring("Sharp");
				break;
			case BL::ShaderNodeBsdfRefraction::distribution_BECKMANN:
				refraction->distribution = ustring("Beckmann");
				break;
			case BL::ShaderNodeBsdfRefraction::distribution_GGX:
				refraction->distribution = ustring("GGX");
				break;
		}
		node = refraction;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
		BL::ShaderNodeBsdfToon b_toon_node(b_node);
		ToonBsdfNode *toon = new ToonBsdfNode();
		switch(b_toon_node.component()) {
			case BL::ShaderNodeBsdfToon::component_DIFFUSE:
				toon->component = ustring("Diffuse");
				break;
			case BL::ShaderNodeBsdfToon::component_GLOSSY:
				toon->component = ustring("Glossy");
				break;
		}
		node = toon;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
		BL::ShaderNodeBsdfHair b_hair_node(b_node);
		HairBsdfNode *hair = new HairBsdfNode();
		switch(b_hair_node.component()) {
			case BL::ShaderNodeBsdfHair::component_Reflection:
				hair->component = ustring("Reflection");
				break;
			case BL::ShaderNodeBsdfHair::component_Transmission:
				hair->component = ustring("Transmission");
				break;
		}
		node = hair;
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
		node = new TranslucentBsdfNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
		node = new TransparentBsdfNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
		node = new VelvetBsdfNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
		node = new EmissionNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
		node = new AmbientOcclusionNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
		node = new ScatterVolumeNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
		node = new AbsorptionVolumeNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
		node = new GeometryNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
		BL::ShaderNodeWireframe b_wireframe_node(b_node);
		WireframeNode *wire = new WireframeNode();
		wire->use_pixel_size = b_wireframe_node.use_pixel_size();
		node = wire;
	}
	else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
		node = new WavelengthNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) {
		node = new BlackbodyNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
		node = new LightPathNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
		node = new LightFalloffNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
		node = new ObjectInfoNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
		node = new ParticleInfoNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
		node = new HairInfoNode();
	}
	else if (b_node.is_a(&RNA_ShaderNodeBump)) {
		BL::ShaderNodeBump b_bump_node(b_node);
		BumpNode *bump = new BumpNode();
		bump->invert = b_bump_node.invert();
		node = bump;
	}
	else if (b_node.is_a(&RNA_ShaderNodeScript)) {
#ifdef WITH_OSL
		if(scene->shader_manager->use_osl()) {
			/* create script node */
			BL::ShaderNodeScript b_script_node(b_node);
			OSLScriptNode *script_node = new OSLScriptNode();
			
			/* Generate inputs/outputs from node sockets
			 *
			 * Note: the node sockets are generated from OSL parameters,
			 * so the names match those of the corresponding parameters exactly.
			 *
			 * Note 2: ShaderInput/ShaderOutput store shallow string copies only!
			 * Socket names must be stored in the extra lists instead. */
			BL::Node::inputs_iterator b_input;
			
			for (b_script_node.inputs.begin(b_input); b_input != b_script_node.inputs.end(); ++b_input) {
				script_node->input_names.push_back(ustring(b_input->name()));
				ShaderInput *input = script_node->add_input(script_node->input_names.back().c_str(),
				                                            convert_socket_type(*b_input));
				set_default_value(input, b_node, *b_input, b_data, b_ntree);
			}
			
			BL::Node::outputs_iterator b_output;
			
			for (b_script_node.outputs.begin(b_output); b_output != b_script_node.outputs.end(); ++b_output) {
				script_node->output_names.push_back(ustring(b_output->name()));
				script_node->add_output(script_node->output_names.back().c_str(),
				                        convert_socket_type(*b_output));
			}
			
			/* load bytecode or filepath */
			OSLShaderManager *manager = (OSLShaderManager*)scene->shader_manager;
			string bytecode_hash = b_script_node.bytecode_hash();
			
			if(!bytecode_hash.empty()) {
				/* loaded bytecode if not already done */
				if(!manager->shader_test_loaded(bytecode_hash))
					manager->shader_load_bytecode(bytecode_hash, b_script_node.bytecode());
				
				script_node->bytecode_hash = bytecode_hash;
			}
			else {
				/* set filepath */
				script_node->filepath = blender_absolute_path(b_data, b_ntree, b_script_node.filepath());
			}
			
			node = script_node;
		}
#endif
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexImage)) {
		BL::ShaderNodeTexImage b_image_node(b_node);
		BL::Image b_image(b_image_node.image());
		ImageTextureNode *image = new ImageTextureNode();
		if(b_image) {
			/* builtin images will use callback-based reading because
			 * they could only be loaded correct from blender side
			 */
			bool is_builtin = b_image.packed_file() ||
			                  b_image.source() == BL::Image::source_GENERATED ||
			                  b_image.source() == BL::Image::source_MOVIE;

			if(is_builtin) {
				/* for builtin images we're using image datablock name to find an image to
				 * read pixels from later
				 *
				 * also store frame number as well, so there's no differences in handling
				 * builtin names for packed images and movies
				 */
				int scene_frame = b_scene.frame_current();
				int image_frame = image_user_frame_number(b_image_node.image_user(), scene_frame);
				image->filename = b_image.name() + "@" + string_printf("%d", image_frame);
				image->builtin_data = b_image.ptr.data;
			}
			else {
				image->filename = image_user_file_path(b_image_node.image_user(), b_image, b_scene.frame_current());
				image->builtin_data = NULL;
			}

			image->animated = b_image_node.image_user().use_auto_refresh();
		}
		image->color_space = ImageTextureNode::color_space_enum[(int)b_image_node.color_space()];
		image->projection = ImageTextureNode::projection_enum[(int)b_image_node.projection()];
		image->projection_blend = b_image_node.projection_blend();
		get_tex_mapping(&image->tex_mapping, b_image_node.texture_mapping());
		node = image;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexEnvironment)) {
		BL::ShaderNodeTexEnvironment b_env_node(b_node);
		BL::Image b_image(b_env_node.image());
		EnvironmentTextureNode *env = new EnvironmentTextureNode();
		if(b_image) {
			bool is_builtin = b_image.packed_file() ||
			                  b_image.source() == BL::Image::source_GENERATED ||
			                  b_image.source() == BL::Image::source_MOVIE;

			if(is_builtin) {
				int scene_frame = b_scene.frame_current();
				int image_frame = image_user_frame_number(b_env_node.image_user(), scene_frame);
				env->filename = b_image.name() + "@" + string_printf("%d", image_frame);
				env->builtin_data = b_image.ptr.data;
			}
			else {
				env->filename = image_user_file_path(b_env_node.image_user(), b_image, b_scene.frame_current());
				env->animated = b_env_node.image_user().use_auto_refresh();
				env->builtin_data = NULL;
			}
		}
		env->color_space = EnvironmentTextureNode::color_space_enum[(int)b_env_node.color_space()];
		env->projection = EnvironmentTextureNode::projection_enum[(int)b_env_node.projection()];
		get_tex_mapping(&env->tex_mapping, b_env_node.texture_mapping());
		node = env;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
		BL::ShaderNodeTexGradient b_gradient_node(b_node);
		GradientTextureNode *gradient = new GradientTextureNode();
		gradient->type = GradientTextureNode::type_enum[(int)b_gradient_node.gradient_type()];
		get_tex_mapping(&gradient->tex_mapping, b_gradient_node.texture_mapping());
		node = gradient;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
		BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
		VoronoiTextureNode *voronoi = new VoronoiTextureNode();
		voronoi->coloring = VoronoiTextureNode::coloring_enum[(int)b_voronoi_node.coloring()];
		get_tex_mapping(&voronoi->tex_mapping, b_voronoi_node.texture_mapping());
		node = voronoi;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
		BL::ShaderNodeTexMagic b_magic_node(b_node);
		MagicTextureNode *magic = new MagicTextureNode();
		magic->depth = b_magic_node.turbulence_depth();
		get_tex_mapping(&magic->tex_mapping, b_magic_node.texture_mapping());
		node = magic;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
		BL::ShaderNodeTexWave b_wave_node(b_node);
		WaveTextureNode *wave = new WaveTextureNode();
		wave->type = WaveTextureNode::type_enum[(int)b_wave_node.wave_type()];
		get_tex_mapping(&wave->tex_mapping, b_wave_node.texture_mapping());
		node = wave;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
		BL::ShaderNodeTexChecker b_checker_node(b_node);
		CheckerTextureNode *checker = new CheckerTextureNode();
		get_tex_mapping(&checker->tex_mapping, b_checker_node.texture_mapping());
		node = checker;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
		BL::ShaderNodeTexBrick b_brick_node(b_node);
		BrickTextureNode *brick = new BrickTextureNode();
		brick->offset = b_brick_node.offset();
		brick->offset_frequency = b_brick_node.offset_frequency();
		brick->squash = b_brick_node.squash();
		brick->squash_frequency = b_brick_node.squash_frequency();
		get_tex_mapping(&brick->tex_mapping, b_brick_node.texture_mapping());
		node = brick;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
		BL::ShaderNodeTexNoise b_noise_node(b_node);
		NoiseTextureNode *noise = new NoiseTextureNode();
		get_tex_mapping(&noise->tex_mapping, b_noise_node.texture_mapping());
		node = noise;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
		BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
		MusgraveTextureNode *musgrave = new MusgraveTextureNode();
		musgrave->type = MusgraveTextureNode::type_enum[(int)b_musgrave_node.musgrave_type()];
		get_tex_mapping(&musgrave->tex_mapping, b_musgrave_node.texture_mapping());
		node = musgrave;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
		BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
		TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
		tex_coord->from_dupli = b_tex_coord_node.from_dupli();
		node = tex_coord;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
		BL::ShaderNodeTexSky b_sky_node(b_node);
		SkyTextureNode *sky = new SkyTextureNode();
		sky->type = SkyTextureNode::type_enum[(int)b_sky_node.sky_type()];
		sky->sun_direction = get_float3(b_sky_node.sun_direction());
		sky->turbidity = b_sky_node.turbidity();
		sky->ground_albedo = b_sky_node.ground_albedo();
		get_tex_mapping(&sky->tex_mapping, b_sky_node.texture_mapping());
		node = sky;
	}
	else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
		BL::ShaderNodeNormalMap b_normal_map_node(b_node);
		NormalMapNode *nmap = new NormalMapNode();
		nmap->space = NormalMapNode::space_enum[(int)b_normal_map_node.space()];
		nmap->attribute = b_normal_map_node.uv_map();
		node = nmap;
	}
	else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
		BL::ShaderNodeTangent b_tangent_node(b_node);
		TangentNode *tangent = new TangentNode();
		tangent->direction_type = TangentNode::direction_type_enum[(int)b_tangent_node.direction_type()];
		tangent->axis = TangentNode::axis_enum[(int)b_tangent_node.axis()];
		tangent->attribute = b_tangent_node.uv_map();
		node = tangent;
	}

	if(node)
		graph->add(node);

	return node;
}
예제 #25
0
/* Create uv map attributes. */
static void attr_create_uv_map(Scene *scene,
                               Mesh *mesh,
                               BL::Mesh& b_mesh,
                               const vector<int>& nverts,
                               const vector<int>& face_flags)
{
	if(b_mesh.tessface_uv_textures.length() != 0) {
		BL::Mesh::tessface_uv_textures_iterator l;

		for(b_mesh.tessface_uv_textures.begin(l); l != b_mesh.tessface_uv_textures.end(); ++l) {
			bool active_render = l->active_render();
			AttributeStandard std = (active_render)? ATTR_STD_UV: ATTR_STD_NONE;
			ustring name = ustring(l->name().c_str());

			/* UV map */
			if(mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std)) {
				Attribute *attr;

				if(active_render)
					attr = mesh->attributes.add(std, name);
				else
					attr = mesh->attributes.add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CORNER);

				BL::MeshTextureFaceLayer::data_iterator t;
				float3 *fdata = attr->data_float3();
				size_t i = 0;

				for(l->data.begin(t); t != l->data.end(); ++t, ++i) {
					int tri_a[3], tri_b[3];
					face_split_tri_indices(nverts[i], face_flags[i], tri_a, tri_b);

					float3 uvs[4];
					uvs[0] = get_float3(t->uv1());
					uvs[1] = get_float3(t->uv2());
					uvs[2] = get_float3(t->uv3());
					if(nverts[i] == 4) {
						uvs[3] = get_float3(t->uv4());
					}

					fdata[0] = uvs[tri_a[0]];
					fdata[1] = uvs[tri_a[1]];
					fdata[2] = uvs[tri_a[2]];
					fdata += 3;

					if(nverts[i] == 4) {
						fdata[0] = uvs[tri_b[0]];
						fdata[1] = uvs[tri_b[1]];
						fdata[2] = uvs[tri_b[2]];
						fdata += 3;
					}
				}
			}

			/* UV tangent */
			std = (active_render)? ATTR_STD_UV_TANGENT: ATTR_STD_NONE;
			name = ustring((string(l->name().c_str()) + ".tangent").c_str());

			if(mesh->need_attribute(scene, name) || (active_render && mesh->need_attribute(scene, std))) {
				std = (active_render)? ATTR_STD_UV_TANGENT_SIGN: ATTR_STD_NONE;
				name = ustring((string(l->name().c_str()) + ".tangent_sign").c_str());
				bool need_sign = (mesh->need_attribute(scene, name) || mesh->need_attribute(scene, std));

				mikk_compute_tangents(b_mesh,
				                      &(*l),
				                      mesh,
				                      nverts,
				                      face_flags,
				                      need_sign,
				                      active_render);
			}
		}
	}
	else if(mesh->need_attribute(scene, ATTR_STD_UV_TANGENT)) {
		bool need_sign = mesh->need_attribute(scene, ATTR_STD_UV_TANGENT_SIGN);
		mikk_compute_tangents(b_mesh,
		                      NULL,
		                      mesh,
		                      nverts,
		                      face_flags,
		                      need_sign,
		                      true);
	}
}
예제 #26
0
Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
                                 BL::ViewLayer &b_view_layer,
                                 BL::DepsgraphObjectInstance &b_instance,
                                 float motion_time,
                                 bool show_self,
                                 bool show_particles,
                                 BlenderObjectCulling &culling,
                                 bool *use_portal)
{
  const bool is_instance = b_instance.is_instance();
  BL::Object b_ob = b_instance.object();
  BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object();
  BL::Object b_ob_instance = is_instance ? b_instance.instance_object() : b_ob;
  const bool motion = motion_time != 0.0f;
  /*const*/ Transform tfm = get_transform(b_ob.matrix_world());
  int *persistent_id = NULL;
  BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id_array;
  if (is_instance) {
    persistent_id_array = b_instance.persistent_id();
    persistent_id = persistent_id_array.data;
  }

  /* light is handled separately */
  if (!motion && object_is_light(b_ob)) {
    /* TODO: don't use lights for excluded layers used as mask layer,
     * when dynamic overrides are back. */
#if 0
    if (!((layer_flag & view_layer.holdout_layer) && (layer_flag & view_layer.exclude_layer)))
#endif
    {
      sync_light(b_parent,
                 persistent_id,
                 b_ob,
                 b_ob_instance,
                 is_instance ? b_instance.random_id() : 0,
                 tfm,
                 use_portal);
    }

    return NULL;
  }

  /* only interested in object that we can create meshes from */
  if (!object_is_mesh(b_ob)) {
    return NULL;
  }

  /* Perform object culling. */
  if (culling.test(scene, b_ob, tfm)) {
    return NULL;
  }

  /* Visibility flags for both parent and child. */
  PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
  bool use_holdout = get_boolean(cobject, "is_holdout") ||
                     b_parent.holdout_get(PointerRNA_NULL, b_view_layer);
  uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;

  if (b_parent.ptr.data != b_ob.ptr.data) {
    visibility &= object_ray_visibility(b_parent);
  }

  /* TODO: make holdout objects on excluded layer invisible for non-camera rays. */
#if 0
  if (use_holdout && (layer_flag & view_layer.exclude_layer)) {
    visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);
  }
#endif

  /* Clear camera visibility for indirect only objects. */
  bool use_indirect_only = b_parent.indirect_only_get(PointerRNA_NULL, b_view_layer);
  if (use_indirect_only) {
    visibility &= ~PATH_RAY_CAMERA;
  }

  /* Don't export completely invisible objects. */
  if (visibility == 0) {
    return NULL;
  }

  /* key to lookup object */
  ObjectKey key(b_parent, persistent_id, b_ob_instance);
  Object *object;

  /* motion vector case */
  if (motion) {
    object = object_map.find(key);

    if (object && object->use_motion()) {
      /* Set transform at matching motion time step. */
      int time_index = object->motion_step(motion_time);
      if (time_index >= 0) {
        object->motion[time_index] = tfm;
      }

      /* mesh deformation */
      if (object->mesh)
        sync_mesh_motion(b_depsgraph, b_ob, object, motion_time);
    }

    return object;
  }

  /* test if we need to sync */
  bool object_updated = false;

  if (object_map.sync(&object, b_ob, b_parent, key))
    object_updated = true;

  /* mesh sync */
  object->mesh = sync_mesh(
      b_depsgraph, b_ob, b_ob_instance, object_updated, show_self, show_particles);

  /* special case not tracked by object update flags */

  /* holdout */
  if (use_holdout != object->use_holdout) {
    object->use_holdout = use_holdout;
    scene->object_manager->tag_update(scene);
    object_updated = true;
  }

  if (visibility != object->visibility) {
    object->visibility = visibility;
    object_updated = true;
  }

  bool is_shadow_catcher = get_boolean(cobject, "is_shadow_catcher");
  if (is_shadow_catcher != object->is_shadow_catcher) {
    object->is_shadow_catcher = is_shadow_catcher;
    object_updated = true;
  }

  /* sync the asset name for Cryptomatte */
  BL::Object parent = b_ob.parent();
  ustring parent_name;
  if (parent) {
    while (parent.parent()) {
      parent = parent.parent();
    }
    parent_name = parent.name();
  }
  else {
    parent_name = b_ob.name();
  }
  if (object->asset_name != parent_name) {
    object->asset_name = parent_name;
    object_updated = true;
  }

  /* object sync
   * transform comparison should not be needed, but duplis don't work perfect
   * in the depsgraph and may not signal changes, so this is a workaround */
  if (object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
    object->name = b_ob.name().c_str();
    object->pass_id = b_ob.pass_index();
    object->tfm = tfm;
    object->motion.clear();

    /* motion blur */
    Scene::MotionType need_motion = scene->need_motion();
    if (need_motion != Scene::MOTION_NONE && object->mesh) {
      Mesh *mesh = object->mesh;
      mesh->use_motion_blur = false;
      mesh->motion_steps = 0;

      uint motion_steps;

      if (need_motion == Scene::MOTION_BLUR) {
        motion_steps = object_motion_steps(b_parent, b_ob);
        mesh->motion_steps = motion_steps;
        if (motion_steps && object_use_deform_motion(b_parent, b_ob)) {
          mesh->use_motion_blur = true;
        }
      }
      else {
        motion_steps = 3;
        mesh->motion_steps = motion_steps;
      }

      object->motion.clear();
      object->motion.resize(motion_steps, transform_empty());

      if (motion_steps) {
        object->motion[motion_steps / 2] = tfm;

        for (size_t step = 0; step < motion_steps; step++) {
          motion_times.insert(object->motion_time(step));
        }
      }
    }

    /* dupli texture coordinates and random_id */
    if (is_instance) {
      object->dupli_generated = 0.5f * get_float3(b_instance.orco()) -
                                make_float3(0.5f, 0.5f, 0.5f);
      object->dupli_uv = get_float2(b_instance.uv());
      object->random_id = b_instance.random_id();
    }
    else {
      object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
      object->dupli_uv = make_float2(0.0f, 0.0f);
      object->random_id = hash_int_2d(hash_string(object->name.c_str()), 0);
    }

    object->tag_update(scene);
  }

  if (is_instance) {
    /* Sync possible particle data. */
    sync_dupli_particle(b_parent, b_instance, object);
  }

  return object;
}
void BlenderSync::sync_world(bool update_all)
{
	Background *background = scene->background;
	Background prevbackground = *background;

	BL::World b_world = b_scene.world();

	if(world_recalc || update_all || b_world.ptr.data != world_map) {
		Shader *shader = scene->shaders[scene->default_background];
		ShaderGraph *graph = new ShaderGraph();

		/* create nodes */
		if(b_world && b_world.use_nodes() && b_world.node_tree()) {
			BL::ShaderNodeTree b_ntree(b_world.node_tree());

			add_nodes(scene, b_data, b_scene, graph, b_ntree);
			
			/* volume */
			PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
			shader->heterogeneous_volume = !get_boolean(cworld, "homogeneous_volume");
		}
		else if(b_world) {
			ShaderNode *closure, *out;

			closure = graph->add(new BackgroundNode());
			closure->input("Color")->value = get_float3(b_world.horizon_color());
			out = graph->output();

			graph->connect(closure->output("Background"), out->input("Surface"));
		}

		if(b_world) {
			/* AO */
			BL::WorldLighting b_light = b_world.light_settings();

			if(b_light.use_ambient_occlusion())
				background->ao_factor = b_light.ao_factor();
			else
				background->ao_factor = 0.0f;

			background->ao_distance = b_light.distance();

			/* visibility */
			PointerRNA cvisibility = RNA_pointer_get(&b_world.ptr, "cycles_visibility");
			uint visibility = 0;

			visibility |= get_boolean(cvisibility, "camera")? PATH_RAY_CAMERA: 0;
			visibility |= get_boolean(cvisibility, "diffuse")? PATH_RAY_DIFFUSE: 0;
			visibility |= get_boolean(cvisibility, "glossy")? PATH_RAY_GLOSSY: 0;
			visibility |= get_boolean(cvisibility, "transmission")? PATH_RAY_TRANSMIT: 0;

			background->visibility = visibility;
		}

		shader->set_graph(graph);
		shader->tag_update(scene);
		background->tag_update(scene);
	}

	PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");

	/* when doing preview render check for BI's transparency settings,
	 * this is so because bledner's preview render routines are not able
	 * to tweak all cycles's settings depending on different circumstances
	 */
	if(b_engine.is_preview() == false)
		background->transparent = get_boolean(cscene, "film_transparent");
	else
		background->transparent = b_scene.render().alpha_mode() == BL::RenderSettings::alpha_mode_TRANSPARENT;

	background->use = render_layer.use_background;

	if(background->modified(prevbackground))
		background->tag_update(scene);
}
예제 #28
0
Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, bool hide_tris)
{
	BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
	
	/* light is handled separately */
	if(object_is_light(b_ob)) {
		/* don't use lamps for excluded layers used as mask layer */
		if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer)))
			sync_light(b_parent, persistent_id, b_ob, tfm);

		return NULL;
	}

	/* only interested in object that we can create meshes from */
	if(!object_is_mesh(b_ob))
		return NULL;

	/* key to lookup object */
	ObjectKey key(b_parent, persistent_id, b_ob);
	Object *object;

	/* motion vector case */
	if(motion) {
		object = object_map.find(key);

		if(object) {
			if(tfm != object->tfm) {
				if(motion == -1)
					object->motion.pre = tfm;
				else
					object->motion.post = tfm;

				object->use_motion = true;
			}

			/* mesh deformation blur not supported yet */
			if(!scene->integrator->motion_blur)
				sync_mesh_motion(b_ob, object->mesh, motion);
		}

		return object;
	}

	/* test if we need to sync */
	bool object_updated = false;

	if(object_map.sync(&object, b_ob, b_parent, key))
		object_updated = true;
	
	bool use_holdout = (layer_flag & render_layer.holdout_layer) != 0;
	
	/* mesh sync */
	object->mesh = sync_mesh(b_ob, object_updated, hide_tris);

	/* special case not tracked by object update flags */

	/* holdout */
	if(use_holdout != object->use_holdout) {
		object->use_holdout = use_holdout;
		scene->object_manager->tag_update(scene);
		object_updated = true;
	}

	/* visibility flags for both parent and child */
	uint visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL_VISIBILITY;
	if(b_parent.ptr.data != b_ob.ptr.data) {
		visibility &= object_ray_visibility(b_parent);
		object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));
	}

	/* make holdout objects on excluded layer invisible for non-camera rays */
	if(use_holdout && (layer_flag & render_layer.exclude_layer))
		visibility &= ~(PATH_RAY_ALL_VISIBILITY - PATH_RAY_CAMERA);

	/* camera flag is not actually used, instead is tested against render layer
	 * flags */
	if(visibility & PATH_RAY_CAMERA) {
		visibility |= layer_flag << PATH_RAY_LAYER_SHIFT;
		visibility &= ~PATH_RAY_CAMERA;
	}

	if(visibility != object->visibility) {
		object->visibility = visibility;
		object_updated = true;
	}

	/* object sync
	 * transform comparison should not be needed, but duplis don't work perfect
	 * in the depsgraph and may not signal changes, so this is a workaround */
	if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) {
		object->name = b_ob.name().c_str();
		object->pass_id = b_ob.pass_index();
		object->tfm = tfm;
		object->motion.pre = tfm;
		object->motion.post = tfm;
		object->use_motion = false;

		/* random number */
		object->random_id = hash_string(object->name.c_str());

		if(persistent_id) {
			for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++)
				object->random_id = hash_int_2d(object->random_id, persistent_id[i]);
		}
		else
			object->random_id = hash_int_2d(object->random_id, 0);

		if(b_parent.ptr.data != b_ob.ptr.data)
			object->random_id ^= hash_int(hash_string(b_parent.name().c_str()));

		/* dupli texture coordinates */
		if (b_dupli_ob) {
			object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f);
			object->dupli_uv = get_float2(b_dupli_ob.uv());
		}
		else {
			object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f);
			object->dupli_uv = make_float2(0.0f, 0.0f);
		}

		object->tag_update(scene);
	}

	return object;
}