//====================================================================================== // Creates all needed model references in portal areas, chaining them to both the area and the entityDef. Bumps tr.viewCount. public static void R_CreateEntityRefs(IRenderEntity def) { int i; Vector3 v; var transformed = stackalloc Vector3[8]; if (def.parms.hModel == null) { def.parms.hModel = renderModelManager.DefaultModel(); } // if the entity hasn't been fully specified due to expensive animation calcs for md5 and particles, use the provided conservative bounds. def.referenceBounds = def.parms.callback != null ? def.parms.bounds : def.parms.hModel.Bounds(def.parms); // some models, like empty particles, may not need to be added at all if (def.referenceBounds.IsCleared) { return; } if (r_showUpdates.Bool && ( def.referenceBounds[1].x - def.referenceBounds[0].x > 1024 || def.referenceBounds[1].y - def.referenceBounds[0].y > 1024)) { common.Printf($"big entityRef: {def.referenceBounds[1].x - def.referenceBounds[0].x},{def.referenceBounds[1].y - def.referenceBounds[0].y}\n"); } for (i = 0; i < 8; i++) { v.x = def.referenceBounds[i & 1][0]; v.y = def.referenceBounds[(i >> 1) & 1][1]; v.z = def.referenceBounds[(i >> 2) & 1][2]; R_LocalPointToGlobal(def.modelMatrix, v, out transformed[i]); } // bump the view count so we can tell if an area already has a reference tr.viewCount++; // push these points down the BSP tree into areas def.world.PushVolumeIntoTree(def, null, 8, transformed); }
// are dangling edges that are outside the light frustum still making planes? public static SrfTriangles R_CreateVertexProgramTurboShadowVolume(IRenderEntity ent, SrfTriangles tri, IRenderLight light, ref SrfCullInfo cullInfo) { int i, j; SrfTriangles newTri; GlIndex[] indexes; byte *facing; var tri_indexes = tri.indexes; var tri_silEdges = tri.silEdges; R_CalcInteractionFacing(ent, tri, light, ref cullInfo); if (r_useShadowProjectedCull.Bool) { R_CalcInteractionCullBits(ent, tri, light, ref cullInfo); } var numFaces = tri.numIndexes / 3; var numShadowingFaces = 0; facing = cullInfo.facing; // if all the triangles are inside the light frustum if (cullInfo.cullBits == Interaction.LIGHT_CULL_ALL_FRONT || !r_useShadowProjectedCull.Bool) { // count the number of shadowing faces for (i = 0; i < numFaces; i++) { numShadowingFaces += facing[i]; } numShadowingFaces = numFaces - numShadowingFaces; } else { // make all triangles that are outside the light frustum "facing", so they won't cast shadows indexes = tri_indexes; var modifyFacing = cullInfo.facing; var cullBits = cullInfo.cullBits; for (j = i = 0; i < tri.numIndexes; i += 3, j++) { if (modifyFacing[j] == 0) { var i1 = indexes[i + 0]; var i2 = indexes[i + 1]; var i3 = indexes[i + 2]; if ((cullBits[i1] & cullBits[i2] & cullBits[i3]) != 0) { modifyFacing[j] = 1; } else { numShadowingFaces++; } } } } // no faces are inside the light frustum and still facing the right way if (numShadowingFaces == 0) { return(null); } // shadowVerts will be NULL on these surfaces, so the shadowVerts will be taken from the ambient surface newTri = R_AllocStaticTriSurf(); newTri.numVerts = tri.numVerts * 2; // alloc the max possible size #if USE_TRI_DATA_ALLOCATOR R_AllocStaticTriSurfIndexes(newTri, (numShadowingFaces + tri.numSilEdges) * 6); GlIndex tempIndexes = newTri.indexes; GlIndex shadowIndexes = newTri.indexes; #else GlIndex *tempIndexes = stackalloc GlIndex[tri.numSilEdges * 6 + intX.ALLOC16]; tempIndexes = (GlIndex *)_alloca16(tempIndexes); GlIndex *shadowIndexes = tempIndexes; #endif // create new triangles along sil planes SilEdge sil; for (sil = tri_silEdges, i = tri.numSilEdges; i > 0; i--, sil++) { int f1 = facing[sil.p1], f2 = facing[sil.p2]; if ((f1 ^ f2) == 0) { continue; } int v1 = sil.v1 << 1, v2 = sil.v2 << 1; // set the two triangle winding orders based on facing without using a poorly-predictable branch shadowIndexes[0] = v1; shadowIndexes[1] = v2 ^ f1; shadowIndexes[2] = v2 ^ f2; shadowIndexes[3] = v1 ^ f2; shadowIndexes[4] = v1 ^ f1; shadowIndexes[5] = v2 ^ 1; shadowIndexes += 6; } int numShadowIndexes = shadowIndexes - tempIndexes; // we aren't bothering to separate front and back caps on these newTri.numIndexes = newTri.numShadowIndexesNoFrontCaps = numShadowIndexes + numShadowingFaces * 6; newTri.numShadowIndexesNoCaps = numShadowIndexes; newTri.shadowCapPlaneBits = SHADOW_CAP_INFINITE; #if USE_TRI_DATA_ALLOCATOR // decrease the size of the memory block to only store the used indexes R_ResizeStaticTriSurfIndexes(newTri, newTri.numIndexes); #else // allocate memory for the indexes R_AllocStaticTriSurfIndexes(newTri, newTri.numIndexes); // copy the indexes we created for the sil planes Simd.Memcpy(newTri.indexes, tempIndexes, numShadowIndexes * sizeof(GlIndex)); #endif // these have no effect, because they extend to infinity newTri.bounds.Clear(); // put some faces on the model and some on the distant projection indexes = tri_indexes; shadowIndexes = newTri.indexes + numShadowIndexes; for (i = 0, j = 0; i < tri.numIndexes; i += 3, j++) { if (facing[j] != 0) { continue; } var i0 = indexes[i + 0] << 1; shadowIndexes[2] = i0; shadowIndexes[3] = i0 ^ 1; var i1 = indexes[i + 1] << 1; shadowIndexes[1] = i1; shadowIndexes[4] = i1 ^ 1; var i2 = indexes[i + 2] << 1; shadowIndexes[0] = i2; shadowIndexes[5] = i2 ^ 1; shadowIndexes += 6; } return(newTri); }