示例#1
0
static void applyObjectConstraintVec(TransInfo *t,
                                     TransDataContainer *tc,
                                     TransData *td,
                                     const float in[3],
                                     float out[3],
                                     float pvec[3])
{
  copy_v3_v3(out, in);
  if (t->con.mode & CON_APPLY) {
    if (!td) {
      mul_m3_v3(t->con.pmtx, out);

      const int dims = getConstraintSpaceDimension(t);
      if (dims == 2) {
        if (!is_zero_v3(out)) {
          if (!isPlaneProjectionViewAligned(t)) {
            planeProjection(t, in, out);
          }
        }
      }
      else if (dims == 1) {
        float c[3];

        if (t->con.mode & CON_AXIS0) {
          copy_v3_v3(c, t->con.mtx[0]);
        }
        else if (t->con.mode & CON_AXIS1) {
          copy_v3_v3(c, t->con.mtx[1]);
        }
        else if (t->con.mode & CON_AXIS2) {
          copy_v3_v3(c, t->con.mtx[2]);
        }
        axisProjection(t, c, in, out);
      }
      postConstraintChecks(t, out, pvec);
      copy_v3_v3(out, pvec);
    }
    else {
      int i = 0;

      out[0] = out[1] = out[2] = 0.0f;
      if (t->con.mode & CON_AXIS0) {
        out[0] = in[i++];
      }
      if (t->con.mode & CON_AXIS1) {
        out[1] = in[i++];
      }
      if (t->con.mode & CON_AXIS2) {
        out[2] = in[i++];
      }

      mul_m3_v3(td->axismtx, out);
      if (t->flag & T_EDIT) {
        mul_m3_v3(tc->mat3_unit, out);
      }
    }
  }
}
示例#2
0
static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3],
                                  float time, float freq, float shape, float amplitude,
                                  const float spiral_start[3])
{
	float result[3];

	CLAMP(time, 0.f, 1.f);

	copy_v3_v3(result, state->co);

	{
		/* Creates a logarithmic spiral:
		 *   r(theta) = a * exp(b * theta)
		 *
		 * The "density" parameter b is defined by the shape parameter
		 * and goes up to the Golden Spiral for 1.0
		 * https://en.wikipedia.org/wiki/Golden_spiral
		 */
		const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f;
		/* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
		const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
		                           (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);

		float spiral_axis[3], rot[3][3];
		float vec[3];

		float theta = freq * time * 2.0f * (float)M_PI;
		float radius = amplitude * expf(b * theta);

		/* a bit more intuitive than using negative frequency for this */
		if (amplitude < 0.0f)
			theta = -theta;

		cross_v3_v3v3(spiral_axis, dir, kink);
		normalize_v3(spiral_axis);

		mul_v3_v3fl(vec, kink, -radius);

		axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
		mul_m3_v3(rot, vec);

		madd_v3_v3fl(vec, kink, amplitude);

		axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
		mul_m3_v3(rot, vec);

		add_v3_v3v3(result, spiral_start, vec);
	}

	copy_v3_v3(state->co, result);
}
static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
	copy_v3_v3(out, in);
	if (t->con.mode & CON_APPLY) {
		if (!td) {
			mul_m3_v3(t->con.pmtx, out);
			if (getConstraintSpaceDimension(t) == 2) {
				if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
					planeProjection(t, in, out);
				}
			}
			else if (getConstraintSpaceDimension(t) == 1) {
				float c[3];

				if (t->con.mode & CON_AXIS0) {
					copy_v3_v3(c, t->con.mtx[0]);
				}
				else if (t->con.mode & CON_AXIS1) {
					copy_v3_v3(c, t->con.mtx[1]);
				}
				else if (t->con.mode & CON_AXIS2) {
					copy_v3_v3(c, t->con.mtx[2]);
				}
				axisProjection(t, c, in, out);
			}
			postConstraintChecks(t, out, pvec);
			copy_v3_v3(out, pvec);
		}
		else {
			int i = 0;

			out[0] = out[1] = out[2] = 0.0f;
			if (t->con.mode & CON_AXIS0) {
				out[0] = in[i++];
			}
			if (t->con.mode & CON_AXIS1) {
				out[1] = in[i++];
			}
			if (t->con.mode & CON_AXIS2) {
				out[2] = in[i++];
			}

			mul_m3_v3(td->axismtx, out);
			if (t->flag & T_EDIT) {
				mul_m3_v3(t->obedit_mat, out);
			}
		}
	}
}
示例#4
0
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
{
	float angle, start[3], end[3];

	sub_v3_v3v3(start, p1, t->center_global);
	sub_v3_v3v3(end,   p2, t->center_global);
		
	// Angle around a constraint axis (error prone, will need debug)
	if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
		float axis[3], tmp[3];
		
		t->con.applyRot(t, NULL, axis, NULL);

		project_v3_v3v3(tmp, end, axis);
		sub_v3_v3v3(end, end, tmp);
		
		project_v3_v3v3(tmp, start, axis);
		sub_v3_v3v3(start, start, tmp);
		
		normalize_v3(end);
		normalize_v3(start);
		
		cross_v3_v3v3(tmp, start, end);
		
		if (dot_v3v3(tmp, axis) < 0.0f)
			angle = -acosf(dot_v3v3(start, end));
		else
			angle = acosf(dot_v3v3(start, end));
	}
	else {
		float mtx[3][3];
		
		copy_m3_m4(mtx, t->viewmat);

		mul_m3_v3(mtx, end);
		mul_m3_v3(mtx, start);
		
		angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]);
	}
	
	if (angle > (float)M_PI) {
		angle = angle - 2 * (float)M_PI;
	}
	else if (angle < -((float)M_PI)) {
		angle = 2.0f * (float)M_PI + angle;
	}
	
	return angle;
}
示例#5
0
static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3)
{
	VlakRen *vlr = bs->vlr;
	float A, d1, d2, d3, *v1, *v2, *v3;

	if (bs->quad) {
		v1 = vlr->v1->co;
		v2 = vlr->v3->co;
		v3 = vlr->v4->co;
	}
	else {
		v1 = vlr->v1->co;
		v2 = vlr->v2->co;
		v3 = vlr->v3->co;
	}

	/* formula derived from barycentric coordinates:
	 * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea
	 * then taking u and v partial derivatives to get dxco and dyco */
	A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]);

	if (fabsf(A) > FLT_EPSILON) {
		A = 0.5f / A;

		d1 = uv2[1] - uv3[1];
		d2 = uv3[1] - uv1[1];
		d3 = uv1[1] - uv2[1];
		bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
		bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
		bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;

		d1 = uv3[0] - uv2[0];
		d2 = uv1[0] - uv3[0];
		d3 = uv2[0] - uv1[0];
		bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A;
		bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A;
		bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A;
	}
	else {
		bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f;
		bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f;
	}

	if (bs->obi->flag & R_TRANSFORMED) {
		mul_m3_v3(bs->obi->nmat, bs->dxco);
		mul_m3_v3(bs->obi->nmat, bs->dyco);
	}
}
示例#6
0
/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/
void shadeSunView(float col_r[3], const float view[3])
{
	GroupObject *go;
	LampRen *lar;
	float sview[3];
	bool do_init = true;
	
	for (go=R.lights.first; go; go= go->next) {
		lar= go->lampren;
		if (lar->type==LA_SUN &&	lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)) {
			float sun_collector[3];
			float colorxyz[3];
			
			if (do_init) {

				normalize_v3_v3(sview, view);
				mul_m3_v3(R.imat, sview);
				if (sview[2] < 0.0f)
					sview[2] = 0.0f;
				normalize_v3(sview);
				do_init = false;
			}
			
			GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz);
			xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2],
			           lar->sunsky->sky_colorspace);
			
			ramp_blend(lar->sunsky->skyblendtype, col_r, lar->sunsky->skyblendfac, sun_collector);
		}
	}
}
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
	Main *bmain = CTX_data_main(C);
	float *v1, *v3;
	float mat[3][3];

	CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
	{
		if (ob->parent) {
			/* vectors pointed to by v1 and v3 will get modified */
			v1 = ob->loc;
			v3 = ob->parentinv[3];
			
			copy_m3_m4(mat, ob->parentinv);
			negate_v3_v3(v3, v1);
			mul_m3_v3(mat, v3);
		}

		DAG_id_tag_update(&ob->id, OB_RECALC_OB);
	}
	CTX_DATA_END;

	DAG_ids_flush_update(bmain, 0);
	
	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
