Example #1
0
static float bm_edge_calc_rotate_beauty__angle(
        const float v1[3], const float v2[3], const float v3[3], const float v4[3])
{
	/* not a loop (only to be able to break out) */
	do {
		float no_a[3], no_b[3];
		float angle_24, angle_13;

		/* edge (2-4), current state */
		normal_tri_v3(no_a, v2, v3, v4);
		normal_tri_v3(no_b, v2, v4, v1);
		angle_24 = angle_normalized_v3v3(no_a, no_b);

		/* edge (1-3), new state */
		/* only check new state for degenerate outcome */
		if ((normal_tri_v3(no_a, v1, v2, v3) == 0.0f) ||
		    (normal_tri_v3(no_b, v1, v3, v4) == 0.0f))
		{
			break;
		}
		angle_13 = angle_normalized_v3v3(no_a, no_b);

		return angle_13 - angle_24;
	} while (false);

	return FLT_MAX;
}
Example #2
0
static void bvh_callback(void *userdata, int index, const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit)
{
	BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata;
	MFace *mf = data->sys->heat.mface + index;
	float (*verts)[3] = data->sys->heat.verts;
	float lambda, uv[2], n[3], dir[3];

	mul_v3_v3fl(dir, data->vec, hit->dist);

	if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v2], verts[mf->v3], &lambda, uv)) {
		normal_tri_v3(n, verts[mf->v1], verts[mf->v2], verts[mf->v3]);
		if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
			hit->index = index;
			hit->dist *= lambda;
		}
	}

	mul_v3_v3fl(dir, data->vec, hit->dist);

	if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v3], verts[mf->v4], &lambda, uv)) {
		normal_tri_v3(n, verts[mf->v1], verts[mf->v3], verts[mf->v4]);
		if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
			hit->index = index;
			hit->dist *= lambda;
		}
	}
}
Example #3
0
static int meshdeform_intersect(MeshDeformBind *mdb, MeshDeformIsect *isec)
{
	MFace *mface;
	float face[4][3], co[3], uvw[3], len, nor[3], end[3];
	int f, hit, is= 0, totface;

	isec->labda= 1e10;

	mface= mdb->cagedm->getFaceArray(mdb->cagedm);
	totface= mdb->cagedm->getNumFaces(mdb->cagedm);

	add_v3_v3v3(end, isec->start, isec->vec);

	for(f=0; f<totface; f++, mface++) {
		copy_v3_v3(face[0], mdb->cagecos[mface->v1]);
		copy_v3_v3(face[1], mdb->cagecos[mface->v2]);
		copy_v3_v3(face[2], mdb->cagecos[mface->v3]);

		if(mface->v4) {
			copy_v3_v3(face[3], mdb->cagecos[mface->v4]);
			hit = meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw);

			if(hit) {
				normal_tri_v3( nor,face[0], face[1], face[2]);
			}
			else {
				hit= meshdeform_tri_intersect(isec->start, end, face[0], face[2], face[3], co, uvw);
				normal_tri_v3( nor,face[0], face[2], face[3]);
			}
		}
		else {
			hit= meshdeform_tri_intersect(isec->start, end, face[0], face[1], face[2], co, uvw);
			normal_tri_v3( nor,face[0], face[1], face[2]);
		}

		if(hit) {
			len= len_v3v3(isec->start, co)/len_v3v3(isec->start, end);
			if(len < isec->labda) {
				isec->labda= len;
				isec->face = mface;
				isec->isect= (INPR(isec->vec, nor) <= 0.0f);
				is= 1;
			}
		}
	}

	return is;
}
Example #4
0
/* Callback to bvh tree nearest point. The tree must have been built using bvhtree_from_mesh_faces.
 * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	const MVert *vert = data->vert;
	const MFace *face = data->face + index;

	const float *t0, *t1, *t2, *t3;
	t0 = vert[face->v1].co;
	t1 = vert[face->v2].co;
	t2 = vert[face->v3].co;
	t3 = face->v4 ? vert[face->v4].co : NULL;

	
	do {
		float nearest_tmp[3], dist_sq;

		closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
		dist_sq = len_squared_v3v3(co, nearest_tmp);

		if (dist_sq < nearest->dist_sq) {
			nearest->index = index;
			nearest->dist_sq = dist_sq;
			copy_v3_v3(nearest->co, nearest_tmp);
			normal_tri_v3(nearest->no, t0, t1, t2);
		}

		t1 = t2;
		t2 = t3;
		t3 = NULL;

	} while (t2);
}
Example #5
0
static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index)
{
	unsigned int indices[]= {data->mface[face_num].v1, data->mface[face_num].v2,
	                         data->mface[face_num].v3, data->mface[face_num].v4};
	const int smoothnormal= (data->mface[face_num].flag & ME_SMOOTH);

	if(!smoothnormal)  { /* flat */
		if(data->precomputed_normals) {
			copy_v3_v3(norm, &data->precomputed_normals[3*face_num]);
		} else {
			float nor[3];
			float *p0, *p1, *p2;
			const int iGetNrVerts= data->mface[face_num].v4!=0 ? 4 : 3;

			p0= data->mvert[indices[0]].co;
			p1= data->mvert[indices[1]].co;
			p2= data->mvert[indices[2]].co;

			if(iGetNrVerts==4) {
				float *p3= data->mvert[indices[3]].co;
				normal_quad_v3(nor, p0, p1, p2, p3);
			} else {
				normal_tri_v3(nor, p0, p1, p2);
			}

			copy_v3_v3(norm, nor);
		}
	} else {
		short *no= data->mvert[indices[vert_index]].no;

		normal_short_to_float_v3(norm, no);
		normalize_v3(norm);
	}
}
Example #6
0
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
static void editmesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	BMEditMesh *em = data->em_evil;
	const BMLoop **ltri = (const BMLoop **)em->looptris[index];

	const float *t0, *t1, *t2;
	t0 = ltri[0]->v->co;
	t1 = ltri[1]->v->co;
	t2 = ltri[2]->v->co;

	{
		float nearest_tmp[3], dist_sq;

		closest_on_tri_to_point_v3(nearest_tmp, co, t0, t1, t2);
		dist_sq = len_squared_v3v3(co, nearest_tmp);

		if (dist_sq < nearest->dist_sq) {
			nearest->index = index;
			nearest->dist_sq = dist_sq;
			copy_v3_v3(nearest->co, nearest_tmp);
			normal_tri_v3(nearest->no, t0, t1, t2);
		}
	}
}
static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
	BVHCallbackUserData *data = (struct BVHCallbackUserData *)userdata;
	const MLoopTri *lt = &data->sys->heat.mlooptri[index];
	const MLoop *mloop = data->sys->heat.mloop;
	float (*verts)[3] = data->sys->heat.verts;
	const float *vtri_co[3];
	float dist_test;

	vtri_co[0] = verts[mloop[lt->tri[0]].v];
	vtri_co[1] = verts[mloop[lt->tri[1]].v];
	vtri_co[2] = verts[mloop[lt->tri[2]].v];

