Ejemplo n.º 1
0
/**
 * @brief Update the node size and fire the pos callback
 */
void UI_NodeSetPos(uiNode_t* node, vec2_t pos) {
	if (Vector2Equal(node->box.pos, pos))
		return;
	node->box.pos[0] = pos[0];
	node->box.pos[1] = pos[1];
	UI_Node_PosChanged(node);
}
Ejemplo n.º 2
0
/**
 * @brief Update the node size and fire the size callback
 */
void UI_NodeSetSize (uiNode_t* node, vec2_t size)
{
	if (Vector2Equal(node->box.size, size))
		return;
	node->box.size[0] = size[0];
	node->box.size[1] = size[1];
	UI_Node_SizeChanged(node);
}
Ejemplo n.º 3
0
/**
 * @brief return true if the node size change and update the cache
 */
qboolean UI_AbstractScrollableNodeIsSizeChange (uiNode_t *node)
{
	assert(UI_NodeInstanceOf(node, "abstractscrollable"));

	if (!Vector2Equal(node->size, EXTRADATA(node).cacheSize)) {
		Vector2Copy(node->size, EXTRADATA(node).cacheSize);
		return qtrue;
	}
	return qfalse;
}
/**
 * @brief return true if the node size change and update the cache
 */
bool uiAbstractScrollableNode::isSizeChange (uiNode_t *node)
{
	assert(UI_Node_IsScrollableContainer(node));

	if (!Vector2Equal(node->box.size, EXTRADATA(node).cacheSize)) {
		Vector2Copy(node->box.size, EXTRADATA(node).cacheSize);
		return true;
	}
	return false;
}
Ejemplo n.º 5
0
static const mission_t* CP_TerrorInCity (const city_t *city)
{
	if (!city)
		return nullptr;

	MIS_Foreach(mission) {
		if (mission->category == INTERESTCATEGORY_TERROR_ATTACK
		 && mission->stage <= STAGE_TERROR_MISSION
		 && Vector2Equal(mission->pos, city->pos))
			return mission;
	}
	return nullptr;
}
Ejemplo n.º 6
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;
}