示例#8
0
/**
 * \param ray_distance  Distance to the hit point
 * \param r_location  Location of the hit point
 * \param r_normal  Normal of the hit surface, transformed to always face the camera
 */
static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance)
{
	float dummy_dist_px = 0;
	float ray_normal[3] = {0, 0, 1}; /* forward */
	float ray_start[3];
	float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */
	bool ret;

	*ray_distance = TRANSFORM_DIST_MAX_RAY;

	copy_v3_v3(ray_start, rv3d->viewinv[3]);
	copy_m3_m4(mat, rv3d->viewinv);

	mul_m3_v3(mat, ray_normal);

	mul_v3_fl(ray_normal, -1);
	normalize_v3(ray_normal);

	ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE,
	                       NULL, NULL,
	                       ray_start, ray_normal, ray_distance,
	                       NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL);


	/* dot is positive if both rays are facing the same direction */
	if (dot_v3v3(ray_normal, r_normal) > 0) {
		copy_v3_fl3(r_normal, -r_normal[0], -r_normal[1], -r_normal[2]);
	}

	/* artifically scale the distance to the scene size */
	*ray_distance /= walk->grid;

	return ret;
}
static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
{
	copy_v3_v3(out, in);
	if (!td && t->con.mode & CON_APPLY) {
		mul_m3_v3(t->con.pmtx, out);

		// With snap, a projection is alright, no need to correct for view alignment
		if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) {
			if (getConstraintSpaceDimension(t) == 2) {
				if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) {
					planeProjection(t, in, out);
				}
			}
			else if (getConstraintSpaceDimension(t) == 1) {
				float c[3];

				if (t->con.mode & CON_AXIS0) {
					copy_v3_v3(c, t->con.mtx[0]);
				}
				else if (t->con.mode & CON_AXIS1) {
					copy_v3_v3(c, t->con.mtx[1]);
				}
				else if (t->con.mode & CON_AXIS2) {
					copy_v3_v3(c, t->con.mtx[2]);
				}
				axisProjection(t, c, in, out);
			}
		}
		postConstraintChecks(t, out, pvec);
	}
}
示例#10
0
/* returns standard diameter */
static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4])
{
	Object *obedit = CTX_data_edit_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
	
	unit_m4(primmat);

	eul_to_mat3(rmat, rot);
	invert_m3(rmat);
	
	/* inverse transform for initial rotation and object */
	copy_m3_m4(mat, obedit->obmat);
	mul_m3_m3m3(cmat, rmat, mat);
	invert_m3_m3(imat, cmat);
	copy_m4_m3(primmat, imat);

	/* center */
	copy_v3_v3(primmat[3], loc);
	sub_v3_v3(primmat[3], obedit->obmat[3]);
	invert_m3_m3(imat, mat);
	mul_m3_v3(imat, primmat[3]);

	return v3d ? v3d->grid : 1.0f;
}
示例#11
0
static int object_hook_recenter_exec(bContext *C, wmOperator *op)
{
	PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier);
	int num= RNA_enum_get(op->ptr, "modifier");
	Object *ob=NULL;
	HookModifierData *hmd=NULL;
	Scene *scene = CTX_data_scene(C);
	float bmat[3][3], imat[3][3];
	
	if (ptr.data) {		/* if modifier context is available, use that */
		ob = ptr.id.data;
		hmd= ptr.data;
	} 
	else {			/* use the provided property */
		ob = CTX_data_edit_object(C);
		hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num);
	}
	if (!ob || !hmd) {
		BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier");
		return OPERATOR_CANCELLED;
	}
	
	/* recenter functionality */
	copy_m3_m4(bmat, ob->obmat);
	invert_m3_m3(imat, bmat);
	
	sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]);
	mul_m3_v3(imat, hmd->cent);
	
	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
	WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
	
	return OPERATOR_FINISHED;
}
示例#12
0
/* Only view vector is important here. Result goes to col_r[3] */
void shadeSkyView(float col_r[3], const float rco[3], const float view[3], const float dxyview[2], short thread)
{
	float zen[3], hor[3], blend, blendm;
	int skyflag;
	
	/* flag indicating if we render the top hemisphere */
	skyflag = WO_ZENUP;
	
	/* Some view vector stuff. */
	if (R.wrld.skytype & WO_SKYREAL) {
		
		blend = dot_v3v3(view, R.grvec);
		
		if (blend<0.0f) skyflag= 0;
		
		blend = fabsf(blend);
	}
	else if (R.wrld.skytype & WO_SKYPAPER) {
		blend= 0.5f + 0.5f * view[1];
	}
	else {
		/* the fraction of how far we are above the bottom of the screen */
		blend = fabsf(0.5f + view[1]);
	}

	copy_v3_v3(hor, &R.wrld.horr);
	copy_v3_v3(zen, &R.wrld.zenr);

	/* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If           */
	/* SKYBLEND is active, the texture and color blend are added.           */
	if (R.wrld.skytype & WO_SKYTEX) {
		float lo[3];
		copy_v3_v3(lo, view);
		if (R.wrld.skytype & WO_SKYREAL) {

			mul_m3_v3(R.imat, lo);

			SWAP(float, lo[1],  lo[2]);

		}
		do_sky_tex(rco, view, lo, dxyview, hor, zen, &blend, skyflag, thread);
	}
	
	if (blend>1.0f) blend= 1.0f;
	blendm= 1.0f-blend;
	
	/* No clipping, no conversion! */
	if (R.wrld.skytype & WO_SKYBLEND) {
		col_r[0] = (blendm*hor[0] + blend*zen[0]);
		col_r[1] = (blendm*hor[1] + blend*zen[1]);
		col_r[2] = (blendm*hor[2] + blend*zen[2]);
	}
	else {
		/* Done when a texture was grabbed. */
		col_r[0]= hor[0];
		col_r[1]= hor[1];
		col_r[2]= hor[2];
	}
}
示例#13
0
static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
{
  int i = 0;

  mul_m3_v3(t->con.imtx, vec);

  snapGridIncrement(t, vec);

  if (t->flag & T_NULL_ONE) {
    if (!(t->con.mode & CON_AXIS0)) {
      vec[0] = 1.0f;
    }

    if (!(t->con.mode & CON_AXIS1)) {
      vec[1] = 1.0f;
    }

    if (!(t->con.mode & CON_AXIS2)) {
      vec[2] = 1.0f;
    }
  }

  if (applyNumInput(&t->num, vec)) {
    constraintNumInput(t, vec);
    removeAspectRatio(t, vec);
  }

  /* autovalues is operator param, use that directly but not if snapping is forced */
  if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) {
    copy_v3_v3(vec, t->auto_values);
    constraintAutoValues(t, vec);
    /* inverse transformation at the end */
  }

  if (t->con.mode & CON_AXIS0) {
    pvec[i++] = vec[0];
  }
  if (t->con.mode & CON_AXIS1) {
    pvec[i++] = vec[1];
  }
  if (t->con.mode & CON_AXIS2) {
    pvec[i++] = vec[2];
  }

  mul_m3_v3(t->con.mtx, vec);
}
void setBoneRollFromNormal(EditBone *bone, const float no[3], float UNUSED(invmat[4][4]), float tmat[3][3])
{
	if (no != NULL && !is_zero_v3(no)) {
		float normal[3];

		copy_v3_v3(normal, no);
		mul_m3_v3(tmat, normal);
		
		bone->roll = ED_rollBoneToVector(bone, normal, false);
	}
}
BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2])
{
  float vec[3] = {x, y, 1.0f};
  mul_m3_v3(matrix, vec);
  uv[0] = vec[0] / vec[2];
  uv[1] = vec[1] / vec[2];

  deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2];
  deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2];
  deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2];
  deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2];
}
示例#16
0
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3])
{
	float d1[3], d2[3], len_d1;

	sub_v3_v3v3(d1, p1, t->center_global);
	sub_v3_v3v3(d2, p2, t->center_global);

	if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
		mul_m3_v3(t->con.pmtx, d1);
		mul_m3_v3(t->con.pmtx, d2);
	}

	project_v3_v3v3(d1, d1, d2);
	
	len_d1 = len_v3(d1);

	/* Use 'invalid' dist when `center == p1` (after projecting),
	 * in this case scale will _never_ move the point in relation to the center,
	 * so it makes no sense to take it into account when scaling. see: T46503 */
	return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID;
}
示例#17
0
static void occ_face(const OccFace *face, float co[3], float normal[3], float *area)
{
	ObjectInstanceRen *obi;
	VlakRen *vlr;
	float v1[3], v2[3], v3[3], v4[3];

	obi = &R.objectinstance[face->obi];
	vlr = RE_findOrAddVlak(obi->obr, face->facenr);
	
	if (co) {
		if (vlr->v4)
			mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co);
		else
			cent_tri_v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co);

		if (obi->flag & R_TRANSFORMED)
			mul_m4_v3(obi->mat, co);
	}
	
	if (normal) {
		normal[0] = -vlr->n[0];
		normal[1] = -vlr->n[1];
		normal[2] = -vlr->n[2];

		if (obi->flag & R_TRANSFORMED)
			mul_m3_v3(obi->nmat, normal);
	}

	if (area) {
		copy_v3_v3(v1, vlr->v1->co);
		copy_v3_v3(v2, vlr->v2->co);
		copy_v3_v3(v3, vlr->v3->co);
		if (vlr->v4) copy_v3_v3(v4, vlr->v4->co);

		if (obi->flag & R_TRANSFORMED) {
			mul_m4_v3(obi->mat, v1);
			mul_m4_v3(obi->mat, v2);
			mul_m4_v3(obi->mat, v3);
			if (vlr->v4) mul_m4_v3(obi->mat, v4);
		}

		/* todo: correct area for instances */
		if (vlr->v4)
			*area = area_quad_v3(v1, v2, v3, v4);
		else
			*area = area_tri_v3(v1, v2, v3);
	}
}
示例#18
0
bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon)
{
	float m[3][3];

	BLI_quadric_to_tensor_m3(q, m);

	if (invert_m3_ex(m, epsilon)) {
		BLI_quadric_to_vector_v3(q, v);
		mul_m3_v3(m, v);
		negate_v3(v);

		return true;
	}
	else {
		return false;
	}
}
示例#19
0
/* Meta object density, brute force for now 
 * (might be good enough anyway, don't need huge number of metaobs to model volumetric objects */
