-
-
-/*
-// svbspmesh_t is in model_brush.h
-
-typedef struct svbsppolygon_s
-{
- struct svbsppolygon_s *next;
- int numverts;
- float *verts;
- float normal[3], dist;
-}
-svbsppolygon_t;
-
-typedef struct svbspnode_s
-{
- // true if this is a leaf (has no children), not a node
- int isleaf;
- // (shared) parent node
- struct svbspnode_s *parent;
- // (leaf) dark or lit leaf
- int dark;
- // (leaf) polygons bounding this leaf
- svbsppolygon_t *polygons;
- // (node) children
- struct svbspnode_s *children[2];
- // (node) splitting plane
- float normal[3], dist;
-}
-svbspnode_t;
-
-svbspnode_t *Mod_SVBSP_AllocNode(svbspnode_t *parent, svbspnode_t *child0, svbspnode_t *child1, float *normal, float dist)
-{
- svbspnode_t *node;
- node = Mem_Alloc(loadmodel->mempool, sizeof(svbspnode_t));
- node->parent = parent;
- node->children[0] = child0;
- node->children[1] = child1;
- VectorCopy(normal, node->normal);
- node->dist = dist;
- return node;
-}
-
-svbspnode_t *Mod_SVBSP_AllocLeaf(svbspnode_t *parent, int dark)
-{
- svbspnode_t *leaf;
- leaf = Mem_Alloc(loadmodel->mempool, sizeof(svbspnode_t));
- leaf->isleaf = true;
- leaf->parent = parent;
- leaf->dark = dark;
- return leaf;
-}
-
-svbspnode_t *Mod_SVBSP_NewTree(void)
-{
- return Mod_SVBSP_AllocLeaf(NULL, false);
-}
-
-void Mod_SVBSP_FreeTree(svbspnode_t *node)
-{
- if (!node->isleaf)
- {
- Mod_SVBSP_FreeTree(node->children[0]);
- Mod_SVBSP_FreeTree(node->children[1]);
- }
- Mem_Free(node);
-}
-
-void Mod_SVBSP_RecursiveAddPolygon(svbspnode_t *node, int numverts, float *verts, float *normal, float dist, int constructmode)
-{
- int i, j, numvertsfront, numvertsback, maxverts, counts[3];
- float *vertsfront, *vertsback, *v, d, temp[3];
- float dists[4096];
- qbyte sides[4096];
- svbsppolygon_t *poly;
- if (node->isleaf)
- {
- if (constructmode == 0)
- {
- // construct tree structure
- node->isleaf = false;
- node->children[0] = Mod_SVBSP_AllocLeaf(node, false);
- node->children[1] = Mod_SVBSP_AllocLeaf(node, false);
- VectorCopy(normal, node->normal);
- node->dist = dist;
- }
- else if (constructmode == 1)
- {
- // mark dark leafs
- node->dark = true;
- }
- else
- {
- // link polygons into lit leafs only (this is the optimization)
- if (!node->dark)
- {
- poly = Mem_Alloc(loadmodel->mempool, sizeof(svbsppolygon_t) + numverts * sizeof(float[3]));
- poly->numverts = numverts;
- poly->verts = (float *)(poly + 1);
- VectorCopy(normal, poly->normal);
- poly->dist = dist;
- memcpy(poly->verts, verts, numverts * sizeof(float[3]));
- poly->next = node->polygons;
- node->polygons = poly;
- }
- }
- }
- else
- {
- counts[SIDE_FRONT] = counts[SIDE_BACK] = counts[SIDE_ON] = 0;
- for (i = 0, v = verts;i < numverts;i++, v += 3)
- {
- dists[i] = DotProduct(v, node->normal) - node->dist;
- if (dists[i] >= 0.1)
- sides[i] = SIDE_FRONT;
- else if (dists[i] <= -0.1)
- sides[i] = SIDE_BACK;
- else
- sides[i] = SIDE_ON;
- counts[sides[i]]++;
- }
- if (counts[SIDE_FRONT] && counts[SIDE_BACK])
- {
- // some front, some back... sliced
- numvertsfront = 0;
- numvertsback = 0;
- // this is excessive, but nice for safety...
- maxverts = numverts + 4;
- vertsfront = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- vertsback = Mem_Alloc(loadmodel->mempool, maxverts * sizeof(float[3]));
- for (i = 0, j = numverts - 1;i < numverts;j = i, i++)
- {
- if (sides[j] == SIDE_FRONT)
- {
- VectorCopy(&verts[j * 3], &vertsfront[numvertsfront * 3]);
- numvertsfront++;
- if (sides[i] == SIDE_BACK)
- {
- d = dists[j] / (dists[j] - dists[i]);
- VectorSubtract(&verts[i * 3], &verts[j * 3], temp);
- VectorMA(&verts[j * 3], d, temp, temp);
- VectorCopy(temp, &vertsfront[numvertsfront * 3]);
- VectorCopy(temp, &vertsback[numvertsback * 3]);
- numvertsfront++;
- numvertsback++;
- }
- }
- else if (sides[j] == SIDE_BACK)
- {
- VectorCopy(&verts[j * 3], &vertsback[numvertsback * 3]);
- numvertsback++;
- if (sides[i] == SIDE_FRONT)
- {
- d = dists[j] / (dists[j] - dists[i]);
- VectorSubtract(&verts[i * 3], &verts[j * 3], temp);
- VectorMA(&verts[j * 3], d, temp, temp);
- VectorCopy(temp, &vertsfront[numvertsfront * 3]);
- VectorCopy(temp, &vertsback[numvertsback * 3]);
- numvertsfront++;
- numvertsback++;
- }
- }
- else
- {
- VectorCopy(&verts[j * 3], &vertsfront[numvertsfront * 3]);
- VectorCopy(&verts[j * 3], &vertsback[numvertsback * 3]);
- numvertsfront++;
- numvertsback++;
- }
- }
- Mod_SVBSP_RecursiveAddPolygon(node->children[1], numvertsfront, vertsfront, normal, dist, constructmode);
- Mod_SVBSP_RecursiveAddPolygon(node->children[0], numvertsback, vertsback, normal, dist, constructmode);
- Mem_Free(vertsfront);
- Mem_Free(vertsback);
- }
- else if (counts[SIDE_BACK])
- Mod_SVBSP_RecursiveAddPolygon(node->children[0], numverts, verts, normal, dist, constructmode);
- else if (counts[SIDE_FRONT])
- Mod_SVBSP_RecursiveAddPolygon(node->children[1], numverts, verts, normal, dist, constructmode);
- else
- {
- // mode 0 is constructing tree, don't make unnecessary splits
- if (constructmode == 1)
- {
- // marking dark leafs
- // send it down the side it is not facing
- Mod_SVBSP_RecursiveAddPolygon(node->children[DotProduct(node->normal, normal) < 0], numverts, verts, normal, dist, constructmode);
- }
- else if (constructmode == 2)
- {
- // linking polygons into lit leafs only
- // send it down the side it is facing
- Mod_SVBSP_RecursiveAddPolygon(node->children[DotProduct(node->normal, normal) >= 0], numverts, verts, normal, dist, constructmode);
- }
- }
- }
-}
-
-int svbsp_count_nodes;
-int svbsp_count_leafs;
-int svbsp_count_polygons;
-int svbsp_count_darkleafs;
-int svbsp_count_originalpolygons;
-int svbsp_count_meshs;
-int svbsp_count_triangles;
-int svbsp_count_vertices;
-
-void Mod_SVBSP_AddPolygon(svbspnode_t *root, int numverts, float *verts, int constructmode, float *test, int linenumber)
-{
- int i;
- float normal[3], dist, dir0[3], dir1[3], *v0, *v1, *v2;
- svbsp_count_originalpolygons++;
- for (i = 0, v0 = verts + (numverts - 2) * 3, v1 = verts + (numverts - 1) * 3, v2 = verts;i < numverts;i++, v0 = v1, v1 = v2, v2 += 3)
- {
- VectorSubtract(v0, v1, dir0);
- VectorSubtract(v2, v1, dir1);
- CrossProduct(dir0, dir1, normal);
- if (DotProduct(normal, normal) >= 0.1)
- break;
- }
- if (i == numverts)
- return;
- VectorNormalize(normal);
- dist = DotProduct(verts, normal);
- if (test && DotProduct(test, normal) > dist + 0.1)
- Con_Printf("%i %f %f %f %f : %f %f %f %f\n", linenumber, normal[0], normal[1], normal[2], dist, test[0], test[1], test[2], DotProduct(test, normal));
- Mod_SVBSP_RecursiveAddPolygon(root, numverts, verts, normal, dist, constructmode);
-}
-
-void Mod_SVBSP_RecursiveGatherStats(svbspnode_t *node)
-{
- svbsppolygon_t *poly;
- for (poly = node->polygons;poly;poly = poly->next)
- svbsp_count_polygons++;
- if (node->isleaf)
- {
- svbsp_count_leafs++;
- if (node->dark)
- svbsp_count_darkleafs++;
- }
- else
- {
- svbsp_count_nodes++;
- Mod_SVBSP_RecursiveGatherStats(node->children[0]);
- Mod_SVBSP_RecursiveGatherStats(node->children[1]);
- }
-}
-
-svbspmesh_t *Mod_SVBSP_AllocMesh(int maxverts)
-{
- svbspmesh_t *mesh;
- mesh = Mem_Alloc(loadmodel->mempool, sizeof(svbspmesh_t) + maxverts * sizeof(float[4]) + maxverts * sizeof(int[3]));
- mesh->maxverts = maxverts;
- mesh->maxtriangles = maxverts;
- mesh->numverts = 0;
- mesh->numtriangles = 0;
- mesh->verts = (float *)(mesh + 1);
- mesh->elements = (int *)(mesh->verts + mesh->maxverts * 4);
- return mesh;
-}
-
-svbspmesh_t *Mod_SVBSP_ReAllocMesh(svbspmesh_t *oldmesh)
-{
- svbspmesh_t *newmesh;
- newmesh = Mem_Alloc(loadmodel->mempool, sizeof(svbspmesh_t) + oldmesh->numverts * sizeof(float[4]) + oldmesh->numtriangles * sizeof(int[3]));
- newmesh->maxverts = newmesh->numverts = oldmesh->numverts;
- newmesh->maxtriangles = newmesh->numtriangles = oldmesh->numtriangles;
- newmesh->verts = (float *)(newmesh + 1);
- newmesh->elements = (int *)(newmesh->verts + newmesh->maxverts * 4);
- memcpy(newmesh->verts, oldmesh->verts, newmesh->numverts * sizeof(float[4]));
- memcpy(newmesh->elements, oldmesh->elements, newmesh->numtriangles * sizeof(int[3]));
- return newmesh;
-}
-
-void Mod_SVBSP_RecursiveBuildTriangleMeshs(svbspmesh_t *firstmesh, svbspnode_t *node)
-{
- svbsppolygon_t *poly;
- svbspmesh_t *mesh;
- int i, j, k;
- float *v, *m, temp[3];
- if (node->isleaf)
- {
- for (poly = node->polygons;poly;poly = poly->next)
- {
- mesh = firstmesh;
- while (poly->numverts + mesh->numverts > mesh->maxverts || (poly->numverts - 2) + mesh->numtriangles > mesh->maxtriangles)
- {
- if (mesh->next == NULL)
- mesh->next = Mod_SVBSP_AllocMesh(max(1000, poly->numverts));
- mesh = mesh->next;
- }
- for (i = 0, v = poly->verts;i < poly->numverts - 2;i++, v += 3)
- {
- for (k = 0;k < 3;k++)
- {
- if (k == 0)
- v = poly->verts;
- else if (k == 1)
- v = poly->verts + (i + 1) * 3;
- else if (k == 2)
- v = poly->verts + (i + 2) * 3;
- for (j = 0, m = mesh->verts;j < mesh->numverts;j++, m += 4)
- {
- VectorSubtract(v, m, temp);
- if (DotProduct(temp, temp) < 0.1)
- break;
- }
- if (j == mesh->numverts)
- {
- mesh->numverts++;
- VectorCopy(v, m);
- }
- mesh->elements[mesh->numtriangles * 3 + k] = j;
- }
- mesh->numtriangles++;
- }
- }
- }
- else
- {
- Mod_SVBSP_RecursiveBuildTriangleMeshs(firstmesh, node->children[0]);
- Mod_SVBSP_RecursiveBuildTriangleMeshs(firstmesh, node->children[1]);
- }
-}
-
-svbspmesh_t *Mod_SVBSP_BuildTriangleMeshs(svbspnode_t *root, vec3_t mins, vec3_t maxs)
-{
- svbspmesh_t *firstmesh, *mesh, *newmesh, *nextmesh;
- int i;
- float *v;
- firstmesh = Mod_SVBSP_AllocMesh(1000);
- Mod_SVBSP_RecursiveBuildTriangleMeshs(firstmesh, root);
- // reallocate meshs to conserve space
- for (mesh = firstmesh, firstmesh = NULL;mesh;mesh = nextmesh)
- {
- svbsp_count_meshs++;
- svbsp_count_triangles += mesh->numtriangles;
- svbsp_count_vertices += mesh->numverts;
-
- // calculate bbox
- if (firstmesh == NULL)
- {
- VectorCopy(mesh->verts, mins);
- VectorCopy(mesh->verts, maxs);
- }
- for (i = 0, v = mesh->verts;i < mesh->numverts;i++, v += 4)
- {
- if (mins[0] > v[0]) mins[0] = v[0];if (maxs[0] < v[0]) maxs[0] = v[0];
- if (mins[1] > v[1]) mins[1] = v[1];if (maxs[1] < v[1]) maxs[1] = v[1];
- if (mins[2] > v[2]) mins[2] = v[2];if (maxs[2] < v[2]) maxs[2] = v[2];
- }
-
- nextmesh = mesh->next;
- newmesh = Mod_SVBSP_ReAllocMesh(mesh);
- newmesh->next = firstmesh;
- firstmesh = newmesh;
- Mem_Free(mesh);
- }
- return firstmesh;
-}
-
-void Mod_SVBSP_FreeTriangleMeshs(svbspmesh_t *mesh)
-{
- svbspmesh_t *nextmesh;
- for (;mesh;mesh = nextmesh)
- {
- nextmesh = mesh->next;
- Mem_Free(mesh);
- }
-}
-*/
-
-typedef struct svpolygon_s
-{
- struct svpolygon_s *next;
- int maxverts;
- int numverts;
- float *verts;
- float normal[3], dist;
-}
-svpolygon_t;
-
-typedef struct svbrush_s
-{
- struct svbrush_s *next;
- svpolygon_t *polygons;
- vec3_t mins, maxs;
-}
-svbrush_t;
-
-typedef struct svworld_s
-{
- svbrush_t *brushs;
-}
-svworld_t;
-
-svworld_t *Mod_ShadowBrush_NewWorld(mempool_t *mempool)
-{
- return Mem_Alloc(mempool, sizeof(svworld_t));
-}
-
-void Mod_ShadowBrush_FreeWorld(svworld_t *world)
-{
- svbrush_t *brush, *brushnext;
- svpolygon_t *poly, *polynext;
- for (brush = world->brushs;brush;brush = brushnext)
- {
- brushnext = brush->next;
- for (poly = brush->polygons;poly;poly = polynext)
- {
- polynext = poly->next;
- Mem_Free(poly);
- }
- Mem_Free(brush);
- }
- Mem_Free(world);
-}
-
-svbrush_t *Mod_ShadowBrush_BeginBrush(mempool_t *mempool)
-{
- return Mem_Alloc(mempool, sizeof(svbrush_t));
-}
-
-void Mod_ShadowBrush_AddPolygon(mempool_t *mempool, svbrush_t *brush, int numverts, float *verts)
-{
- int i;
- float normal[3], dist, dir0[3], dir1[3], *v0, *v1, *v2;
- svpolygon_t *poly;
- for (i = 0, v0 = verts + (numverts - 2) * 3, v1 = verts + (numverts - 1) * 3, v2 = verts;i < numverts;i++, v0 = v1, v1 = v2, v2 += 3)
- {
- VectorSubtract(v0, v1, dir0);
- VectorSubtract(v2, v1, dir1);
- CrossProduct(dir0, dir1, normal);
- if (DotProduct(normal, normal) >= 0.1)
- break;
- }
- if (i == numverts)
- return;
- VectorNormalize(normal);
- dist = DotProduct(verts, normal);
-
- poly = Mem_Alloc(mempool, sizeof(svpolygon_t) + numverts * sizeof(float[3]));
- poly->numverts = numverts;
- poly->verts = (float *)(poly + 1);
- VectorCopy(normal, poly->normal);
- poly->dist = dist;
- poly->next = brush->polygons;
- brush->polygons = poly;
- memcpy(poly->verts, verts, numverts * sizeof(float[3]));
-}
-
-void Mod_ShadowBrush_AddPolygonI(mempool_t *mempool, svbrush_t *brush, int numverts, float *verts)
-{
- int i;
- float normal[3], dist, dir0[3], dir1[3], *v0, *v1, *v2;
- svpolygon_t *poly;
- for (i = 0, v0 = verts + (numverts - 2) * 3, v1 = verts + (numverts - 1) * 3, v2 = verts;i < numverts;i++, v0 = v1, v1 = v2, v2 += 3)
- {
- VectorSubtract(v0, v1, dir0);
- VectorSubtract(v2, v1, dir1);
- CrossProduct(dir0, dir1, normal);
- if (DotProduct(normal, normal) >= 0.1)
- break;
- }
- if (i == numverts)
- return;
- VectorNormalize(normal);
- dist = DotProduct(verts, normal);
- VectorNegate(normal, normal);
- dist = -dist;
-
- poly = Mem_Alloc(mempool, sizeof(svpolygon_t) + numverts * sizeof(float[3]));
- poly->numverts = numverts;
- poly->verts = (float *)(poly + 1);
- VectorCopy(normal, poly->normal);
- poly->dist = dist;
- poly->next = brush->polygons;
- brush->polygons = poly;
- for (i = 0, v0 = verts + (numverts - 1) * 3, v1 = poly->verts;i < numverts;i++, v0 -= 3, v1 += 3)
- VectorCopy(v0, v1);
-}
-
-void Mod_ShadowBrush_EndBrush(svworld_t *world, svbrush_t *brush)
-{
- int i;
- float *v;
- svpolygon_t *poly;
- if (!brush->polygons)
- {
- Mem_Free(brush);
- return;
- }
- brush->next = world->brushs;
- world->brushs = brush;
- VectorCopy(brush->polygons->verts, brush->mins);
- VectorCopy(brush->polygons->verts, brush->maxs);
- for (poly = brush->polygons;poly;poly = poly->next)
- {
- for (i = 0, v = poly->verts;i < poly->numverts;i++, v += 3)
- {
- if (brush->mins[0] > v[0]) brush->mins[0] = v[0];if (brush->maxs[0] < v[0]) brush->maxs[0] = v[0];
- if (brush->mins[1] > v[1]) brush->mins[1] = v[1];if (brush->maxs[1] < v[1]) brush->maxs[1] = v[1];
- if (brush->mins[2] > v[2]) brush->mins[2] = v[2];if (brush->maxs[2] < v[2]) brush->maxs[2] = v[2];
- }
- }
-}
-
-void Mod_ShadowBrush_ProcessWorld(mempool_t *mempool, svworld_t *world)
-{
- /*
- for (clipbrush = world->brushs;clipbrush;clipbrush = clipbrush->next)
- {
- for (brush = world->brushs;brush;brush = brush->next)
- {
- if (brush != clipbrush
- && brush->mins[0] <= clipbrush->maxs[0]
- && brush->maxs[0] >= clipbrush->mins[0]
- && brush->mins[1] <= clipbrush->maxs[1]
- && brush->maxs[1] >= clipbrush->mins[1]
- && brush->mins[2] <= clipbrush->maxs[2]
- && brush->maxs[2] >= clipbrush->mins[2])
- continue;
- for (poly = brush->polygons;poly;poly = poly->next)
- {
-
- }
- }
- }
- */
-}
-
-shadowmesh_t *Mod_ShadowBrush_BuildMeshs(mempool_t *mempool, svworld_t *world)
-{
- shadowmesh_t *mesh;
- svbrush_t *brush;
- svpolygon_t *poly;
- mesh = Mod_ShadowMesh_Begin(mempool);
- for (brush = world->brushs;brush;brush = brush->next)
- for (poly = brush->polygons;poly;poly = poly->next)
- Mod_ShadowMesh_AddPolygon(mempool, mesh, poly->numverts, poly->verts);
- mesh = Mod_ShadowMesh_Finish(mempool, mesh);
- return mesh;
-}
-