예제 #1
0
  MikkUserData(const BL::Mesh &b_mesh,
               const char *layer_name,
               const Mesh *mesh,
               float3 *tangent,
               float *tangent_sign)
      : mesh(mesh), texface(NULL), orco(NULL), tangent(tangent), tangent_sign(tangent_sign)
  {
    const AttributeSet &attributes = (mesh->subd_faces.size()) ? mesh->subd_attributes :
                                                                 mesh->attributes;

    Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
    vertex_normal = attr_vN->data_float3();

    if (layer_name == NULL) {
      Attribute *attr_orco = attributes.find(ATTR_STD_GENERATED);

      if (attr_orco) {
        orco = attr_orco->data_float3();
        mesh_texture_space(*(BL::Mesh *)&b_mesh, orco_loc, orco_size);
      }
    }
    else {
      Attribute *attr_uv = attributes.find(ustring(layer_name));
      if (attr_uv != NULL) {
        texface = attr_uv->data_float2();
      }
    }
  }
예제 #2
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);
  }
}
예제 #3
0
void BlenderSync::sync_curves(
    Mesh *mesh, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step)
{
  if (!motion) {
    /* Clear stored curve data */
    mesh->curve_keys.clear();
    mesh->curve_radius.clear();
    mesh->curve_first_key.clear();
    mesh->curve_shader.clear();
    mesh->curve_attributes.clear();
  }

  /* obtain general settings */
  const bool use_curves = scene->curve_system_manager->use_curves;

  if (!(use_curves && b_ob.mode() != b_ob.mode_PARTICLE_EDIT && b_ob.mode() != b_ob.mode_EDIT)) {
    if (!motion)
      mesh->compute_bounds();
    return;
  }

  const int primitive = scene->curve_system_manager->primitive;
  const int triangle_method = scene->curve_system_manager->triangle_method;
  const int resolution = scene->curve_system_manager->resolution;
  const size_t vert_num = mesh->verts.size();
  const size_t tri_num = mesh->num_triangles();
  int used_res = 1;

  /* extract particle hair data - should be combined with connecting to mesh later*/

  ParticleCurveData CData;

  ObtainCacheParticleData(mesh, &b_mesh, &b_ob, &CData, !preview);

  /* add hair geometry to mesh */
  if (primitive == CURVE_TRIANGLES) {
    if (triangle_method == CURVE_CAMERA_TRIANGLES) {
      /* obtain camera parameters */
      float3 RotCam;
      Camera *camera = scene->camera;
      Transform &ctfm = camera->matrix;
      if (camera->type == CAMERA_ORTHOGRAPHIC) {
        RotCam = -make_float3(ctfm.x.z, ctfm.y.z, ctfm.z.z);
      }
      else {
        Transform tfm = get_transform(b_ob.matrix_world());
        Transform itfm = transform_quick_inverse(tfm);
        RotCam = transform_point(&itfm, make_float3(ctfm.x.w, ctfm.y.w, ctfm.z.w));
      }
      bool is_ortho = camera->type == CAMERA_ORTHOGRAPHIC;
      ExportCurveTrianglePlanes(mesh, &CData, RotCam, is_ortho);
    }
    else {
      ExportCurveTriangleGeometry(mesh, &CData, resolution);
      used_res = resolution;
    }
  }
  else {
    if (motion)
      ExportCurveSegmentsMotion(mesh, &CData, motion_step);
    else
      ExportCurveSegments(scene, mesh, &CData);
  }

  /* generated coordinates from first key. we should ideally get this from
   * blender to handle deforming objects */
  if (!motion) {
    if (mesh->need_attribute(scene, ATTR_STD_GENERATED)) {
      float3 loc, size;
      mesh_texture_space(b_mesh, loc, size);

      if (primitive == CURVE_TRIANGLES) {
        Attribute *attr_generated = mesh->attributes.add(ATTR_STD_GENERATED);
        float3 *generated = attr_generated->data_float3();

        for (size_t i = vert_num; i < mesh->verts.size(); i++)
          generated[i] = mesh->verts[i] * size - loc;
      }
      else {
        Attribute *attr_generated = mesh->curve_attributes.add(ATTR_STD_GENERATED);
        float3 *generated = attr_generated->data_float3();

        for (size_t i = 0; i < mesh->num_curves(); i++) {
          float3 co = mesh->curve_keys[mesh->get_curve(i).first_key];
          generated[i] = co * size - loc;
        }
      }
    }
  }

  /* create vertex color attributes */
  if (!motion) {
    BL::Mesh::vertex_colors_iterator l;
    int vcol_num = 0;

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

      ObtainCacheParticleVcol(mesh, &b_mesh, &b_ob, &CData, !preview, vcol_num);

      if (primitive == CURVE_TRIANGLES) {
        Attribute *attr_vcol = mesh->attributes.add(
            ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CORNER_BYTE);

        uchar4 *cdata = attr_vcol->data_uchar4();

        ExportCurveTriangleVcol(&CData, tri_num * 3, used_res, cdata);
      }
      else {
        Attribute *attr_vcol = mesh->curve_attributes.add(
            ustring(l->name().c_str()), TypeDesc::TypeColor, ATTR_ELEMENT_CURVE);

        float3 *fdata = attr_vcol->data_float3();

        if (fdata) {
          size_t i = 0;

          /* Encode vertex color using the sRGB curve. */
          for (size_t curve = 0; curve < CData.curve_vcol.size(); curve++) {
            fdata[i++] = color_srgb_to_linear_v3(CData.curve_vcol[curve]);
          }
        }
      }
    }
  }

  /* create UV attributes */
  if (!motion) {
    BL::Mesh::uv_layers_iterator l;
    int uv_num = 0;

    for (b_mesh.uv_layers.begin(l); l != b_mesh.uv_layers.end(); ++l, uv_num++) {
      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_uv;

        ObtainCacheParticleUV(mesh, &b_mesh, &b_ob, &CData, !preview, uv_num);

        if (primitive == CURVE_TRIANGLES) {
          if (active_render)
            attr_uv = mesh->attributes.add(std, name);
          else
            attr_uv = mesh->attributes.add(name, TypeFloat2, ATTR_ELEMENT_CORNER);

          float2 *uv = attr_uv->data_float2();

          ExportCurveTriangleUV(&CData, tri_num * 3, used_res, uv);
        }
        else {
          if (active_render)
            attr_uv = mesh->curve_attributes.add(std, name);
          else
            attr_uv = mesh->curve_attributes.add(name, TypeFloat2, ATTR_ELEMENT_CURVE);

          float2 *uv = attr_uv->data_float2();

          if (uv) {
            size_t i = 0;

            for (size_t curve = 0; curve < CData.curve_uv.size(); curve++) {
              uv[i++] = CData.curve_uv[curve];
            }
          }
        }
      }
    }
  }

  mesh->compute_bounds();
}
예제 #4
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);
	}
}
예제 #5
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);
	}
}
예제 #6
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);
	}
}