static float metadensity(Object *ob, const float co[3])
{
	float mat[4][4], imat[4][4], dens = 0.f;
	MetaBall *mb = (MetaBall *)ob->data;
	MetaElem *ml;
	
	/* transform co to meta-element */
	float tco[3] = {co[0], co[1], co[2]};
	mult_m4_m4m4(mat, R.viewmat, ob->obmat);
	invert_m4_m4(imat, mat);
	mul_m4_v3(imat, tco);
	
	for (ml = mb->elems.first; ml; ml = ml->next) {
		float bmat[3][3], dist2;
		
		/* element rotation transform */
		float tp[3] = {ml->x - tco[0], ml->y - tco[1], ml->z - tco[2]};
		quat_to_mat3(bmat, ml->quat);
		transpose_m3(bmat); /* rot.only, so inverse == transpose */
		mul_m3_v3(bmat, tp);

		/* MB_BALL default */
		switch (ml->type) {
			case MB_ELIPSOID:
				tp[0] /= ml->expx, tp[1] /= ml->expy, tp[2] /= ml->expz;
				break;
			case MB_CUBE:
				tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f);
			/* no break, xy as plane */
			case MB_PLANE:
				tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f);
			/* no break, x as tube */
			case MB_TUBE:
				tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f);
		}

		/* ml->rad2 is not set */
		dist2 = 1.0f - (dot_v3v3(tp, tp) / (ml->rad * ml->rad));
		if (dist2 > 0.f)
			dens += (ml->flag & MB_NEGATIVE) ? -ml->s * dist2 * dist2 * dist2 : ml->s * dist2 * dist2 * dist2;
	}
	
	dens -= mb->thresh;
	return (dens < 0.f) ? 0.f : dens;
}
示例#20
0
static void rigid_add_half_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w)
{
	/* formula (8) */
	float Rsum[3][3], rhs[3];

	if (sys->vpinned[v1->tmp.l])
		return;

	add_m3_m3m3(Rsum, sys->rigid.R[v1->tmp.l], sys->rigid.R[v2->tmp.l]);
	transpose_m3(Rsum);

	sub_v3_v3v3(rhs, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]);
	mul_m3_v3(Rsum, rhs);
	mul_v3_fl(rhs, 0.5f);
	mul_v3_fl(rhs, w);

	add_v3_v3(sys->rigid.rhs[v1->tmp.l], rhs);
}
示例#21
0
static void imapaint_tri_weights(Object *ob,
                                 const float v1[3], const float v2[3], const float v3[3],
                                 const float co[2], float w[3])
{
	float pv1[4], pv2[4], pv3[4], h[3], divw;
	float model[4][4], proj[4][4], wmat[3][3], invwmat[3][3];
	GLint view[4];

	/* compute barycentric coordinates */

	/* get the needed opengl matrices */
	glGetIntegerv(GL_VIEWPORT, view);
	glGetFloatv(GL_MODELVIEW_MATRIX,  (float *)model);
	glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj);
	view[0] = view[1] = 0;

	/* project the verts */
	imapaint_project(ob, model, proj, v1, pv1);
	imapaint_project(ob, model, proj, v2, pv2);
	imapaint_project(ob, model, proj, v3, pv3);

	/* do inverse view mapping, see gluProject man page */
	h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1;
	h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1;
	h[2] = 1.0f;

	/* solve for (w1,w2,w3)/perspdiv in:
	 * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */

	wmat[0][0] = pv1[0];  wmat[1][0] = pv2[0];  wmat[2][0] = pv3[0];
	wmat[0][1] = pv1[1];  wmat[1][1] = pv2[1];  wmat[2][1] = pv3[1];
	wmat[0][2] = pv1[3];  wmat[1][2] = pv2[3];  wmat[2][2] = pv3[3];

	invert_m3_m3(invwmat, wmat);
	mul_m3_v3(invwmat, h);

	copy_v3_v3(w, h);

	/* w is still divided by perspdiv, make it sum to one */
	divw = w[0] + w[1] + w[2];
	if (divw != 0.0f) {
		mul_v3_fl(w, 1.0f / divw);
	}
}
示例#22
0
static void applyAxisConstraintVec(TransInfo *t,
                                   TransDataContainer *UNUSED(tc),
                                   TransData *td,
                                   const float in[3],
                                   float out[3],
                                   float pvec[3])
{
  copy_v3_v3(out, in);
  if (!td && t->con.mode & CON_APPLY) {
    mul_m3_v3(t->con.pmtx, out);

    // With snap, a projection is alright, no need to correct for view alignment
    if (!validSnap(t)) {
      const int dims = getConstraintSpaceDimension(t);
      if (dims == 2) {
        if (!is_zero_v3(out)) {
          if (!isPlaneProjectionViewAligned(t)) {
            planeProjection(t, in, out);
          }
        }
      }
      else if (dims == 1) {
        float c[3];

        if (t->con.mode & CON_AXIS0) {
          copy_v3_v3(c, t->con.mtx[0]);
        }
        else if (t->con.mode & CON_AXIS1) {
          copy_v3_v3(c, t->con.mtx[1]);
        }
        else if (t->con.mode & CON_AXIS2) {
          copy_v3_v3(c, t->con.mtx[2]);
        }
        axisProjection(t, c, in, out);
      }
    }
    postConstraintChecks(t, out, pvec);
  }
}
示例#23
0
static void imapaint_tri_weights(float matrix[4][4], GLint view[4],
                                 const float v1[3], const float v2[3], const float v3[3],
                                 const float co[2], float w[3])
{
	float pv1[4], pv2[4], pv3[4], h[3], divw;
	float wmat[3][3], invwmat[3][3];

	/* compute barycentric coordinates */

	/* project the verts */
	imapaint_project(matrix, v1, pv1);
	imapaint_project(matrix, v2, pv2);
	imapaint_project(matrix, v3, pv3);

	/* do inverse view mapping, see gluProject man page */
	h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f;
	h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f;
	h[2] = 1.0f;

	/* solve for (w1,w2,w3)/perspdiv in:
	 * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */

	wmat[0][0] = pv1[0];  wmat[1][0] = pv2[0];  wmat[2][0] = pv3[0];
	wmat[0][1] = pv1[1];  wmat[1][1] = pv2[1];  wmat[2][1] = pv3[1];
	wmat[0][2] = pv1[3];  wmat[1][2] = pv2[3];  wmat[2][2] = pv3[3];

	invert_m3_m3(invwmat, wmat);
	mul_m3_v3(invwmat, h);

	copy_v3_v3(w, h);

	/* w is still divided by perspdiv, make it sum to one */
	divw = w[0] + w[1] + w[2];
	if (divw != 0.0f) {
		mul_v3_fl(w, 1.0f / divw);
	}
}
示例#24
0
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op))
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	RegionView3D *rv3d = CTX_wm_region_data(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float gridf, imat[3][3], bmat[3][3], vec[3];
	int a;

	gridf = rv3d->gridview;

	if (obedit) {
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		tv = tvs.transverts;
		for (a = 0; a < tvs.transverts_tot; a++, tv++) {
			copy_v3_v3(vec, tv->loc);
			mul_m3_v3(bmat, vec);
			add_v3_v3(vec, obedit->obmat[3]);
			vec[0] = gridf * floorf(0.5f + vec[0] / gridf);
			vec[1] = gridf * floorf(0.5f + vec[1] / gridf);
			vec[2] = gridf * floorf(0.5f + vec[2] / gridf);
			sub_v3_v3(vec, obedit->obmat[3]);
			
			mul_m3_v3(imat, vec);
			copy_v3_v3(tv->loc, vec);
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects)
		{
			if (ob->mode & OB_MODE_POSE) {
				bPoseChannel *pchan;
				bArmature *arm = ob->data;
				
				invert_m4_m4(ob->imat, ob->obmat);
				
				for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
					if (pchan->bone->flag & BONE_SELECTED) {
						if (pchan->bone->layer & arm->layer) {
							if ((pchan->bone->flag & BONE_CONNECTED) == 0) {
								float nLoc[3];
								
								/* get nearest grid point to snap to */
								copy_v3_v3(nLoc, pchan->pose_mat[3]);
								/* We must operate in world space! */
								mul_m4_v3(ob->obmat, nLoc);
								vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf);
								vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf);
								vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf);
								/* Back in object space... */
								mul_m4_v3(ob->imat, vec);
								
								/* Get location of grid point in pose space. */
								BKE_armature_loc_pose_to_bone(pchan, vec, vec);
								
								/* adjust location */
								if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
									pchan->loc[0] = vec[0];
								if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
									pchan->loc[1] = vec[1];
								if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
									pchan->loc[2] = vec[2];

								/* auto-keyframing */
								ED_autokeyframe_pchan(C, scene, ob, pchan, ks);
							}
							/* if the bone has a parent and is connected to the parent,
							 * don't do anything - will break chain unless we do auto-ik.
							 */
						}
					}
				}
				ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
				
				DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
			}
			else {
				vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf);
				vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf);
				vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf);
				
				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);
					
					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, vec);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += vec[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += vec[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += vec[2];
				
				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}
		CTX_DATA_END;
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
示例#25
0
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3])
{
	Object *obedit = CTX_data_edit_object(C);
	Scene *scene = CTX_data_scene(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float bmat[3][3], vec[3], min[3], max[3], centroid[3];
	int count, a;

	count = 0;
	INIT_MINMAX(min, max);
	zero_v3(centroid);

	if (obedit) {

		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES);

		if (tvs.transverts_tot == 0) {
			return false;
		}

		copy_m3_m4(bmat, obedit->obmat);
		
		tv = tvs.transverts;
		for (a = 0; a < tvs.transverts_tot; a++, tv++) {
			copy_v3_v3(vec, tv->loc);
			mul_m3_v3(bmat, vec);
			add_v3_v3(vec, obedit->obmat[3]);
			add_v3_v3(centroid, vec);
			minmax_v3v3_v3(min, max, vec);
		}
		
		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}

		ED_transverts_free(&tvs);
	}
	else {
		Object *obact = CTX_data_active_object(C);
		
		if (obact && (obact->mode & OB_MODE_POSE)) {
			bArmature *arm = obact->data;
			bPoseChannel *pchan;
			for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
				if (arm->layer & pchan->bone->layer) {
					if (pchan->bone->flag & BONE_SELECTED) {
						copy_v3_v3(vec, pchan->pose_head);
						mul_m4_v3(obact->obmat, vec);
						add_v3_v3(centroid, vec);
						minmax_v3v3_v3(min, max, vec);
						count++;
					}
				}
			}
		}
		else {
			CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
			{
				copy_v3_v3(vec, ob->obmat[3]);

				/* special case for camera -- snap to bundles */
				if (ob->type == OB_CAMERA) {
					/* snap to bundles should happen only when bundles are visible */
					if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) {
						bundle_midpoint(scene, ob, vec);
					}
				}

				add_v3_v3(centroid, vec);
				minmax_v3v3_v3(min, max, vec);
				count++;
			}
			CTX_DATA_END;
		}

		if (count == 0) {
			return false;
		}

		if (v3d->around == V3D_AROUND_CENTER_MEAN) {
			mul_v3_fl(centroid, 1.0f / (float)count);
			copy_v3_v3(cursor, centroid);
		}
		else {
			mid_v3_v3v3(cursor, min, max);
		}
	}
