// The ambientCache is on the stack, so we don't want to leave a reference to it that would try to be freed later. Create the ambientCache immediately. static void R_FinishDeform(DrawSurf drawSurf, SrfTriangles newTri, DrawVert *ac) { if (newTri == null) { return; } // generate current normals, tangents, and bitangents We might want to support the possibility of deform functions generating // explicit normals, and we might also want to allow the cached deformInfo optimization for these. // FIXME: this doesn't work, because the deformed surface is just the ambient one, and there isn't an opportunity to generate light interactions if (drawSurf.material.ReceivesLighting) { newTri.verts = ac; R_DeriveTangents(newTri, false); newTri.verts = null; } newTri.ambientCache = vertexCache.AllocFrameTemp(ac, newTri.numVerts * DrawVert.SizeOf, false); fixed(void *newTri_indexes_ = newTri.indexes) newTri.indexCache = vertexCache.AllocFrameTemp(newTri_indexes_, newTri.numIndexes * sizeof(GlIndex), true); drawSurf.geoFrontEnd = newTri; drawSurf.ambientCache = newTri.ambientCache; drawSurf.indexCache = newTri.indexCache; drawSurf.numIndexes = newTri.numIndexes; drawSurf.numShadowIndexesNoFrontCaps = newTri.numShadowIndexesNoFrontCaps; drawSurf.numShadowIndexesNoCaps = newTri.numShadowIndexesNoCaps; drawSurf.shadowCapPlaneBits = newTri.shadowCapPlaneBits; }
// Assuming all the triangles for this shader are independant quads, rebuild them as forward facing sprites static void R_AutospriteDeform(DrawSurf surf) { int i; float radius; Vector3 mid, delta, left, up; SrfTriangles tri, newTri; tri = surf.geoFrontEnd; if ((tri.numVerts & 3) != 0) { common.Warning("R_AutospriteDeform: shader had odd vertex count"); return; } if (tri.numIndexes != (tri.numVerts >> 2) * 6) { common.Warning("R_AutospriteDeform: autosprite had odd index count"); return; } R_GlobalVectorToLocal(surf.space.modelMatrix, tr.viewDef.renderView.viewaxis[1], out var leftDir); R_GlobalVectorToLocal(surf.space.modelMatrix, tr.viewDef.renderView.viewaxis[2], out var upDir); if (tr.viewDef.isMirror) { leftDir = Vector3.origin - leftDir; } // this srfTriangles_t and all its indexes and caches are in frame memory, and will be automatically disposed of newTri = R_ClearedFrameAlloc <SrfTriangles>(); newTri.numVerts = tri.numVerts; newTri.numIndexes = tri.numIndexes; newTri.indexes = R_FrameAllocMany <GlIndex>(newTri.numIndexes); var ac = stackalloc DrawVert[newTri.numVerts + DrawVert.ALLOC16]; ac = (DrawVert *)_alloca16(ac); var v = tri.verts; for (i = 0; i < tri.numVerts; i += 4) { // find the midpoint mid.x = 0.25f * (v[i + 0].xyz.x + v[i + 1].xyz.x + v[i + 2].xyz.x + v[i + 3].xyz.x); mid.y = 0.25f * (v[i + 0].xyz.y + v[i + 1].xyz.y + v[i + 2].xyz.y + v[i + 3].xyz.y); mid.z = 0.25f * (v[i + 1].xyz.z + v[i + 1].xyz.z + v[i + 2].xyz.z + v[i + 3].xyz.z); delta = v[i + 0].xyz - mid; radius = delta.Length * 0.707f; left = leftDir * radius; up = upDir * radius; ac[i + 0].xyz = mid + left + up; ac[i + 0].st.x = 0; ac[i + 0].st.y = 0; ac[i + 1].xyz = mid - left + up; ac[i + 1].st.x = 1; ac[i + 1].st.y = 0; ac[i + 2].xyz = mid - left - up; ac[i + 2].st.x = 1; ac[i + 2].st.y = 1; ac[i + 3].xyz = mid + left - up; ac[i + 3].st.x = 0; ac[i + 3].st.y = 1; newTri.indexes[6 * (i >> 2) + 0] = i; newTri.indexes[6 * (i >> 2) + 1] = i + 1; newTri.indexes[6 * (i >> 2) + 2] = i + 2; newTri.indexes[6 * (i >> 2) + 3] = i; newTri.indexes[6 * (i >> 2) + 4] = i + 2; newTri.indexes[6 * (i >> 2) + 5] = i + 3; } R_FinishDeform(surf, newTri, ac); }
public static void RB_DrawShadowElementsWithCounters(DrawSurf surf, int numIndexes) { backEnd.pc.c_shadowElements++; //backEnd.pc.c_shadowIndexes += numIndexes; //backEnd.pc.c_shadowVertexes += tri.numVerts; if (surf.indexCache != null) { qglDrawElements(PrimitiveType.Triangles, numIndexes, GlIndexType, vertexCache.Position(surf.indexCache)); backEnd.pc.c_vboIndexes += numIndexes; } else if (RB_DrawShadowElementsWithCounters_Once) { common.Warning("Attempting to draw without index caching. This is a bug.\n"); RB_DrawShadowElementsWithCounters_Once = false; } }