Esempio n. 1
0
static void camera_to_frame_view_cb(const float co[3], void *user_data)
{
	CameraViewFrameData *data = (CameraViewFrameData *)user_data;
	unsigned int i;

	for (i = 0; i < 4; i++) {
		float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]);
		if (nd < data->dist_vals_sq[i]) {
			data->dist_vals_sq[i] = nd;
		}
	}

	data->tot++;
}
Esempio n. 2
0
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag flag)
{
	DerivedMesh *dm = derivedData;
	DerivedMesh *result;
	ScrewModifierData *ltmd = (ScrewModifierData *) md;
	const int useRenderParams = flag & MOD_APPLY_RENDER;
	
	int *origindex;
	int mpoly_index = 0;
	unsigned int step;
	unsigned int i, j;
	unsigned int i1, i2;
	unsigned int step_tot = useRenderParams ? ltmd->render_steps : ltmd->steps;
	const bool do_flip = ltmd->flag & MOD_SCREW_NORMAL_FLIP ? 1 : 0;

	const int quad_ord[4] = {
	    do_flip ? 3 : 0,
	    do_flip ? 2 : 1,
	    do_flip ? 1 : 2,
	    do_flip ? 0 : 3,
	};
	const int quad_ord_ofs[4] = {
	    do_flip ? 2 : 0,
	    do_flip ? 1 : 1,
	    do_flip ? 0 : 2,
	    do_flip ? 3 : 3,
	};

	unsigned int maxVerts = 0, maxEdges = 0, maxPolys = 0;
	const unsigned int totvert = (unsigned int)dm->getNumVerts(dm);
	const unsigned int totedge = (unsigned int)dm->getNumEdges(dm);
	const unsigned int totpoly = (unsigned int)dm->getNumPolys(dm);

	unsigned int *edge_poly_map = NULL;  /* orig edge to orig poly */
	unsigned int *vert_loop_map = NULL;  /* orig vert to orig loop */

	/* UV Coords */
	const unsigned int mloopuv_layers_tot = (unsigned int)CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV);
	MLoopUV **mloopuv_layers = BLI_array_alloca(mloopuv_layers, mloopuv_layers_tot);
	float uv_u_scale;
	float uv_v_minmax[2] = {FLT_MAX, -FLT_MAX};
	float uv_v_range_inv;
	float uv_axis_plane[4];

	char axis_char = 'X';
	bool close;
	float angle = ltmd->angle;
	float screw_ofs = ltmd->screw_ofs;
	float axis_vec[3] = {0.0f, 0.0f, 0.0f};
	float tmp_vec1[3], tmp_vec2[3]; 
	float mat3[3][3];
	float mtx_tx[4][4]; /* transform the coords by an object relative to this objects transformation */
	float mtx_tx_inv[4][4]; /* inverted */
	float mtx_tmp_a[4][4];
	
	unsigned int vc_tot_linked = 0;
	short other_axis_1, other_axis_2;
	const float *tmpf1, *tmpf2;

	unsigned int edge_offset;
	
	MPoly *mpoly_orig, *mpoly_new, *mp_new;
	MLoop *mloop_orig, *mloop_new, *ml_new;
	MEdge *medge_orig, *med_orig, *med_new, *med_new_firstloop, *medge_new;
	MVert *mvert_new, *mvert_orig, *mv_orig, *mv_new, *mv_new_base;

	ScrewVertConnect *vc, *vc_tmp, *vert_connect = NULL;

	const char mpoly_flag = (ltmd->flag & MOD_SCREW_SMOOTH_SHADING) ? ME_SMOOTH : 0;

	/* don't do anything? */
	if (!totvert)
		return CDDM_from_template(dm, 0, 0, 0, 0, 0);

	switch (ltmd->axis) {
		case 0:
			other_axis_1 = 1;
			other_axis_2 = 2;
			break;
		case 1:
			other_axis_1 = 0;
			other_axis_2 = 2;
			break;
		default: /* 2, use default to quiet warnings */
			other_axis_1 = 0;
			other_axis_2 = 1;
			break;
	}

	axis_vec[ltmd->axis] = 1.0f;

	if (ltmd->ob_axis) {
		/* calc the matrix relative to the axis object */
		invert_m4_m4(mtx_tmp_a, ob->obmat);
		copy_m4_m4(mtx_tx_inv, ltmd->ob_axis->obmat);
		mul_m4_m4m4(mtx_tx, mtx_tmp_a, mtx_tx_inv);

		/* calc the axis vec */
		mul_mat3_m4_v3(mtx_tx, axis_vec); /* only rotation component */
		normalize_v3(axis_vec);

		/* screw */
		if (ltmd->flag & MOD_SCREW_OBJECT_OFFSET) {
			/* find the offset along this axis relative to this objects matrix */
			float totlen = len_v3(mtx_tx[3]);

			if (totlen != 0.0f) {
				float zero[3] = {0.0f, 0.0f, 0.0f};
				float cp[3];
				screw_ofs = closest_to_line_v3(cp, mtx_tx[3], zero, axis_vec);
			}
			else {
				screw_ofs = 0.0f;
			}
		}

		/* angle */

#if 0   /* cant incluide this, not predictable enough, though quite fun. */
		if (ltmd->flag & MOD_SCREW_OBJECT_ANGLE) {
			float mtx3_tx[3][3];
			copy_m3_m4(mtx3_tx, mtx_tx);

			float vec[3] = {0, 1, 0};
			float cross1[3];
			float cross2[3];
			cross_v3_v3v3(cross1, vec, axis_vec);

			mul_v3_m3v3(cross2, mtx3_tx, cross1);
			{
				float c1[3];
				float c2[3];
				float axis_tmp[3];

				cross_v3_v3v3(c1, cross2, axis_vec);
				cross_v3_v3v3(c2, axis_vec, c1);


				angle = angle_v3v3(cross1, c2);

				cross_v3_v3v3(axis_tmp, cross1, c2);
				normalize_v3(axis_tmp);

				if (len_v3v3(axis_tmp, axis_vec) > 1.0f)
					angle = -angle;

			}
		}
#endif
	}
	else {
		/* exis char is used by i_rotate*/
		axis_char = (char)(axis_char + ltmd->axis); /* 'X' + axis */

		/* useful to be able to use the axis vec in some cases still */
		zero_v3(axis_vec);
		axis_vec[ltmd->axis] = 1.0f;
	}

	/* apply the multiplier */
	angle *= (float)ltmd->iter;
	screw_ofs *= (float)ltmd->iter;
	uv_u_scale = 1.0f / (float)(step_tot);

	/* multiplying the steps is a bit tricky, this works best */
	step_tot = ((step_tot + 1) * ltmd->iter) - (ltmd->iter - 1);

	/* will the screw be closed?
	 * Note! smaller then FLT_EPSILON * 100 gives problems with float precision so its never closed. */
	if (fabsf(screw_ofs) <= (FLT_EPSILON * 100.0f) &&
	    fabsf(fabsf(angle) - ((float)M_PI * 2.0f)) <= (FLT_EPSILON * 100.0f))
	{
		close = 1;
		step_tot--;
		if (step_tot < 3) step_tot = 3;
	
		maxVerts = totvert  * step_tot;   /* -1 because we're joining back up */
		maxEdges = (totvert * step_tot) + /* these are the edges between new verts */
		           (totedge * step_tot);  /* -1 because vert edges join */
		maxPolys = totedge * step_tot;

		screw_ofs = 0.0f;
	}
	else {
		close = 0;
		if (step_tot < 3) step_tot = 3;

		maxVerts =  totvert  * step_tot; /* -1 because we're joining back up */
		maxEdges =  (totvert * (step_tot - 1)) + /* these are the edges between new verts */
		           (totedge * step_tot);  /* -1 because vert edges join */
		maxPolys =  totedge * (step_tot - 1);
	}

	if ((ltmd->flag & MOD_SCREW_UV_STRETCH_U) == 0) {
		uv_u_scale = (uv_u_scale / (float)ltmd->iter) * (angle / ((float)M_PI * 2.0f));
	}
	
	result = CDDM_from_template(dm, (int)maxVerts, (int)maxEdges, 0, (int)maxPolys * 4, (int)maxPolys);
	
	/* copy verts from mesh */
	mvert_orig =    dm->getVertArray(dm);
	medge_orig =    dm->getEdgeArray(dm);
	
	mvert_new =     result->getVertArray(result);
	mpoly_new =     result->getPolyArray(result);
	mloop_new =     result->getLoopArray(result);
	medge_new =     result->getEdgeArray(result);

	if (!CustomData_has_layer(&result->polyData, CD_ORIGINDEX)) {
		CustomData_add_layer(&result->polyData, CD_ORIGINDEX, CD_CALLOC, NULL, (int)maxPolys);
	}

	origindex = CustomData_get_layer(&result->polyData, CD_ORIGINDEX);

	DM_copy_vert_data(dm, result, 0, 0, (int)totvert); /* copy first otherwise this overwrites our own vertex normals */

	if (mloopuv_layers_tot) {
		float zero_co[3] = {0};
		plane_from_point_normal_v3(uv_axis_plane, zero_co, axis_vec);
	}

	if (mloopuv_layers_tot) {
		unsigned int uv_lay;
		for (uv_lay = 0; uv_lay < mloopuv_layers_tot; uv_lay++) {
			mloopuv_layers[uv_lay] = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, (int)uv_lay);
		}

		if (ltmd->flag & MOD_SCREW_UV_STRETCH_V) {
			for (i = 0, mv_orig = mvert_orig; i < totvert; i++, mv_orig++) {
				const float v = dist_squared_to_plane_v3(mv_orig->co, uv_axis_plane);
				uv_v_minmax[0] = min_ff(v, uv_v_minmax[0]);
				uv_v_minmax[1] = max_ff(v, uv_v_minmax[1]);
			}
			uv_v_minmax[0] = sqrtf_signed(uv_v_minmax[0]);
			uv_v_minmax[1] = sqrtf_signed(uv_v_minmax[1]);
		}

		uv_v_range_inv = uv_v_minmax[1] - uv_v_minmax[0];
		uv_v_range_inv = uv_v_range_inv ? 1.0f / uv_v_range_inv : 0.0f;
	}

	/* Set the locations of the first set of verts */
	
	mv_new = mvert_new;
	mv_orig = mvert_orig;
	
	/* Copy the first set of edges */
	med_orig = medge_orig;
	med_new = medge_new;
	for (i = 0; i < totedge; i++, med_orig++, med_new++) {
		med_new->v1 = med_orig->v1;
		med_new->v2 = med_orig->v2;
		med_new->crease = med_orig->crease;
		med_new->flag = med_orig->flag &  ~ME_LOOSEEDGE;
	}
	
	/* build polygon -> edge map */
	if (totpoly) {
		MPoly *mp_orig;

		mpoly_orig = dm->getPolyArray(dm);
		mloop_orig = dm->getLoopArray(dm);
		edge_poly_map = MEM_mallocN(sizeof(*edge_poly_map) * totedge, __func__);
		memset(edge_poly_map, 0xff, sizeof(*edge_poly_map) * totedge);

		vert_loop_map = MEM_mallocN(sizeof(*vert_loop_map) * totvert, __func__);
		memset(vert_loop_map, 0xff, sizeof(*vert_loop_map) * totvert);

		for (i = 0, mp_orig = mpoly_orig; i < totpoly; i++, mp_orig++) {
			unsigned int loopstart = (unsigned int)mp_orig->loopstart;
			unsigned int loopend = loopstart + (unsigned int)mp_orig->totloop;

			MLoop *ml_orig = &mloop_orig[loopstart];
			unsigned int k;
			for (k = loopstart; k < loopend; k++, ml_orig++) {
				edge_poly_map[ml_orig->e] = i;
				vert_loop_map[ml_orig->v] = k;

				/* also order edges based on faces */
				if (medge_new[ml_orig->e].v1 != ml_orig->v) {
					SWAP(unsigned int, medge_new[ml_orig->e].v1, medge_new[ml_orig->e].v2);
				}
			}
		}
	}