示例#26
0
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset)
{
	Scene *scene = CTX_data_scene(C);
	Object *obedit = CTX_data_edit_object(C);
	Object *obact = CTX_data_active_object(C);
	View3D *v3d = CTX_wm_view3d(C);
	TransVertStore tvs = {NULL};
	TransVert *tv;
	float imat[3][3], bmat[3][3];
	float center_global[3];
	float offset_global[3];
	int a;

	if (use_offset) {
		if ((v3d && v3d->around == V3D_AROUND_ACTIVE) &&
		    snap_calc_active_center(C, true, center_global))
		{
			/* pass */
		}
		else {
			snap_curs_to_sel_ex(C, center_global);
		}
		sub_v3_v3v3(offset_global, snap_target_global, center_global);
	}

	if (obedit) {
		float snap_target_local[3];
		
		if (ED_transverts_check_obedit(obedit))
			ED_transverts_create_from_obedit(&tvs, obedit, 0);
		if (tvs.transverts_tot == 0)
			return OPERATOR_CANCELLED;

		copy_m3_m4(bmat, obedit->obmat);
		invert_m3_m3(imat, bmat);
		
		/* get the cursor in object space */
		sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]);
		mul_m3_v3(imat, snap_target_local);

		if (use_offset) {
			float offset_local[3];

			mul_v3_m3v3(offset_local, imat, offset_global);

			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				add_v3_v3(tv->loc, offset_local);
			}
		}
		else {
			tv = tvs.transverts;
			for (a = 0; a < tvs.transverts_tot; a++, tv++) {
				copy_v3_v3(tv->loc, snap_target_local);
			}
		}
		
		ED_transverts_update_obedit(&tvs, obedit);
		ED_transverts_free(&tvs);
	}
	else if (obact && (obact->mode & OB_MODE_POSE)) {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);

		bPoseChannel *pchan;
		bArmature *arm = obact->data;
		float snap_target_local[3];

		invert_m4_m4(obact->imat, obact->obmat);
		mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global);

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_SELECTED) &&
			    (PBONE_VISIBLE(arm, pchan->bone)) &&
			    /* if the bone has a parent and is connected to the parent,
			     * don't do anything - will break chain unless we do auto-ik.
			     */
			    (pchan->bone->flag & BONE_CONNECTED) == 0)
			{
				pchan->bone->flag |= BONE_TRANSFORM;
			}
			else {
				pchan->bone->flag &= ~BONE_TRANSFORM;
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			if ((pchan->bone->flag & BONE_TRANSFORM) &&
			    /* check that our parents not transformed (if we have one) */
			    ((pchan->bone->parent &&
			      BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0))
			{
				/* Get position in pchan (pose) space. */
				float cursor_pose[3];

				if (use_offset) {
					mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]);
					add_v3_v3(cursor_pose, offset_global);

					mul_m4_v3(obact->imat, cursor_pose);
					BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose);
				}
				else {
					BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose);
				}

				/* copy new position */
				if ((pchan->protectflag & OB_LOCK_LOCX) == 0)
					pchan->loc[0] = cursor_pose[0];
				if ((pchan->protectflag & OB_LOCK_LOCY) == 0)
					pchan->loc[1] = cursor_pose[1];
				if ((pchan->protectflag & OB_LOCK_LOCZ) == 0)
					pchan->loc[2] = cursor_pose[2];

				/* auto-keyframing */
				ED_autokeyframe_pchan(C, scene, obact, pchan, ks);
			}
		}

		for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) {
			pchan->bone->flag &= ~BONE_TRANSFORM;
		}

		obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);

		DAG_id_tag_update(&obact->id, OB_RECALC_DATA);
	}
	else {
		struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
		Main *bmain = CTX_data_main(C);

		ListBase ctx_data_list;
		CollectionPointerLink *ctx_ob;
		Object *ob;

		CTX_data_selected_editable_objects(C, &ctx_data_list);

		/* reset flags */
		for (ob = bmain->object.first; ob; ob = ob->id.next) {
			ob->flag &= ~OB_DONE;
		}

		/* tag objects we're transforming */
		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;
			ob->flag |= OB_DONE;
		}

		for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) {
			ob = ctx_ob->ptr.data;

			if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) {

				float cursor_parent[3];  /* parent-relative */

				if (use_offset) {
					add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global);
				}
				else {
					copy_v3_v3(cursor_parent, snap_target_global);
				}

				sub_v3_v3(cursor_parent, ob->obmat[3]);

				if (ob->parent) {
					float originmat[3][3];
					BKE_object_where_is_calc_ex(scene, NULL, ob, originmat);

					invert_m3_m3(imat, originmat);
					mul_m3_v3(imat, cursor_parent);
				}
				if ((ob->protectflag & OB_LOCK_LOCX) == 0)
					ob->loc[0] += cursor_parent[0];
				if ((ob->protectflag & OB_LOCK_LOCY) == 0)
					ob->loc[1] += cursor_parent[1];
				if ((ob->protectflag & OB_LOCK_LOCZ) == 0)
					ob->loc[2] += cursor_parent[2];

				/* auto-keyframing */
				ED_autokeyframe_object(C, scene, ob, ks);

				DAG_id_tag_update(&ob->id, OB_RECALC_OB);
			}
		}

		BLI_freelistN(&ctx_data_list);
	}

	WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
	
	return OPERATOR_FINISHED;
}
示例#27
0
/* only valid for perspective cameras */
int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3])
{
	float shift[2];
	float plane_tx[4][3];
	float rot_obmat[3][3];
	const float zero[3]= {0,0,0};
	CameraViewFrameData data_cb;

	unsigned int i;

	camera_view_frame(scene, camera_ob->data, data_cb.frame_tx);

	copy_m3_m4(rot_obmat, camera_ob->obmat);
	normalize_m3(rot_obmat);

	for (i= 0; i < 4; i++) {
		/* normalize so Z is always 1.0f*/
		mul_v3_fl(data_cb.frame_tx[i], 1.0f/data_cb.frame_tx[i][2]);
	}

	/* get the shift back out of the frame */
	shift[0]= (data_cb.frame_tx[0][0] +
	           data_cb.frame_tx[1][0] +
	           data_cb.frame_tx[2][0] +
	           data_cb.frame_tx[3][0]) / 4.0f;
	shift[1]= (data_cb.frame_tx[0][1] +
	           data_cb.frame_tx[1][1] +
	           data_cb.frame_tx[2][1] +
	           data_cb.frame_tx[3][1]) / 4.0f;

	for (i= 0; i < 4; i++) {
		mul_m3_v3(rot_obmat, data_cb.frame_tx[i]);
	}

	for (i= 0; i < 4; i++) {
		normal_tri_v3(data_cb.normal_tx[i],
		              zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]);
	}

	/* initialize callback data */
	data_cb.dist_vals[0]=
	data_cb.dist_vals[1]=
	data_cb.dist_vals[2]=
	data_cb.dist_vals[3]= FLT_MAX;
	data_cb.tot= 0;
	/* run callback on all visible points */
	BKE_scene_foreach_display_point(scene, v3d, BA_SELECT,
	                                camera_to_frame_view_cb, &data_cb);

	if (data_cb.tot <= 1) {
		return FALSE;
	}
	else {
		float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3];
		float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3];

		float plane_isect_pt_1[3], plane_isect_pt_2[3];

		/* apply the dist-from-plane's to the transformed plane points */
		for (i= 0; i < 4; i++) {
			mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]);
		}

		isect_plane_plane_v3(plane_isect_1, plane_isect_1_no,
		                     plane_tx[0], data_cb.normal_tx[0],
		                     plane_tx[2], data_cb.normal_tx[2]);
		isect_plane_plane_v3(plane_isect_2, plane_isect_2_no,
		                     plane_tx[1], data_cb.normal_tx[1],
		                     plane_tx[3], data_cb.normal_tx[3]);

		add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no);
		add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no);

		if (isect_line_line_v3(plane_isect_1, plane_isect_1_other,
		                       plane_isect_2, plane_isect_2_other,
		                       plane_isect_pt_1, plane_isect_pt_2) == 0)
		{
			return FALSE;
		}
		else {
			float cam_plane_no[3]= {0.0f, 0.0f, -1.0f};
			float plane_isect_delta[3];
			float plane_isect_delta_len;

			mul_m3_v3(rot_obmat, cam_plane_no);

			sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1);
			plane_isect_delta_len= len_v3(plane_isect_delta);

			if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) {
				copy_v3_v3(r_co, plane_isect_pt_1);

				/* offset shift */
				normalize_v3(plane_isect_1_no);
				madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len);
			}
			else {
				copy_v3_v3(r_co, plane_isect_pt_2);

				/* offset shift */
				normalize_v3(plane_isect_2_no);
				madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len);
			}


			return TRUE;
		}
	}
}
示例#28
0
static void meshcache_do(
        MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm),
        float (*vertexCos_Real)[3], int numVerts)
{
	const bool use_factor = mcmd->factor < 1.0f;
	float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ?
	                              MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL;
	float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;

	Scene *scene = mcmd->modifier.scene;
	const float fps = FPS;

	char filepath[FILE_MAX];
	const char *err_str = NULL;
	bool ok;

	float time;


	/* -------------------------------------------------------------------- */
	/* Interpret Time (the reading functions also do some of this ) */
	if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
		const float cfra = BKE_scene_frame_get(scene);

		switch (mcmd->time_mode) {
			case MOD_MESHCACHE_TIME_FRAME:
			{
				time = cfra;
				break;
			}
			case MOD_MESHCACHE_TIME_SECONDS:
			{
				time = cfra / fps;
				break;
			}
			case MOD_MESHCACHE_TIME_FACTOR:
			default:
			{
				time = cfra / fps;
				break;
			}
		}

		/* apply offset and scale */
		time = (mcmd->frame_scale * time) - mcmd->frame_start;
	}
	else {  /*  if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */
		switch (mcmd->time_mode) {
			case MOD_MESHCACHE_TIME_FRAME:
			{
				time = mcmd->eval_frame;
				break;
			}
			case MOD_MESHCACHE_TIME_SECONDS:
			{
				time = mcmd->eval_time;
				break;
			}
			case MOD_MESHCACHE_TIME_FACTOR:
			default:
			{
				time = mcmd->eval_factor;
				break;
			}
		}
	}


	/* -------------------------------------------------------------------- */
	/* Read the File (or error out when the file is bad) */

	/* would be nice if we could avoid doing this _every_ frame */
	BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath));
	BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob));

	switch (mcmd->type) {
		case MOD_MESHCACHE_TYPE_MDD:
			ok = MOD_meshcache_read_mdd_times(filepath, vertexCos, numVerts,
			                                  mcmd->interp, time, fps, mcmd->time_mode, &err_str);
			break;
		case MOD_MESHCACHE_TYPE_PC2:
			ok = MOD_meshcache_read_pc2_times(filepath, vertexCos, numVerts,
			                                  mcmd->interp, time, fps, mcmd->time_mode, &err_str);
			break;
		default:
			ok = false;
			break;
	}


	/* -------------------------------------------------------------------- */
	/* tricky shape key integration (slow!) */
	if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) {
		Mesh *me = ob->data;

		/* we could support any object type */
		if (UNLIKELY(ob->type != OB_MESH)) {
			modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects");
		}
		else if (UNLIKELY(me->totvert != numVerts)) {
			modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch");
		}
		else if (UNLIKELY(me->totpoly == 0)) {
			modifier_setError(&mcmd->modifier, "'Integrate' requires faces");
		}
		else {
			/* the moons align! */
			int i;

			float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__);
			float (*vertexCos_New)[3]    = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__);
			MVert *mv = me->mvert;

			for (i = 0; i < numVerts; i++, mv++) {
				copy_v3_v3(vertexCos_Source[i], mv->co);
			}

			BKE_mesh_calc_relative_deform(
			        me->mpoly, me->totpoly,
			        me->mloop, me->totvert,

			        (const float (*)[3])vertexCos_Source,   /* from the original Mesh*/
			        (const float (*)[3])vertexCos_Real,     /* the input we've been given (shape keys!) */

			        (const float (*)[3])vertexCos,          /* the result of this modifier */
			        vertexCos_New                           /* the result of this function */
			        );

			/* write the corrected locations back into the result */
			memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts);

			MEM_freeN(vertexCos_Source);
			MEM_freeN(vertexCos_New);
		}
	}


	/* -------------------------------------------------------------------- */
	/* Apply the transformation matrix (if needed) */
	if (UNLIKELY(err_str)) {
		modifier_setError(&mcmd->modifier, "%s", err_str);
	}
	else if (ok) {
		bool use_matrix = false;
		float mat[3][3];
		unit_m3(mat);

		if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) {
			use_matrix = true;
		}

		if (mcmd->flip_axis) {
			float tmat[3][3];
			unit_m3(tmat);
			if (mcmd->flip_axis & (1 << 0)) tmat[0][0] = -1.0f;
			if (mcmd->flip_axis & (1 << 1)) tmat[1][1] = -1.0f;
			if (mcmd->flip_axis & (1 << 2)) tmat[2][2] = -1.0f;
			mul_m3_m3m3(mat, tmat, mat);

			use_matrix = true;
		}

		if (use_matrix) {
			int i;
			for (i = 0; i < numVerts; i++) {
				mul_m3_v3(mat, vertexCos[i]);
			}
		}
	}

	if (vertexCos_Store) {
		if (ok) {
			if (use_factor) {
				interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
			}
			else {
				memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts);
			}
		}

		MEM_freeN(vertexCos_Store);
	}
}
示例#29
0
/**
 * This function converts an object space normal map to a tangent space normal map for a given low poly mesh
 */