#ifdef USE_KDOPBVH_WATERTIGHT
	if (isect_ray_tri_watertight_v3(data->start, ray->isect_precalc, UNPACK3(vtri_co), &dist_test, NULL))
#else
	UNUSED_VARS(ray);
	if (isect_ray_tri_v3(data->start, data->vec, UNPACK3(vtri_co), &dist_test, NULL))
#endif
	{
		if (dist_test < hit->dist) {
			float n[3];
			normal_tri_v3(n, UNPACK3(vtri_co));
			if (dot_v3v3(n, data->vec) < -1e-5f) {
				hit->index = index;
				hit->dist = dist_test;
			}
		}
	}
}
Example #8
0
/* Callback to bvh tree nearest point. The tree must bust have been built using bvhtree_from_mesh_faces.
 * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	MVert *vert = data->vert;
	MFace *face = data->face + index;

	float *t0, *t1, *t2, *t3;
	t0 = vert[face->v1].co;
	t1 = vert[face->v2].co;
	t2 = vert[face->v3].co;
	t3 = face->v4 ? vert[face->v4].co : NULL;

	
	do {
		float nearest_tmp[3], dist;
		int vertex, edge;
		
		dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
		if (dist < nearest->dist) {
			nearest->index = index;
			nearest->dist = dist;
			copy_v3_v3(nearest->co, nearest_tmp);
			normal_tri_v3(nearest->no, t0, t1, t2);

			if (t1 == vert[face->v3].co)
				nearest->flags |= BVH_ONQUAD;
		}

		t1 = t2;
		t2 = t3;
		t3 = NULL;

	} while (t2);
}
Example #9
0
static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
{
	int i, totface;
	int start;
	float f_no[3];

	float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
	MVert *mvert = dm->getVertArray(dm);
	MFace *f = dm->getFaceArray(dm);

	totface= dm->getNumFaces(dm);
	for(i = 0; i < totface; i++, f++) {
		const int smoothnormal = (f->flag & ME_SMOOTH);

		start = index[mat_orig_to_new[f->mat_nr]];
		index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;

		if(smoothnormal) {
			/* copy vertex normal */
			normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
 			normal_short_to_float_v3(&varray[start+3], mvert[f->v2].no);
			normal_short_to_float_v3(&varray[start+6], mvert[f->v3].no);

			if(f->v4) {
				normal_short_to_float_v3(&varray[start+9], mvert[f->v3].no);
				normal_short_to_float_v3(&varray[start+12], mvert[f->v4].no);
				normal_short_to_float_v3(&varray[start+15], mvert[f->v1].no);
			}
		}
		else if(nors) {
			/* copy cached face normal */
			copy_v3_v3(&varray[start], &nors[i*3]);
			copy_v3_v3(&varray[start+3], &nors[i*3]);
			copy_v3_v3(&varray[start+6], &nors[i*3]);

			if(f->v4) {
				copy_v3_v3(&varray[start+9], &nors[i*3]);
				copy_v3_v3(&varray[start+12], &nors[i*3]);
				copy_v3_v3(&varray[start+15], &nors[i*3]);
			}
		}
		else {
			/* calculate face normal */
			if(f->v4)
				normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
			else
				normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);

			copy_v3_v3(&varray[start], f_no);
			copy_v3_v3(&varray[start+3], f_no);
			copy_v3_v3(&varray[start+6], f_no);

			if(f->v4) {
				copy_v3_v3(&varray[start+9], f_no);
				copy_v3_v3(&varray[start+12], f_no);
				copy_v3_v3(&varray[start+15], f_no);
			}
		}
	}
}
Example #10
0
/* Callback to bvh tree raycast. The tree must have been built using bvhtree_from_mesh_faces.
 * userdata must be a BVHMeshCallbackUserdata built from the same mesh as the tree. */
static void mesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	const MVert *vert = data->vert;
	const MFace *face = &data->face[index];

	const float *t0, *t1, *t2, *t3;
	t0 = vert[face->v1].co;
	t1 = vert[face->v2].co;
	t2 = vert[face->v3].co;
	t3 = face->v4 ? vert[face->v4].co : NULL;

	
	do {
		float dist;
		if (data->sphere_radius == 0.0f)
			dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
		else
			dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);

		if (dist >= 0 && dist < hit->dist) {
			hit->index = index;
			hit->dist = dist;
			madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);

			normal_tri_v3(hit->no, t0, t1, t2);
		}

		t1 = t2;
		t2 = t3;
		t3 = NULL;

	} while (t2);
}
Example #11
0
/* copy of function above */
static void mesh_looptri_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	const MVert *vert = data->vert;
	const MLoopTri *lt = &data->looptri[index];
	const float *vtri_co[3] = {
	    vert[data->loop[lt->tri[0]].v].co,
	    vert[data->loop[lt->tri[1]].v].co,
	    vert[data->loop[lt->tri[2]].v].co,
	};
	float dist;

	if (data->sphere_radius == 0.0f)
		dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(vtri_co));
	else
		dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, UNPACK3(vtri_co));

	if (dist >= 0 && dist < hit->dist) {
		hit->index = index;
		hit->dist = dist;
		madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);

		normal_tri_v3(hit->no, UNPACK3(vtri_co));
	}
}
Example #12
0
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
static void editmesh_faces_spherecast(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	BMEditMesh *em = data->em_evil;
	const BMLoop **ltri = (const BMLoop **)em->looptris[index];

	const float *t0, *t1, *t2;
	t0 = ltri[0]->v->co;
	t1 = ltri[1]->v->co;
	t2 = ltri[2]->v->co;


	{
		float dist;
		if (data->sphere_radius == 0.0f)
			dist = bvhtree_ray_tri_intersection(ray, hit->dist, t0, t1, t2);
		else
			dist = bvhtree_sphereray_tri_intersection(ray, data->sphere_radius, hit->dist, t0, t1, t2);

		if (dist >= 0 && dist < hit->dist) {
			hit->index = index;
			hit->dist = dist;
			madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);

			normal_tri_v3(hit->no, t0, t1, t2);
		}
	}
}
/**
 * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
 * The Linear system is LV = d
 * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
 * The Laplacian Matrix is computes as a
 * Lij = sum(Wij) (if i == j)
 * Lij = Wij (if i != j)
 * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
 *
 * The Differential Coordinate is computes as a
 * di = Vi * sum(Wij) - sum(Wij * Vj)
 * Where :
 * di is the Differential Coordinate i
 * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
 * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
 *
 * This Laplacian Matrix is described in the paper:
 * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
 * New York, USA
 *
 * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
 * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
 * Conference on Graphics Patterns and Images, SIBGRAPI, 2013
 *
 * The computation of Differential Coordinates is described in the paper:
 * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
 * 2004. p. 179-188.
 */
