Ejemplo n.º 1
0
void RowEchelon<T>::getAllSolutions(VectorT& x0,MatrixT& N) const
{
  getNullspace(N);

  VectorT* N0 = new VectorT[N.n];
  for(int i=0;i<N.n;i++) N.getColRef(i,N0[i]);
  backSub(x0);
  Orthogonalize(x0,N0,N.n);
  delete [] N0;
}
Ejemplo n.º 2
0
void CameraBase::ComputeModelView( bool forceIdentity /*= false*/ )
{
	m_camInvDirty = true;
	m_frustumPlanesDirty = true;

	if (forceIdentity)
	{
		hkgMat4Identity(m_viewMat);
		return;
	}

	Orthogonalize();

	noVec3 eye;
	eye = m_from;
		
	noVec3 f;
	// right hand 
	f = m_to - eye;
	// left hand
	//f = eye - m_to;

	f.Normalize();
	m_up.Normalize();

	noVec3 s,u;
	s = f.Cross(m_up);
	u = s.Cross(f);

	m_viewMat[0] = s[0];  m_viewMat[4] = s[1];  m_viewMat[8] = s[2]; 
	m_viewMat[1] = u[0];  m_viewMat[5] = u[1];  m_viewMat[9] = u[2];	
	m_viewMat[2] = -f[0]; m_viewMat[6] = -f[1]; m_viewMat[10] = -f[2];

	m_viewMat[3] = 0.0f; m_viewMat[7] = 0.0f; m_viewMat[11] = 0.0f;
	eye = -eye;
	m_viewMat[12] = (m_viewMat[0]*eye[0]) + (m_viewMat[4]*eye[1]) + (m_viewMat[8] *eye[2]);
	m_viewMat[13] = (m_viewMat[1]*eye[0]) + (m_viewMat[5]*eye[1]) + (m_viewMat[9] *eye[2]);
	m_viewMat[14] = (m_viewMat[2]*eye[0]) + (m_viewMat[6]*eye[1]) + (m_viewMat[10]*eye[2]);

	m_viewMat[15] = 1.0f;
}
Ejemplo n.º 3
0
/**
 * @brief Calculates normals and tangents for all frames and does vertex merging based on smoothness
 * @param mesh The mesh to calculate normals for
 * @param nFrames How many frames the mesh has
 * @param smoothness How aggressively should normals be smoothed; value is compared with dotproduct of vectors to decide if they should be merged
 * @sa R_ModCalcNormalsAndTangents
 */