void RE_bake_normal_world_to_tangent(
        const BakePixel pixel_array[], const size_t num_pixels, const int depth,
        float result[], Mesh *me, const BakeNormalSwizzle normal_swizzle[3],
        float mat[4][4])
{
	size_t i;

	TriTessFace *triangles;

	DerivedMesh *dm = CDDM_from_mesh(me);

	triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh");
	mesh_calc_tri_tessface(triangles, me, true, dm);

	BLI_assert(num_pixels >= 3);

	for (i = 0; i < num_pixels; i++) {
		TriTessFace *triangle;
		float tangents[3][3];
		float normals[3][3];
		float signs[3];
		int j;

		float tangent[3];
		float normal[3];
		float binormal[3];
		float sign;
		float u, v, w;

		float tsm[3][3]; /* tangent space matrix */
		float itsm[3][3];

		size_t offset;
		float nor[3]; /* texture normal */

		bool is_smooth;

		int primitive_id = pixel_array[i].primitive_id;

		offset = i * depth;

		if (primitive_id == -1) {
			copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f);
			continue;
		}

		triangle = &triangles[primitive_id];
		is_smooth = triangle->is_smooth;

		for (j = 0; j < 3; j++) {
			const TSpace *ts;

			if (is_smooth)
				normal_short_to_float_v3(normals[j], triangle->mverts[j]->no);
			else
				normal[j] = triangle->normal[j];

			ts = triangle->tspace[j];
			copy_v3_v3(tangents[j], ts->tangent);
			signs[j] = ts->sign;
		}

		u = pixel_array[i].uv[0];
		v = pixel_array[i].uv[1];
		w = 1.0f - u - v;

		/* normal */
		if (is_smooth)
			interp_barycentric_tri_v3(normals, u, v, normal);

		/* tangent */
		interp_barycentric_tri_v3(tangents, u, v, tangent);

		/* sign */
		/* The sign is the same at all face vertices for any non degenerate face.
		 * Just in case we clamp the interpolated value though. */
		sign = (signs[0]  * u + signs[1]  * v + signs[2] * w) < 0 ? (-1.0f) : 1.0f;

		/* binormal */
		/* B = sign * cross(N, T)  */
		cross_v3_v3v3(binormal, normal, tangent);
		mul_v3_fl(binormal, sign);

		/* populate tangent space matrix */
		copy_v3_v3(tsm[0], tangent);
		copy_v3_v3(tsm[1], binormal);
		copy_v3_v3(tsm[2], normal);

		/* texture values */
		normal_uncompress(nor, &result[offset]);

		/* converts from world space to local space */
		mul_transposed_mat3_m4_v3(mat, nor);

		invert_m3_m3(itsm, tsm);
		mul_m3_v3(itsm, nor);
		normalize_v3(nor);

		/* save back the values */
		normal_compress(&result[offset], nor, normal_swizzle);
	}

	/* garbage collection */
	MEM_freeN(triangles);

	if (dm)
		dm->release(dm);
}
/* the ctrl-click method */
static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
	View3D *v3d;
	bArmature *arm;
	EditBone *ebone, *newbone, *flipbone;
	float mat[3][3], imat[3][3];
	const float *curs;
	int a, to_root = 0;
	Object *obedit;
	Scene *scene;

	scene = CTX_data_scene(C);
	v3d = CTX_wm_view3d(C);
	obedit = CTX_data_edit_object(C);
	arm = obedit->data;
	
	/* find the active or selected bone */
	for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
		if (EBONE_VISIBLE(arm, ebone)) {
			if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone)
				break;
		}
	}
	
	if (ebone == NULL) {
		for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
			if (EBONE_VISIBLE(arm, ebone)) {
				if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone)
					break;
			}
		}
		if (ebone == NULL) 
			return OPERATOR_CANCELLED;
		
		to_root = 1;
	}
	
	ED_armature_deselect_all(obedit);
	
	/* we re-use code for mirror editing... */
	flipbone = NULL;
	if (arm->flag & ARM_MIRROR_EDIT)
		flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);

	for (a = 0; a < 2; a++) {
		if (a == 1) {
			if (flipbone == NULL)
				break;
			else {
				SWAP(EditBone *, flipbone, ebone);
			}
		}
		
		newbone = ED_armature_edit_bone_add(arm, ebone->name);
		arm->act_edbone = newbone;
		
		if (to_root) {
			copy_v3_v3(newbone->head, ebone->head);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone->parent;
		}
		else {
			copy_v3_v3(newbone->head, ebone->tail);
			newbone->rad_head = ebone->rad_tail;
			newbone->parent = ebone;
			newbone->flag |= BONE_CONNECTED;
		}
		
		curs = ED_view3d_cursor3d_get(scene, v3d);
		copy_v3_v3(newbone->tail, curs);
		sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]);
		
		if (a == 1)
			newbone->tail[0] = -newbone->tail[0];
		
		copy_m3_m4(mat, obedit->obmat);
		invert_m3_m3(imat, mat);
		mul_m3_v3(imat, newbone->tail);
		
		newbone->length = len_v3v3(newbone->head, newbone->tail);
		newbone->rad_tail = newbone->length * 0.05f;
		newbone->dist = newbone->length * 0.25f;
		
	}
	
	ED_armature_sync_selection(arm->edbo);

	WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
	
	return OPERATOR_FINISHED;
}