Esempio n. 3
0
/* add a gpencil object to cache to defer drawing */
tGPencilObjectCache *gpencil_object_cache_add(tGPencilObjectCache *cache_array,
                                              Object *ob,
                                              int *gp_cache_size,
                                              int *gp_cache_used)
{
  const DRWContextState *draw_ctx = DRW_context_state_get();
  tGPencilObjectCache *cache_elem = NULL;
  RegionView3D *rv3d = draw_ctx->rv3d;
  View3D *v3d = draw_ctx->v3d;
  tGPencilObjectCache *p = NULL;

  /* By default a cache is created with one block with a predefined number of free slots,
   * if the size is not enough, the cache is reallocated adding a new block of free slots.
   * This is done in order to keep cache small. */
  if (*gp_cache_used + 1 > *gp_cache_size) {
    if ((*gp_cache_size == 0) || (cache_array == NULL)) {
      p = MEM_callocN(sizeof(struct tGPencilObjectCache) * GP_CACHE_BLOCK_SIZE,
                      "tGPencilObjectCache");
      *gp_cache_size = GP_CACHE_BLOCK_SIZE;
    }
    else {
      *gp_cache_size += GP_CACHE_BLOCK_SIZE;
      p = MEM_recallocN(cache_array, sizeof(struct tGPencilObjectCache) * *gp_cache_size);
    }
    cache_array = p;
  }
  /* zero out all pointers */
  cache_elem = &cache_array[*gp_cache_used];
  memset(cache_elem, 0, sizeof(*cache_elem));

  cache_elem->ob = ob;
  cache_elem->gpd = (bGPdata *)ob->data;
  cache_elem->name = BKE_id_to_unique_string_key(&ob->id);

  copy_v3_v3(cache_elem->loc, ob->obmat[3]);
  copy_m4_m4(cache_elem->obmat, ob->obmat);
  cache_elem->idx = *gp_cache_used;

  /* object is duplicated (particle) */
  if (ob->base_flag & BASE_FROM_DUPLI) {
    /* Check if the original object is not in the viewlayer
     * and cannot be managed as dupli. This is slower, but required to keep
     * the particle drawing FPS and display instanced objects in scene
     * without the original object */
    bool has_original = gpencil_has_noninstanced_object(ob);
    cache_elem->is_dup_ob = (has_original) ? ob->base_flag & BASE_FROM_DUPLI : false;
  }
  else {
    cache_elem->is_dup_ob = false;
  }

  cache_elem->scale = mat4_to_scale(ob->obmat);

  /* save FXs */
  cache_elem->pixfactor = cache_elem->gpd->pixfactor;
  cache_elem->shader_fx = ob->shader_fx;

  /* save wire mode (object mode is always primary option) */
  if (ob->dt == OB_WIRE) {
    cache_elem->shading_type[0] = (int)OB_WIRE;
  }
  else {
    if (v3d) {
      cache_elem->shading_type[0] = (int)v3d->shading.type;
    }
  }

  /* shgrp array */
  cache_elem->tot_layers = 0;
  int totgpl = BLI_listbase_count(&cache_elem->gpd->layers);
  if (totgpl > 0) {
    cache_elem->shgrp_array = MEM_callocN(sizeof(tGPencilObjectCache_shgrp) * totgpl, __func__);
  }

  /* calculate zdepth from point of view */
  float zdepth = 0.0;
  if (rv3d) {
    if (rv3d->is_persp) {
      zdepth = ED_view3d_calc_zfac(rv3d, ob->obmat[3], NULL);
    }
    else {
      zdepth = -dot_v3v3(rv3d->viewinv[2], ob->obmat[3]);
    }
  }
  else {
    /* In render mode, rv3d is not available, so use the distance to camera.
     * The real distance is not important, but the relative distance to the camera plane
     * in order to sort by z_depth of the objects
     */
    float vn[3] = {0.0f, 0.0f, -1.0f}; /* always face down */
    float plane_cam[4];
    struct Object *camera = draw_ctx->scene->camera;
    if (camera) {
      mul_m4_v3(camera->obmat, vn);
      normalize_v3(vn);
      plane_from_point_normal_v3(plane_cam, camera->loc, vn);
      zdepth = dist_squared_to_plane_v3(ob->obmat[3], plane_cam);
    }
  }
  cache_elem->zdepth = zdepth;
  /* increase slots used in cache */
  (*gp_cache_used)++;

  return cache_array;
}