void R_ModCalcUniqueNormalsAndTangents (mAliasMesh_t *mesh, int nFrames, float smoothness)
{
	int i, j;
	vec3_t triangleNormals[MAX_ALIAS_TRIS];
	vec3_t triangleTangents[MAX_ALIAS_TRIS];
	vec3_t triangleBitangents[MAX_ALIAS_TRIS];
	const mAliasVertex_t *vertexes = mesh->vertexes;
	mAliasCoord_t *stcoords = mesh->stcoords;
	mAliasVertex_t *newVertexes;
	mAliasComplexVertex_t tmpVertexes[MAX_ALIAS_VERTS];
	vec3_t tmpBitangents[MAX_ALIAS_VERTS];
	mAliasCoord_t *newStcoords;
	const int numIndexes = mesh->num_tris * 3;
	const int32_t *indexArray = mesh->indexes;
	int32_t *newIndexArray;
	int indRemap[MAX_ALIAS_VERTS];
	int sharedTris[MAX_ALIAS_VERTS];
	int numVerts = 0;

	newIndexArray = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * numIndexes, vid_modelPool, 0);

	/* calculate per-triangle surface normals */
	for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
		vec3_t dir1, dir2;
		vec2_t dir1uv, dir2uv;

		/* calculate two mostly perpendicular edge directions */
		VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
		VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
		Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
		Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);

		/* we have two edge directions, we can calculate a third vector from
		 * them, which is the direction of the surface normal */
		CrossProduct(dir1, dir2, triangleNormals[j]);

		/* then we use the texture coordinates to calculate a tangent space */
		if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
			const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
			vec3_t tmp1, tmp2;

			/* calculate tangent */
			VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
			VectorMul(dir1uv[1] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleTangents[j]);

			/* calculate bitangent */
			VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
			VectorMul(dir1uv[0] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleBitangents[j]);
		} else {
			const float frac = 1.0 / (0.00001);
			vec3_t tmp1, tmp2;

			/* calculate tangent */
			VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
			VectorMul(dir1uv[1] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleTangents[j]);

			/* calculate bitangent */
			VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
			VectorMul(dir1uv[0] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleBitangents[j]);
		}

		/* normalize */
		VectorNormalizeFast(triangleNormals[j]);
		VectorNormalizeFast(triangleTangents[j]);
		VectorNormalizeFast(triangleBitangents[j]);

		Orthogonalize(triangleTangents[j], triangleBitangents[j]);
	}

	/* do smoothing */
	for (i = 0; i < numIndexes; i++) {
		const int idx = (i - i % 3) / 3;
		VectorCopy(triangleNormals[idx], tmpVertexes[i].normal);
		VectorCopy(triangleTangents[idx], tmpVertexes[i].tangent);
		VectorCopy(triangleBitangents[idx], tmpBitangents[i]);

		for (j = 0; j < numIndexes; j++) {
			const int idx2 = (j - j % 3) / 3;
			/* don't add a vertex with itself */
			if (j == i)
				continue;

			/* only average normals if vertices have the same position
			 * and the normals aren't too far apart to start with */
			if (VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
					&& DotProduct(triangleNormals[idx], triangleNormals[idx2]) > smoothness) {
				/* average the normals */
				VectorAdd(tmpVertexes[i].normal, triangleNormals[idx2], tmpVertexes[i].normal);

				/* if the tangents match as well, average them too.
				 * Note that having matching normals without matching tangents happens
				 * when the order of vertices in two triangles sharing the vertex
				 * in question is different.  This happens quite frequently if the
				 * modeler does not go out of their way to avoid it. */

				if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
						&& DotProduct(triangleTangents[idx], triangleTangents[idx2]) > smoothness
						&& DotProduct(triangleBitangents[idx], triangleBitangents[idx2]) > smoothness) {
					/* average the tangents */
					VectorAdd(tmpVertexes[i].tangent, triangleTangents[idx2], tmpVertexes[i].tangent);
					VectorAdd(tmpBitangents[i], triangleBitangents[idx2], tmpBitangents[i]);
				}
			}
		}

		VectorNormalizeFast(tmpVertexes[i].normal);
		VectorNormalizeFast(tmpVertexes[i].tangent);
		VectorNormalizeFast(tmpBitangents[i]);
	}

	/* assume all vertices are unique until proven otherwise */
	for (i = 0; i < numIndexes; i++)
		indRemap[i] = -1;

	/* merge vertices that have become identical */
	for (i = 0; i < numIndexes; i++) {
		vec3_t n, b, t, v;
		if (indRemap[i] != -1)
			continue;

		for (j = i + 1; j < numIndexes; j++) {
			if (Vector2Equal(stcoords[indexArray[i]], stcoords[indexArray[j]])
					&& VectorEqual(vertexes[indexArray[i]].point, vertexes[indexArray[j]].point)
					&& (DotProduct(tmpVertexes[i].normal, tmpVertexes[j].normal) > smoothness)
					&& (DotProduct(tmpVertexes[i].tangent, tmpVertexes[j].tangent) > smoothness)) {
				indRemap[j] = i;
				newIndexArray[j] = numVerts;
			}
		}

		VectorCopy(tmpVertexes[i].normal, n);
		VectorCopy(tmpVertexes[i].tangent, t);
		VectorCopy(tmpBitangents[i], b);

		/* normalization here does shared-vertex smoothing */
		VectorNormalizeFast(n);
		VectorNormalizeFast(t);
		VectorNormalizeFast(b);

		/* Grahm-Schmidt orthogonalization */
		VectorMul(DotProduct(t, n), n, v);
		VectorSubtract(t, v, t);
		VectorNormalizeFast(t);

		/* calculate handedness */
		CrossProduct(n, t, v);
		tmpVertexes[i].tangent[3] = (DotProduct(v, b) < 0.0) ? -1.0 : 1.0;
		VectorCopy(n, tmpVertexes[i].normal);
		VectorCopy(t, tmpVertexes[i].tangent);

		newIndexArray[i] = numVerts++;
		indRemap[i] = i;
	}

	for (i = 0; i < numVerts; i++)
		sharedTris[i] = 0;

	for (i = 0; i < numIndexes; i++)
		sharedTris[newIndexArray[i]]++;

	/* set up reverse-index that maps Vertex objects to a list of triangle verts */
	mesh->revIndexes = (mIndexList_t *)Mem_PoolAlloc(sizeof(mIndexList_t) * numVerts, vid_modelPool, 0);
	for (i = 0; i < numVerts; i++) {
		mesh->revIndexes[i].length = 0;
		mesh->revIndexes[i].list = (int32_t *)Mem_PoolAlloc(sizeof(int32_t) * sharedTris[i], vid_modelPool, 0);
	}

	/* merge identical vertexes, storing only unique ones */
	newVertexes = (mAliasVertex_t *)Mem_PoolAlloc(sizeof(mAliasVertex_t) * numVerts * nFrames, vid_modelPool, 0);
	newStcoords = (mAliasCoord_t *)Mem_PoolAlloc(sizeof(mAliasCoord_t) * numVerts, vid_modelPool, 0);
	for (i = 0; i < numIndexes; i++) {
		const int idx = indexArray[indRemap[i]];
		const int idx2 = newIndexArray[i];

		/* add vertex to new vertex array */
		VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
		Vector2Copy(stcoords[idx], newStcoords[idx2]);
		mesh->revIndexes[idx2].list[mesh->revIndexes[idx2].length++] = i;
	}

	/* copy over the points from successive frames */
	for (i = 1; i < nFrames; i++) {
		for (j = 0; j < numIndexes; j++) {
			const int idx = indexArray[indRemap[j]] + (mesh->num_verts * i);
			const int idx2 = newIndexArray[j] + (numVerts * i);

			VectorCopy(vertexes[idx].point, newVertexes[idx2].point);
		}
	}

	/* copy new arrays back into original mesh */
	Mem_Free(mesh->stcoords);
	Mem_Free(mesh->indexes);
	Mem_Free(mesh->vertexes);

	mesh->num_verts = numVerts;
	mesh->vertexes = newVertexes;
	mesh->stcoords = newStcoords;
	mesh->indexes = newIndexArray;
}
Ejemplo n.º 4
0
/**
 * @brief Calculates a per-vertex tangentspace basis and stores it in GL arrays attached to the mesh
 * @param mesh The mesh to calculate normals for
 * @param framenum The animation frame to calculate normals for
 * @param translate The frame translation for the given animation frame
 * @param backlerp Whether to store the results in the GL arrays for the previous keyframe or the next keyframe
 * @sa R_ModCalcUniqueNormalsAndTangents
 */