static void initLaplacianMatrix(LaplacianSystem *sys)
{
	float no[3];
	float w2, w3;
	int i = 3, j, ti;
	int idv[3];

	for (ti = 0; ti < sys->total_tris; ti++) {
		const unsigned int *vidt = sys->tris[ti];
		const float *co[3];

		co[0] = sys->co[vidt[0]];
		co[1] = sys->co[vidt[1]];
		co[2] = sys->co[vidt[2]];

		normal_tri_v3(no, UNPACK3(co));
		add_v3_v3(sys->no[vidt[0]], no);
		add_v3_v3(sys->no[vidt[1]], no);
		add_v3_v3(sys->no[vidt[2]], no);

		for (j = 0; j < 3; j++) {
			const float *v1, *v2, *v3;

			idv[0] = vidt[j];
			idv[1] = vidt[(j + 1) % i];
			idv[2] = vidt[(j + 2) % i];

			v1 = sys->co[idv[0]];
			v2 = sys->co[idv[1]];
			v3 = sys->co[idv[2]];

			w2 = cotangent_tri_weight_v3(v3, v1, v2);
			w3 = cotangent_tri_weight_v3(v2, v3, v1);

			sys->delta[idv[0]][0] += v1[0] * (w2 + w3);
			sys->delta[idv[0]][1] += v1[1] * (w2 + w3);
			sys->delta[idv[0]][2] += v1[2] * (w2 + w3);

			sys->delta[idv[0]][0] -= v2[0] * w2;
			sys->delta[idv[0]][1] -= v2[1] * w2;
			sys->delta[idv[0]][2] -= v2[2] * w2;

			sys->delta[idv[0]][0] -= v3[0] * w3;
			sys->delta[idv[0]][1] -= v3[1] * w3;
			sys->delta[idv[0]][2] -= v3[2] * w3;

			nlMatrixAdd(idv[0], idv[1], -w2);
			nlMatrixAdd(idv[0], idv[2], -w3);
			nlMatrixAdd(idv[0], idv[0], w2 + w3);
		}
	}
}
Example #14
0
void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
{
	int val;

	for (val = 0; val < 4; val++) {
		normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
		if (UNLIKELY(is_flip)) {
			negate_v3(clip[val]);
		}

		clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
	}
}
Example #15
0
void GeometryExporter::create_normals(std::vector<Normal> &nor, std::vector<Face> &ind, Mesh *me)
{
	int i, j, v;
	MVert *vert = me->mvert;
	std::map<unsigned int, unsigned int> nshar;

	for (i = 0; i < me->totface; i++) {
		MFace *fa = &me->mface[i];
		Face f;
		unsigned int *nn = &f.v1;
		unsigned int *vv = &fa->v1;

		memset(&f, 0, sizeof(f));
		v = fa->v4 == 0 ? 3 : 4;

		if (!(fa->flag & ME_SMOOTH)) {
			Normal n;
			if (v == 4)
				normal_quad_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co, vert[fa->v4].co);
			else
				normal_tri_v3(&n.x, vert[fa->v1].co, vert[fa->v2].co, vert[fa->v3].co);
			nor.push_back(n);
		}

		for (j = 0; j < v; j++) {
			if (fa->flag & ME_SMOOTH) {
				if (nshar.find(*vv) != nshar.end())
					*nn = nshar[*vv];
				else {
					Normal n = {
						vert[*vv].no[0]/32767.0,
						vert[*vv].no[1]/32767.0,
						vert[*vv].no[2]/32767.0
					};
					nor.push_back(n);
					*nn = (unsigned int)nor.size() - 1;
					nshar[*vv] = *nn;
				}
				vv++;
			}
			else {
				*nn = (unsigned int)nor.size() - 1;
			}
			nn++;
		}

		ind.push_back(f);
	}
}
Example #16
0
static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject* args)
{
	VectorObject *vec1, *vec2, *vec3, *vec4;
	float n[3];

	if(PyTuple_GET_SIZE(args) == 3) {
		if(!PyArg_ParseTuple(args, "O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3)) {
			return NULL;
		}
		if(vec1->size != vec2->size || vec1->size != vec3->size) {
			PyErr_SetString(PyExc_ValueError,
			                "vectors must be of the same size");
			return NULL;
		}
		if(vec1->size < 3) {
			PyErr_SetString(PyExc_ValueError,
			                "2D vectors unsupported");
			return NULL;
		}

		if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1)
			return NULL;

		normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec);
	}
	else {
		if(!PyArg_ParseTuple(args, "O!O!O!O!:normal", &vector_Type, &vec1, &vector_Type, &vec2, &vector_Type, &vec3, &vector_Type, &vec4)) {
			return NULL;
		}
		if(vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) {
			PyErr_SetString(PyExc_ValueError,
			                "vectors must be of the same size");
			return NULL;
		}
		if(vec1->size < 3) {
			PyErr_SetString(PyExc_ValueError,
			                "2D vectors unsupported");
			return NULL;
		}

		if(BaseMath_ReadCallback(vec1) == -1 || BaseMath_ReadCallback(vec2) == -1 || BaseMath_ReadCallback(vec3) == -1 || BaseMath_ReadCallback(vec4) == -1)
			return NULL;

		normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec);
	}

	return newVectorObject(n, 3, Py_NEW, NULL);
}
Example #17
0
void ED_view3d_calc_clipping(BoundBox *bb, float planes[4][4], bglMats *mats, const rcti *rect)
{
	float modelview[4][4];
	double xs, ys, p[3];
	int val, flip_sign, a;

	/* near zero floating point values can give issues with gluUnProject
		in side view on some implementations */
	if(fabs(mats->modelview[0]) < 1e-6) mats->modelview[0]= 0.0;
	if(fabs(mats->modelview[5]) < 1e-6) mats->modelview[5]= 0.0;

	/* Set up viewport so that gluUnProject will give correct values */
	mats->viewport[0] = 0;
	mats->viewport[1] = 0;

	/* four clipping planes and bounding volume */
	/* first do the bounding volume */
	for(val=0; val<4; val++) {
		xs= (val==0||val==3)?rect->xmin:rect->xmax;
		ys= (val==0||val==1)?rect->ymin:rect->ymax;

		gluUnProject(xs, ys, 0.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
		VECCOPY(bb->vec[val], p);

		gluUnProject(xs, ys, 1.0, mats->modelview, mats->projection, mats->viewport, &p[0], &p[1], &p[2]);
		VECCOPY(bb->vec[4+val], p);
	}

	/* verify if we have negative scale. doing the transform before cross
	   product flips the sign of the vector compared to doing cross product
	   before transform then, so we correct for that. */
	for(a=0; a<16; a++)
		((float*)modelview)[a] = mats->modelview[a];
	flip_sign = is_negative_m4(modelview);

	/* then plane equations */
	for(val=0; val<4; val++) {

		normal_tri_v3(planes[val], bb->vec[val], bb->vec[val==3?0:val+1], bb->vec[val+4]);

		if(flip_sign)
			negate_v3(planes[val]);

		planes[val][3]= - planes[val][0]*bb->vec[val][0]
			- planes[val][1]*bb->vec[val][1]
			- planes[val][2]*bb->vec[val][2];
	}
}
Example #18
0
static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float v0[3], const float v1[3], const float v2[3])
{
	
	float idist;
	float p1[3];
	float plane_normal[3], hit_point[3];

	normal_tri_v3(plane_normal, v0, v1, v2);

	madd_v3_v3v3fl(p1, ray->origin, ray->direction, m_dist);
	if (isect_sweeping_sphere_tri_v3(ray->origin, p1, radius, v0, v1, v2, &idist, hit_point)) {
		return idist * m_dist;
	}

	return FLT_MAX;
}
Example #19
0
static float sphereray_tri_intersection(const BVHTreeRay *ray, float radius, const float m_dist, const float *v0, const float *v1, const float *v2)
{
	
	float idist;
	float p1[3];
	float plane_normal[3], hit_point[3];

	normal_tri_v3( plane_normal,(float*)v0, (float*)v1, (float*)v2);

	VECADDFAC( p1, ray->origin, ray->direction, m_dist);
	if(isect_sweeping_sphere_tri_v3((float*)ray->origin, p1, radius, (float*)v0, (float*)v1, (float*)v2, &idist, hit_point))
	{
		return idist * m_dist;
	}

	return FLT_MAX;
}
/**
 * Adds face to indices, expands memory if needed.
 */
