Exemple #1
0
static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, int curvekey)
{
  const float3 ickey_loc = CData->curvekey_co[curvekey];
  const float curve_time = CData->curvekey_time[curvekey];
  const float curve_length = CData->curve_length[curve];
  float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
  float radius = shaperadius(
      CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);

  if (CData->psys_closetip[sys] &&
      (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
    radius = 0.0f;

  /* curve motion keys store both position and radius in float4 */
  float4 mP = float3_to_float4(ickey_loc);
  mP.w = radius;
  return mP;
}
Exemple #2
0
static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData)
{
  int num_keys = 0;
  int num_curves = 0;

  if (mesh->num_curves())
    return;

  Attribute *attr_intercept = NULL;
  Attribute *attr_random = NULL;

  if (mesh->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT))
    attr_intercept = mesh->curve_attributes.add(ATTR_STD_CURVE_INTERCEPT);
  if (mesh->need_attribute(scene, ATTR_STD_CURVE_RANDOM))
    attr_random = mesh->curve_attributes.add(ATTR_STD_CURVE_RANDOM);

  /* compute and reserve size of arrays */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      num_keys += CData->curve_keynum[curve];
      num_curves++;
    }
  }

  if (num_curves > 0) {
    VLOG(1) << "Exporting curve segments for mesh " << mesh->name;
  }

  mesh->reserve_curves(mesh->num_curves() + num_curves, mesh->curve_keys.size() + num_keys);

  num_keys = 0;
  num_curves = 0;

  /* actually export */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      size_t num_curve_keys = 0;

      for (int curvekey = CData->curve_firstkey[curve];
           curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
           curvekey++) {
        const float3 ickey_loc = CData->curvekey_co[curvekey];
        const float curve_time = CData->curvekey_time[curvekey];
        const float curve_length = CData->curve_length[curve];
        const float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
        float radius = shaperadius(
            CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);
        if (CData->psys_closetip[sys] &&
            (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) {
          radius = 0.0f;
        }
        mesh->add_curve_key(ickey_loc, radius);
        if (attr_intercept)
          attr_intercept->add(time);

        num_curve_keys++;
      }

      if (attr_random != NULL) {
        attr_random->add(hash_int_01(num_curves));
      }

      mesh->add_curve(num_keys, CData->psys_shader[sys]);
      num_keys += num_curve_keys;
      num_curves++;
    }
  }

  /* check allocation */
  if ((mesh->curve_keys.size() != num_keys) || (mesh->num_curves() != num_curves)) {
    VLOG(1) << "Allocation failed, clearing data";
    mesh->clear();
  }
}
Exemple #3
0
static void ExportCurveTrianglePlanes(Mesh *mesh,
                                      ParticleCurveData *CData,
                                      float3 RotCam,
                                      bool is_ortho)
{
  int vertexno = mesh->verts.size();
  int vertexindex = vertexno;
  int numverts = 0, numtris = 0;

  /* compute and reserve size of arrays */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      numverts += 2 + (CData->curve_keynum[curve] - 1) * 2;
      numtris += (CData->curve_keynum[curve] - 1) * 2;
    }
  }

  mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);

  /* actually export */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      float3 xbasis;
      float3 v1;
      float time = 0.0f;
      float3 ickey_loc = CData->curvekey_co[CData->curve_firstkey[curve]];
      float radius = shaperadius(
          CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], 0.0f);
      v1 = CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
           CData->curvekey_co[CData->curve_firstkey[curve]];
      if (is_ortho)
        xbasis = normalize(cross(RotCam, v1));
      else
        xbasis = normalize(cross(RotCam - ickey_loc, v1));
      float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
      float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
      mesh->add_vertex(ickey_loc_shfl);
      mesh->add_vertex(ickey_loc_shfr);
      vertexindex += 2;

      for (int curvekey = CData->curve_firstkey[curve] + 1;
           curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve];
           curvekey++) {
        ickey_loc = CData->curvekey_co[curvekey];

        if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
          v1 = CData->curvekey_co[curvekey] -
               CData->curvekey_co[max(curvekey - 1, CData->curve_firstkey[curve])];
        else
          v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey - 1];

        time = CData->curvekey_time[curvekey] / CData->curve_length[curve];
        radius = shaperadius(
            CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);

        if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)
          radius = shaperadius(CData->psys_shape[sys],
                               CData->psys_rootradius[sys],
                               CData->psys_tipradius[sys],
                               0.95f);

        if (CData->psys_closetip[sys] &&
            (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
          radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);

        if (is_ortho)
          xbasis = normalize(cross(RotCam, v1));
        else
          xbasis = normalize(cross(RotCam - ickey_loc, v1));
        float3 ickey_loc_shfl = ickey_loc - radius * xbasis;
        float3 ickey_loc_shfr = ickey_loc + radius * xbasis;
        mesh->add_vertex(ickey_loc_shfl);
        mesh->add_vertex(ickey_loc_shfr);
        mesh->add_triangle(
            vertexindex - 2, vertexindex, vertexindex - 1, CData->psys_shader[sys], true);
        mesh->add_triangle(
            vertexindex + 1, vertexindex - 1, vertexindex, CData->psys_shader[sys], true);
        vertexindex += 2;
      }
    }
  }

  mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
  mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
  mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
  mesh->add_face_normals();
  mesh->add_vertex_normals();
  mesh->attributes.remove(ATTR_STD_FACE_NORMAL);

  /* texture coords still needed */
}
Exemple #4
0
static void ExportCurveTriangleGeometry(Mesh *mesh, ParticleCurveData *CData, int resolution)
{
  int vertexno = mesh->verts.size();
  int vertexindex = vertexno;
  int numverts = 0, numtris = 0;

  /* compute and reserve size of arrays */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      numverts += (CData->curve_keynum[curve] - 1) * resolution + resolution;
      numtris += (CData->curve_keynum[curve] - 1) * 2 * resolution;
    }
  }

  mesh->reserve_mesh(mesh->verts.size() + numverts, mesh->num_triangles() + numtris);

  /* actually export */
  for (int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
    for (int curve = CData->psys_firstcurve[sys];
         curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys];
         curve++) {
      float3 firstxbasis = cross(make_float3(1.0f, 0.0f, 0.0f),
                                 CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
                                     CData->curvekey_co[CData->curve_firstkey[curve]]);
      if (!is_zero(firstxbasis))
        firstxbasis = normalize(firstxbasis);
      else
        firstxbasis = normalize(cross(make_float3(0.0f, 1.0f, 0.0f),
                                      CData->curvekey_co[CData->curve_firstkey[curve] + 1] -
                                          CData->curvekey_co[CData->curve_firstkey[curve]]));

      for (int curvekey = CData->curve_firstkey[curve];
           curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1;
           curvekey++) {
        float3 xbasis = firstxbasis;
        float3 v1;
        float3 v2;

        if (curvekey == CData->curve_firstkey[curve]) {
          v1 = CData->curvekey_co[min(
                   curvekey + 2, CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] -
               CData->curvekey_co[curvekey + 1];
          v2 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
        }
        else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
          v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
          v2 = CData->curvekey_co[curvekey - 1] -
               CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
        }
        else {
          v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
          v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
        }

        xbasis = cross(v1, v2);

        if (len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
          firstxbasis = normalize(xbasis);
          break;
        }
      }

      for (int curvekey = CData->curve_firstkey[curve];
           curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1;
           curvekey++) {
        int subv = 1;
        float3 xbasis;
        float3 ybasis;
        float3 v1;
        float3 v2;

        if (curvekey == CData->curve_firstkey[curve]) {
          subv = 0;
          v1 = CData->curvekey_co[min(
                   curvekey + 2, CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)] -
               CData->curvekey_co[curvekey + 1];
          v2 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
        }
        else if (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1) {
          v1 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
          v2 = CData->curvekey_co[curvekey - 1] -
               CData->curvekey_co[max(curvekey - 2, CData->curve_firstkey[curve])];
        }
        else {
          v1 = CData->curvekey_co[curvekey + 1] - CData->curvekey_co[curvekey];
          v2 = CData->curvekey_co[curvekey] - CData->curvekey_co[curvekey - 1];
        }

        xbasis = cross(v1, v2);

        if (len_squared(xbasis) >= 0.05f * len_squared(v1) * len_squared(v2)) {
          xbasis = normalize(xbasis);
          firstxbasis = xbasis;
        }
        else
          xbasis = firstxbasis;

        ybasis = normalize(cross(xbasis, v2));

        for (; subv <= 1; subv++) {
          float3 ickey_loc = make_float3(0.0f, 0.0f, 0.0f);
          float time = 0.0f;

          InterpolateKeySegments(subv, 1, curvekey, curve, &ickey_loc, &time, CData);

          float radius = shaperadius(CData->psys_shape[sys],
                                     CData->psys_rootradius[sys],
                                     CData->psys_tipradius[sys],
                                     time);

          if ((curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2) &&
              (subv == 1))
            radius = shaperadius(CData->psys_shape[sys],
                                 CData->psys_rootradius[sys],
                                 CData->psys_tipradius[sys],
                                 0.95f);

          if (CData->psys_closetip[sys] && (subv == 1) &&
              (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 2))
            radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], 0.0f, 0.95f);

          float angle = M_2PI_F / (float)resolution;
          for (int section = 0; section < resolution; section++) {
            float3 ickey_loc_shf = ickey_loc + radius * (cosf(angle * section) * xbasis +
                                                         sinf(angle * section) * ybasis);
            mesh->add_vertex(ickey_loc_shf);
          }

          if (subv != 0) {
            for (int section = 0; section < resolution - 1; section++) {
              mesh->add_triangle(vertexindex - resolution + section,
                                 vertexindex + section,
                                 vertexindex - resolution + section + 1,
                                 CData->psys_shader[sys],
                                 true);
              mesh->add_triangle(vertexindex + section + 1,
                                 vertexindex - resolution + section + 1,
                                 vertexindex + section,
                                 CData->psys_shader[sys],
                                 true);
            }
            mesh->add_triangle(vertexindex - 1,
                               vertexindex + resolution - 1,
                               vertexindex - resolution,
                               CData->psys_shader[sys],
                               true);
            mesh->add_triangle(vertexindex,
                               vertexindex - resolution,
                               vertexindex + resolution - 1,
                               CData->psys_shader[sys],
                               true);
          }
          vertexindex += resolution;
        }
      }
    }
  }

  mesh->resize_mesh(mesh->verts.size(), mesh->num_triangles());
  mesh->attributes.remove(ATTR_STD_VERTEX_NORMAL);
  mesh->attributes.remove(ATTR_STD_FACE_NORMAL);
  mesh->add_face_normals();
  mesh->add_vertex_normals();
  mesh->attributes.remove(ATTR_STD_FACE_NORMAL);

  /* texture coords still needed */
}
Exemple #5
0
static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step)
{
	VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name
	        << ", motion step " << motion_step;

	/* find attribute */
	Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
	bool new_attribute = false;

	/* add new attribute if it doesn't exist already */
	if(!attr_mP) {
		VLOG(1) << "Creating new motion vertex position attribute";
		attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
		new_attribute = true;
	}

	/* export motion vectors for curve keys */
	size_t numkeys = mesh->curve_keys.size();
	float4 *mP = attr_mP->data_float4() + motion_step*numkeys;
	bool have_motion = false;
	int i = 0;

	for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) {
		if(CData->psys_curvenum[sys] == 0)
			continue;

		for(int curve = CData->psys_firstcurve[sys]; curve < CData->psys_firstcurve[sys] + CData->psys_curvenum[sys]; curve++) {
			if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f)
				continue;

			for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) {
				if(i < mesh->curve_keys.size()) {
					float3 ickey_loc = CData->curvekey_co[curvekey];
					float time = CData->curvekey_time[curvekey]/CData->curve_length[curve];
					float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time);

					if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1))
						radius = 0.0f;

					/* curve motion keys store both position and radius in float4 */
					mP[i] = float3_to_float4(ickey_loc);
					mP[i].w = radius;

					/* unlike mesh coordinates, these tend to be slightly different
					 * between frames due to particle transforms into/out of object
					 * space, so we use an epsilon to detect actual changes */
					float4 curve_key = float3_to_float4(mesh->curve_keys[i]);
					curve_key.w = mesh->curve_radius[i];
					if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f)
						have_motion = true;
				}

				i++;
			}
		}
	}

	/* in case of new attribute, we verify if there really was any motion */
	if(new_attribute) {
		if(i != numkeys || !have_motion) {
			/* No motion or hair "topology" changed, remove attributes again. */
			if(i != numkeys) {
				VLOG(1) << "Hair topology changed, removing attribute.";
			}
			else {
				VLOG(1) << "No motion, removing attribute.";
			}
			mesh->curve_attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
		}
		else if(motion_step > 0) {
			VLOG(1) << "Filling in new motion vertex position for motion_step "
			        << motion_step;
			/* motion, fill up previous steps that we might have skipped because
			 * they had no motion, but we need them anyway now */
			for(int step = 0; step < motion_step; step++) {
				float4 *mP = attr_mP->data_float4() + step*numkeys;

				for(int key = 0; key < numkeys; key++) {
					mP[key] = float3_to_float4(mesh->curve_keys[key]);
					mP[key].w = mesh->curve_radius[key];
				}
			}
		}
	}
}