static void R_ModCalcNormalsAndTangents (mAliasMesh_t *mesh, int framenum, const vec3_t translate, qboolean backlerp)
{
	int i, j;
	mAliasVertex_t *vertexes = &mesh->vertexes[framenum * mesh->num_verts];
	mAliasCoord_t *stcoords = mesh->stcoords;
	const int numIndexes = mesh->num_tris * 3;
	const int32_t *indexArray = mesh->indexes;
	vec3_t triangleNormals[MAX_ALIAS_TRIS];
	vec3_t triangleTangents[MAX_ALIAS_TRIS];
	vec3_t triangleBitangents[MAX_ALIAS_TRIS];
	float *texcoords, *verts, *normals, *tangents;

	/* set up array pointers for either the previous keyframe or the next keyframe */
	texcoords = mesh->texcoords;
	if (backlerp) {
		verts = mesh->verts;
		normals = mesh->normals;
		tangents = mesh->tangents;
	} else {
		verts = mesh->next_verts;
		normals = mesh->next_normals;
		tangents = mesh->next_tangents;
	}

	/* calculate per-triangle surface normals and tangents*/
	for (i = 0, j = 0; i < numIndexes; i += 3, j++) {
		vec3_t dir1, dir2;
		vec2_t dir1uv, dir2uv;

		/* calculate two mostly perpendicular edge directions */
		VectorSubtract(vertexes[indexArray[i + 0]].point, vertexes[indexArray[i + 1]].point, dir1);
		VectorSubtract(vertexes[indexArray[i + 2]].point, vertexes[indexArray[i + 1]].point, dir2);
		Vector2Subtract(stcoords[indexArray[i + 0]], stcoords[indexArray[i + 1]], dir1uv);
		Vector2Subtract(stcoords[indexArray[i + 2]], stcoords[indexArray[i + 1]], dir2uv);

		/* we have two edge directions, we can calculate a third vector from
		 * them, which is the direction of the surface normal */
		CrossProduct(dir1, dir2, triangleNormals[j]);
		/* normalize */
		VectorNormalizeFast(triangleNormals[j]);

		/* then we use the texture coordinates to calculate a tangent space */
		if ((dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]) != 0.0) {
			const float frac = 1.0 / (dir1uv[1] * dir2uv[0] - dir1uv[0] * dir2uv[1]);
			vec3_t tmp1, tmp2;

			/* calculate tangent */
			VectorMul(-1.0 * dir2uv[1] * frac, dir1, tmp1);
			VectorMul(dir1uv[1] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleTangents[j]);

			/* calculate bitangent */
			VectorMul(-1.0 * dir2uv[0] * frac, dir1, tmp1);
			VectorMul(dir1uv[0] * frac, dir2, tmp2);
			VectorAdd(tmp1, tmp2, triangleBitangents[j]);

			/* normalize */
			VectorNormalizeFast(triangleTangents[j]);
			VectorNormalizeFast(triangleBitangents[j]);
		} else {
			VectorClear(triangleTangents[j]);
			VectorClear(triangleBitangents[j]);
		}
	}

	/* for each vertex */
	for (i = 0; i < mesh->num_verts; i++) {
		vec3_t n, b, v;
		vec4_t t;
		const int len = mesh->revIndexes[i].length;
		const int32_t *list = mesh->revIndexes[i].list;

		VectorClear(n);
		VectorClear(t);
		VectorClear(b);

		/* for each vertex that got mapped to this one (ie. for each triangle this vertex is a part of) */
		for (j = 0; j < len; j++) {
			const int32_t idx = list[j] / 3;
			VectorAdd(n, triangleNormals[idx], n);
			VectorAdd(t, triangleTangents[idx], t);
			VectorAdd(b, triangleBitangents[idx], b);
		}

		/* normalization here does shared-vertex smoothing */
		VectorNormalizeFast(n);
		VectorNormalizeFast(t);
		VectorNormalizeFast(b);

		/* Grahm-Schmidt orthogonalization */
		Orthogonalize(t, n);

		/* calculate handedness */
		CrossProduct(n, t, v);
		t[3] = (DotProduct(v, b) < 0.0) ? -1.0 : 1.0;

		/* copy this vertex's info to all the right places in the arrays */
		for (j = 0; j < len; j++) {
			const int32_t idx = list[j];
			const int meshIndex = mesh->indexes[list[j]];
			Vector2Copy(stcoords[meshIndex], (texcoords + (2 * idx)));
			VectorAdd(vertexes[meshIndex].point, translate, (verts + (3 * idx)));
			VectorCopy(n, (normals + (3 * idx)));
			Vector4Copy(t, (tangents + (4 * idx)));
		}
	}
}