static void make_face(PROCESS *process, int i1, int i2, int i3, int i4)
{
	int *cur;

#ifdef USE_ACCUM_NORMAL
	float n[3];
#endif

	if (UNLIKELY(process->totindex == process->curindex)) {
		process->totindex += 4096;
		process->indices = MEM_reallocN(process->indices, sizeof(int[4]) * process->totindex);
	}

	cur = process->indices[process->curindex++];

	/* displists now support array drawing, we treat tri's as fake quad */

	cur[0] = i1;
	cur[1] = i2;
	cur[2] = i3;

	if (i4 == 0) {
		cur[3] = i3;
	}
	else {
		cur[3] = i4;
	}

#ifdef USE_ACCUM_NORMAL
	if (i4 == 0) {
		normal_tri_v3(n, process->co[i1], process->co[i2], process->co[i3]);
		accumulate_vertex_normals(
		        process->no[i1], process->no[i2], process->no[i3], NULL, n,
		        process->co[i1], process->co[i2], process->co[i3], NULL);
	}
	else {
		normal_quad_v3(n, process->co[i1], process->co[i2], process->co[i3], process->co[i4]);
		accumulate_vertex_normals(
		        process->no[i1], process->no[i2], process->no[i3], process->no[i4], n,
		        process->co[i1], process->co[i2], process->co[i3], process->co[i4]);
	}
#endif

}
Example #21
0
/* copy of function above */
static void mesh_looptri_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	const MVert *vert = data->vert;
	const MLoopTri *lt = &data->looptri[index];
	const float *vtri_co[3] = {
	    vert[data->loop[lt->tri[0]].v].co,
	    vert[data->loop[lt->tri[1]].v].co,
	    vert[data->loop[lt->tri[2]].v].co,
	};
	float nearest_tmp[3], dist_sq;

	closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(vtri_co));
	dist_sq = len_squared_v3v3(co, nearest_tmp);

	if (dist_sq < nearest->dist_sq) {
		nearest->index = index;
		nearest->dist_sq = dist_sq;
		copy_v3_v3(nearest->co, nearest_tmp);
		normal_tri_v3(nearest->no, UNPACK3(vtri_co));
	}
}
Example #22
0
static int face_in_node(RayFace *face, short x, short y, short z, float rtf[][3])
{
	static float nor[3], d;
	float fx, fy, fz;
	
	// init static vars 
	if(face) {
		normal_tri_v3( nor,rtf[0], rtf[1], rtf[2]);
		d= -nor[0]*rtf[0][0] - nor[1]*rtf[0][1] - nor[2]*rtf[0][2];
		return 0;
	}
	
	fx= x;
	fy= y;
	fz= z;
	
	if((fx)*nor[0] + (fy)*nor[1] + (fz)*nor[2] + d > 0.0f) {
		if((fx+1)*nor[0] + (fy  )*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
		if((fx  )*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
		if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d < 0.0f) return 1;
	
		if((fx  )*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
		if((fx+1)*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
		if((fx  )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
		if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d < 0.0f) return 1;
	}
	else {
		if((fx+1)*nor[0] + (fy  )*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
		if((fx  )*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
		if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz  )*nor[2] + d > 0.0f) return 1;
	
		if((fx  )*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
		if((fx+1)*nor[0] + (fy  )*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
		if((fx  )*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
		if((fx+1)*nor[0] + (fy+1)*nor[1] + (fz+1)*nor[2] + d > 0.0f) return 1;
	}
	
	return 0;
}
static void harmonic_ray_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
{
	struct MeshRayCallbackData *data = userdata;
	MeshDeformBind *mdb = data->mdb;
	const MLoop *mloop = mdb->cagedm_cache.mloop;
	const MLoopTri *looptri = mdb->cagedm_cache.looptri, *lt;
	const float (*poly_nors)[3] = mdb->cagedm_cache.poly_nors;
	MeshDeformIsect *isec = data->isec;
	float no[3], co[3], end[3], uvw[3], dist;
	float *face[3];
	
	lt = &looptri[index];
	
	face[0] = mdb->cagecos[mloop[lt->tri[0]].v];
	face[1] = mdb->cagecos[mloop[lt->tri[1]].v];
	face[2] = mdb->cagecos[mloop[lt->tri[2]].v];
	
	add_v3_v3v3(end, isec->start, isec->vec);
	
	if (!meshdeform_tri_intersect(ray->origin, end, UNPACK3(face), co, uvw))
		return;

	if (poly_nors) {
		copy_v3_v3(no, poly_nors[lt->poly]);
	}
	else {
		normal_tri_v3(no, UNPACK3(face));
	}

	dist = len_v3v3(ray->origin, co) / isec->vec_length;
	if (dist < hit->dist) {
		hit->index = index;
		hit->dist = dist;
		copy_v3_v3(hit->co, co);
		
		isec->isect = (dot_v3v3(no, ray->direction) <= 0.0f);
		isec->lambda = dist;
	}
}
static void heat_calc_vnormals(LaplacianSystem *sys)
{
	float fnor[3];
	int a, v1, v2, v3, (*face)[3];

	sys->heat.vnors = MEM_callocN(sizeof(float) * 3 * sys->totvert, "HeatVNors");

	for (a = 0, face = sys->faces; a < sys->totface; a++, face++) {
		v1 = (*face)[0];
		v2 = (*face)[1];
		v3 = (*face)[2];

		normal_tri_v3(fnor, sys->verts[v1], sys->verts[v2], sys->verts[v3]);
		
		add_v3_v3(sys->heat.vnors[v1], fnor);
		add_v3_v3(sys->heat.vnors[v2], fnor);
		add_v3_v3(sys->heat.vnors[v3], fnor);
	}

	for (a = 0; a < sys->totvert; a++)
		normalize_v3(sys->heat.vnors[a]);
}
Example #25
0
/* copy of function above (warning, should de-duplicate with editmesh_bvh.c) */
static void editmesh_faces_nearest_point(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
{
	const BVHTreeFromMesh *data = (BVHTreeFromMesh *) userdata;
	BMEditMesh *em = data->em_evil;
	const BMLoop **ltri = (const BMLoop **)em->looptris[index];

	float *t0, *t1, *t2;
	t0 = ltri[0]->v->co;
	t1 = ltri[1]->v->co;
	t2 = ltri[2]->v->co;

	{
		float nearest_tmp[3], dist;
		int vertex, edge;

		dist = nearest_point_in_tri_surface(t0, t1, t2, co, &vertex, &edge, nearest_tmp);
		if (dist < nearest->dist) {
			nearest->index = index;
			nearest->dist = dist;
			copy_v3_v3(nearest->co, nearest_tmp);
			normal_tri_v3(nearest->no, t0, t1, t2);
		}
	}
}
static void rotateDifferentialCoordinates(LaplacianSystem *sys)
{
	float alpha, beta, gamma;
	float pj[3], ni[3], di[3];
	float uij[3], dun[3], e2[3], pi[3], fni[3], vn[4][3];
	int i, j, lvin, num_fni, k, fi;
	int *fidn;

	for (i = 0; i < sys->total_verts; i++) {
		copy_v3_v3(pi, sys->co[i]);
		copy_v3_v3(ni, sys->no[i]);
		k = sys->unit_verts[i];
		copy_v3_v3(pj, sys->co[k]);
		sub_v3_v3v3(uij, pj, pi);
		mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
		sub_v3_v3(uij, dun);
		normalize_v3(uij);
		cross_v3_v3v3(e2, ni, uij);
		copy_v3_v3(di, sys->delta[i]);
		alpha = dot_v3v3(ni, di);
		beta = dot_v3v3(uij, di);
		gamma = dot_v3v3(e2, di);

		pi[0] = nlGetVariable(0, i);
		pi[1] = nlGetVariable(1, i);
		pi[2] = nlGetVariable(2, i);
		zero_v3(ni);
		num_fni = 0;
		num_fni = sys->ringf_map[i].count;
		for (fi = 0; fi < num_fni; fi++) {
			const unsigned int *vin;
			fidn = sys->ringf_map[i].indices;
			vin = sys->faces[fidn[fi]];
			lvin = vin[3] ? 4 : 3;
			for (j = 0; j < lvin; j++) {
				vn[j][0] = nlGetVariable(0, vin[j]);
				vn[j][1] = nlGetVariable(1, vin[j]);
				vn[j][2] = nlGetVariable(2, vin[j]);
				if (vin[j] == sys->unit_verts[i]) {
					copy_v3_v3(pj, vn[j]);
				}
			}

			if (lvin == 3) {
				normal_tri_v3(fni, vn[0], vn[1], vn[2]);
			}
			else if (lvin == 4) {
				normal_quad_v3(fni, vn[0], vn[1], vn[2], vn[3]);
			}
			add_v3_v3(ni, fni);
		}

		normalize_v3(ni);
		sub_v3_v3v3(uij, pj, pi);
		mul_v3_v3fl(dun, ni, dot_v3v3(uij, ni));
		sub_v3_v3(uij, dun);
		normalize_v3(uij);
		cross_v3_v3v3(e2, ni, uij);
		fni[0] = alpha * ni[0] + beta * uij[0] + gamma * e2[0];
		fni[1] = alpha * ni[1] + beta * uij[1] + gamma * e2[1];
		fni[2] = alpha * ni[2] + beta * uij[2] + gamma * e2[2];

		if (len_squared_v3(fni) > FLT_EPSILON) {
			nlRightHandSideSet(0, i, fni[0]);
			nlRightHandSideSet(1, i, fni[1]);
			nlRightHandSideSet(2, i, fni[2]);
		}
		else {
			nlRightHandSideSet(0, i, sys->delta[i][0]);
			nlRightHandSideSet(1, i, sys->delta[i][1]);
			nlRightHandSideSet(2, i, sys->delta[i][2]);
		}
	}
}
Example #27
0
static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
{
	Mesh *me = ob->data;
	DerivedMesh *ddm;
	MPoly *mp, *mface  = me->mpoly;
	MTexPoly *mtpoly   = me->mtpoly;
	MLoopUV *mloopuv   = me->mloopuv;
	MLoopUV *luv;
	MLoopCol *mloopcol = me->mloopcol;  /* why does mcol exist? */
	MLoopCol *lcol;

	bProperty *prop = BKE_bproperty_object_get(ob, "Text");
	GPUVertexAttribs gattribs;
	int a, totpoly = me->totpoly;

	/* fake values to pass to GPU_render_text() */
	MCol  tmp_mcol[4]  = {{0}};
	MCol *tmp_mcol_pt  = mloopcol ? tmp_mcol : NULL;
	MTFace tmp_tf      = {{{0}}};

	/* don't draw without tfaces */
	if (!mtpoly || !mloopuv)
		return;

	/* don't draw when editing */
	if (ob->mode & OB_MODE_EDIT)
		return;
	else if (ob == OBACT)
		if (BKE_paint_select_elem_test(ob))
			return;

	ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);

	for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
		short matnr = mp->mat_nr;
		int mf_smooth = mp->flag & ME_SMOOTH;
		Material *mat = (me->mat) ? me->mat[matnr] : NULL;
		int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;


		if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) {
			/* get the polygon as a tri/quad */
			int mp_vi[4];
			float v1[3], v2[3], v3[3], v4[3];
			char string[MAX_PROPSTRING];
			int characters, i, glattrib = -1, badtex = 0;


			/* TEXFACE */
			ME_MTEXFACE_CPY(&tmp_tf, mtpoly);

			if (glsl) {
				GPU_enable_material(matnr + 1, &gattribs);

				for (i = 0; i < gattribs.totlayer; i++) {
					if (gattribs.layer[i].type == CD_MTFACE) {
						glattrib = gattribs.layer[i].glindex;
						break;
					}
				}
			}
			else {
				badtex = set_draw_settings_cached(0, &tmp_tf, mat, Gtexdraw);
				if (badtex) {
					continue;
				}
			}

			mp_vi[0] = me->mloop[mp->loopstart + 0].v;
			mp_vi[1] = me->mloop[mp->loopstart + 1].v;
			mp_vi[2] = me->mloop[mp->loopstart + 2].v;
			mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0;

			/* UV */
			luv = &mloopuv[mp->loopstart];
			copy_v2_v2(tmp_tf.uv[0], luv->uv); luv++;
			copy_v2_v2(tmp_tf.uv[1], luv->uv); luv++;
			copy_v2_v2(tmp_tf.uv[2], luv->uv); luv++;
			if (mp->totloop >= 4) {
				copy_v2_v2(tmp_tf.uv[3], luv->uv);
			}

			/* COLOR */
			if (mloopcol) {
				unsigned int totloop_clamp = min_ii(4, mp->totloop);
				unsigned int j;
				lcol = &mloopcol[mp->loopstart];

				for (j = 0; j < totloop_clamp; j++, lcol++) {
					MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
				}
			}

			/* LOCATION */
			ddm->getVertCo(ddm, mp_vi[0], v1);
			ddm->getVertCo(ddm, mp_vi[1], v2);
			ddm->getVertCo(ddm, mp_vi[2], v3);
			if (mp->totloop >= 4) {
				ddm->getVertCo(ddm, mp_vi[3], v4);
			}



			/* The BM_FONT handling is in the gpu module, shared with the
			 * game engine, was duplicated previously */

			BKE_bproperty_set_valstr(prop, string);
			characters = strlen(string);
			
			if (!BKE_image_has_ibuf(mtpoly->tpage, NULL))
				characters = 0;

			if (!mf_smooth) {
				float nor[3];

				normal_tri_v3(nor, v1, v2, v3);

				glNormal3fv(nor);
			}

			GPU_render_text(&tmp_tf, mode, string, characters,
			                (unsigned int *)tmp_mcol_pt, v1, v2, v3, (mp->totloop >= 4 ? v4 : NULL), glattrib);
		}
	}

	ddm->release(ddm);
}
/**
 * This method computes the Laplacian Matrix and Differential Coordinates for all vertex in the mesh.
 * The Linear system is LV = d
 * Where L is Laplacian Matrix, V as the vertexes in Mesh, d is the differential coordinates
 * The Laplacian Matrix is computes as a
 * Lij = sum(Wij) (if i == j)
 * Lij = Wij (if i != j)
 * Wij is weight between vertex Vi and vertex Vj, we use cotangent weight
 *
 * The Differential Coordinate is computes as a
 * di = Vi * sum(Wij) - sum(Wij * Vj)
 * Where :
 * di is the Differential Coordinate i
 * sum (Wij) is the sum of all weights between vertex Vi and its vertexes neighbors (Vj)
 * sum (Wij * Vj) is the sum of the product between vertex neighbor Vj and weight Wij for all neighborhood.
 *
 * This Laplacian Matrix is described in the paper:
 * Desbrun M. et.al, Implicit fairing of irregular meshes using diffusion and curvature flow, SIGGRAPH '99, pag 317-324,
 * New York, USA
 *
 * The computation of Laplace Beltrami operator on Hybrid Triangle/Quad Meshes is described in the paper:
 * Pinzon A., Romero E., Shape Inflation With an Adapted Laplacian Operator For Hybrid Quad/Triangle Meshes,
 * Conference on Graphics Patterns and Images, SIBGRAPI, 2013
 *
 * The computation of Differential Coordinates is described in the paper:
 * Sorkine, O. Laplacian Surface Editing. Proceedings of the EUROGRAPHICS/ACM SIGGRAPH Symposium on Geometry Processing,
 * 2004. p. 179-188.
 */
static void initLaplacianMatrix(LaplacianSystem *sys)
{
	float v1[3], v2[3], v3[3], v4[3], no[3];
	float w2, w3, w4;
	int i, j, fi;
	bool has_4_vert;
	unsigned int idv1, idv2, idv3, idv4;

	for (fi = 0; fi < sys->total_faces; fi++) {
		const unsigned int *vidf = sys->faces[fi];

		idv1 = vidf[0];
		idv2 = vidf[1];
		idv3 = vidf[2];
		idv4 = vidf[3];

		has_4_vert = vidf[3] ? 1 : 0;
		if (has_4_vert) {
			normal_quad_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3], sys->co[idv4]);
			add_v3_v3(sys->no[idv4], no);
			i = 4;
		}
		else {
			normal_tri_v3(no, sys->co[idv1], sys->co[idv2], sys->co[idv3]);
			i = 3;
		}
		add_v3_v3(sys->no[idv1], no);
		add_v3_v3(sys->no[idv2], no);
		add_v3_v3(sys->no[idv3], no);

		for (j = 0; j < i; j++) {
			idv1 = vidf[j];
			idv2 = vidf[(j + 1) % i];
			idv3 = vidf[(j + 2) % i];
			idv4 = has_4_vert ? vidf[(j + 3) % i] : 0;

			copy_v3_v3(v1, sys->co[idv1]);
			copy_v3_v3(v2, sys->co[idv2]);
			copy_v3_v3(v3, sys->co[idv3]);
			if (has_4_vert) {
				copy_v3_v3(v4, sys->co[idv4]);
			}

			if (has_4_vert) {

				w2 = (cotan_weight(v4, v1, v2) + cotan_weight(v3, v1, v2)) / 2.0f;
				w3 = (cotan_weight(v2, v3, v1) + cotan_weight(v4, v1, v3)) / 2.0f;
				w4 = (cotan_weight(v2, v4, v1) + cotan_weight(v3, v4, v1)) / 2.0f;

				sys->delta[idv1][0] -= v4[0] * w4;
				sys->delta[idv1][1] -= v4[1] * w4;
				sys->delta[idv1][2] -= v4[2] * w4;

				nlRightHandSideAdd(0, idv1, -v4[0] * w4);
				nlRightHandSideAdd(1, idv1, -v4[1] * w4);
				nlRightHandSideAdd(2, idv1, -v4[2] * w4);

				nlMatrixAdd(idv1, idv4, -w4);
			}
			else {
				w2 = cotan_weight(v3, v1, v2);
				w3 = cotan_weight(v2, v3, v1);
				w4 = 0.0f;
			}

			sys->delta[idv1][0] += v1[0] * (w2 + w3 + w4);
			sys->delta[idv1][1] += v1[1] * (w2 + w3 + w4);
			sys->delta[idv1][2] += v1[2] * (w2 + w3 + w4);

			sys->delta[idv1][0] -= v2[0] * w2;
			sys->delta[idv1][1] -= v2[1] * w2;
			sys->delta[idv1][2] -= v2[2] * w2;

			sys->delta[idv1][0] -= v3[0] * w3;
			sys->delta[idv1][1] -= v3[1] * w3;
			sys->delta[idv1][2] -= v3[2] * w3;

			nlMatrixAdd(idv1, idv2, -w2);
			nlMatrixAdd(idv1, idv3, -w3);
			nlMatrixAdd(idv1, idv1, w2 + w3 + w4);

		}
	}
}
Example #29
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;
		}
	}
}
Example #30
0
int BLI_edgefill(int mat_nr)
{
	/*
	  - fill works with its own lists, so create that first (no faces!)
	  - for vertices, put in ->tmp.v the old pointer
	  - struct elements xs en ys are not used here: don't hide stuff in it
	  - edge flag ->f becomes 2 when it's a new edge
	  - mode: & 1 is check for crossings, then create edges (TO DO )
	*/
	ListBase tempve, temped;
	EditVert *eve;
	EditEdge *eed,*nexted;
	PolyFill *pflist,*pf;
	float *minp, *maxp, *v1, *v2, norm[3], len;
	short a,c,poly=0,ok=0,toggle=0;

	/* reset variables */
	eve= fillvertbase.first;
	while(eve) {
		eve->f= 0;
		eve->xs= 0;
		eve->h= 0;
		eve= eve->next;
	}

	/* first test vertices if they are in edges */
	/* including resetting of flags */
	eed= filledgebase.first;
	while(eed) {
		eed->f= eed->f1= eed->h= 0;
		eed->v1->f= 1;
		eed->v2->f= 1;

		eed= eed->next;
	}

	eve= fillvertbase.first;
	while(eve) {
		if(eve->f & 1) {
			ok=1; 
			break;
		}
		eve= eve->next;
	}

	if(ok==0) return 0;

	/* NEW NEW! define projection: with 'best' normal */
	/* just use the first three different vertices */
	
	/* THIS PART STILL IS PRETTY WEAK! (ton) */
	
	eve= fillvertbase.last;
	len= 0.0;
	v1= eve->co;
	v2= 0;
	eve= fillvertbase.first;
	while(eve) {
		if(v2) {
			if( compare_v3v3(v2, eve->co, COMPLIMIT)==0) {
				len= normal_tri_v3( norm,v1, v2, eve->co);
				if(len != 0.0) break;
			}
		}
		else if(compare_v3v3(v1, eve->co, COMPLIMIT)==0) {
			v2= eve->co;
		}
		eve= eve->next;
	}

	if(len==0.0) return 0;	/* no fill possible */

	norm[0]= fabs(norm[0]);
	norm[1]= fabs(norm[1]);
	norm[2]= fabs(norm[2]);
	
	if(norm[2]>=norm[0] && norm[2]>=norm[1]) {
		cox= 0; coy= 1;
	}
	else if(norm[1]>=norm[0] && norm[1]>=norm[2]) {
		cox= 0; coy= 2;
	}
	else {
		cox= 1; coy= 2;
	}

	/* STEP 1: COUNT POLYS */
	eve= fillvertbase.first;
	while(eve) {
		/* get first vertex with no poly number */
		if(eve->xs==0) {
			poly++;
			/* now a sortof select connected */
			ok= 1;
			eve->xs= poly;
			
			while(ok) {
				
				ok= 0;
				toggle++;
				if(toggle & 1) eed= filledgebase.first;
				else eed= filledgebase.last;

				while(eed) {
					if(eed->v1->xs==0 && eed->v2->xs==poly) {
						eed->v1->xs= poly;
						eed->f1= poly;
						ok= 1;
					}
					else if(eed->v2->xs==0 && eed->v1->xs==poly) {
						eed->v2->xs= poly;
						eed->f1= poly;
						ok= 1;
					}
					else if(eed->f1==0) {
						if(eed->v1->xs==poly && eed->v2->xs==poly) {
							eed->f1= poly;
							ok= 1;
						}
					}
					if(toggle & 1) eed= eed->next;
					else eed= eed->prev;
				}
			}
		}
		eve= eve->next;
	}
	/* printf("amount of poly's: %d\n",poly); */

	/* STEP 2: remove loose edges and strings of edges */
	eed= filledgebase.first;
	while(eed) {
		if(eed->v1->h++ >250) break;
		if(eed->v2->h++ >250) break;
		eed= eed->next;
	}
	if(eed) {
		/* otherwise it's impossible to be sure you can clear vertices */
		callLocalErrorCallBack("No vertices with 250 edges allowed!");
		return 0;
	}
	
	/* does it only for vertices with ->h==1 */
	testvertexnearedge();

	ok= 1;
	while(ok) {
		ok= 0;
		toggle++;
		if(toggle & 1) eed= filledgebase.first;
		else eed= filledgebase.last;
		while(eed) {
			if(toggle & 1) nexted= eed->next;
			else nexted= eed->prev;
			if(eed->v1->h==1) {
				eed->v2->h--;
				BLI_remlink(&fillvertbase,eed->v1); 
				BLI_remlink(&filledgebase,eed); 
				ok= 1;
			}
			else if(eed->v2->h==1) {
				eed->v1->h--;
				BLI_remlink(&fillvertbase,eed->v2); 
				BLI_remlink(&filledgebase,eed); 
				ok= 1;
			}
			eed= nexted;
		}
	}
	if(filledgebase.first==0) {
		/* printf("All edges removed\n"); */
		return 0;
	}


	/* CURRENT STATUS:
	- eve->f      :1= availalble in edges
	- eve->xs     :polynumber
	- eve->h      :amount of edges connected to vertex
	- eve->tmp.v  :store! original vertex number

	- eed->f  :
	- eed->f1 :poly number
	*/


	/* STEP 3: MAKE POLYFILL STRUCT */
	pflist= (PolyFill *)MEM_callocN(poly*sizeof(PolyFill),"edgefill");
	pf= pflist;
	for(a=1;a<=poly;a++) {
		pf->nr= a;
		pf->min[0]=pf->min[1]=pf->min[2]= 1.0e20;
		pf->max[0]=pf->max[1]=pf->max[2]= -1.0e20;
		pf++;
	}
	eed= filledgebase.first;
	while(eed) {
		pflist[eed->f1-1].edges++;
		eed= eed->next;
	}

	eve= fillvertbase.first;
	while(eve) {
		pflist[eve->xs-1].verts++;
		minp= pflist[eve->xs-1].min;
		maxp= pflist[eve->xs-1].max;

		minp[cox]= (minp[cox])<(eve->co[cox]) ? (minp[cox]) : (eve->co[cox]);
		minp[coy]= (minp[coy])<(eve->co[coy]) ? (minp[coy]) : (eve->co[coy]);
		maxp[cox]= (maxp[cox])>(eve->co[cox]) ? (maxp[cox]) : (eve->co[cox]);
		maxp[coy]= (maxp[coy])>(eve->co[coy]) ? (maxp[coy]) : (eve->co[coy]);
		if(eve->h>2) pflist[eve->xs-1].f= 1;

		eve= eve->next;
	}

	/* STEP 4: FIND HOLES OR BOUNDS, JOIN THEM
	 *  ( bounds just to divide it in pieces for optimization, 
	 *    the edgefill itself has good auto-hole detection)
	 * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */
	
	if(poly>1) {
		short *polycache, *pc;

		/* so, sort first */
		qsort(pflist, poly, sizeof(PolyFill), vergpoly);
		
		/*pf= pflist;
		for(a=1;a<=poly;a++) {
			printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
			PRINT2(f, f, pf->min[0], pf->min[1]);
			pf++;
		}*/
	
		polycache= pc= MEM_callocN(sizeof(short)*poly, "polycache");
		pf= pflist;
		for(a=0; a<poly; a++, pf++) {
			for(c=a+1;c<poly;c++) {
				
				/* if 'a' inside 'c': join (bbox too)
				 * Careful: 'a' can also be inside another poly.
				 */
				if(boundisect(pf, pflist+c)) {
					*pc= c;
					pc++;
				}
				/* only for optimize! */
				/* else if(pf->max[cox] < (pflist+c)->min[cox]) break; */
				
			}
			while(pc!=polycache) {
				pc--;
				mergepolysSimp(pf, pflist+ *pc);
			}
		}
		MEM_freeN(polycache);
	}
	
	/* printf("after merge\n");
	pf= pflist;
	for(a=1;a<=poly;a++) {
		printf("poly:%d edges:%d verts:%d flag: %d\n",a,pf->edges,pf->verts,pf->f);
		pf++;
	} */

	/* STEP 5: MAKE TRIANGLES */

	tempve.first= fillvertbase.first;
	tempve.last= fillvertbase.last;
	temped.first= filledgebase.first;
	temped.last= filledgebase.last;
	fillvertbase.first=fillvertbase.last= 0;
	filledgebase.first=filledgebase.last= 0;

	pf= pflist;
	for(a=0;a<poly;a++) {
		if(pf->edges>1) {
			splitlist(&tempve,&temped,pf->nr);
			scanfill(pf, mat_nr);
		}
		pf++;
	}
	BLI_movelisttolist(&fillvertbase,&tempve);
	BLI_movelisttolist(&filledgebase,&temped);

	/* FREE */

	MEM_freeN(pflist);
	return 1;

}