Axiom.Graphics.ShadowCaster.GenerateShadowVolume C# (CSharp) Метод

GenerateShadowVolume() защищенный Метод

Generates the indexes required to render a shadow volume into the index buffer which is passed in, and updates shadow renderables to use it.
protected GenerateShadowVolume ( EdgeData edgeData, HardwareIndexBuffer indexBuffer, Light light, ShadowRenderableList shadowRenderables, int flags ) : void
edgeData EdgeData The edge information to use.
indexBuffer HardwareIndexBuffer The buffer into which to write data into; current /// contents are assumed to be discardable.
light Axiom.Core.Light The light, mainly for type info as silhouette calculations /// should already have been done in
shadowRenderables ShadowRenderableList A list of shadow renderables which has /// already been constructed but will need populating with details of /// the index ranges to be used.
flags int Additional controller flags, see .
Результат void
		protected virtual void GenerateShadowVolume( EdgeData edgeData, HardwareIndexBuffer indexBuffer, Light light,
			ShadowRenderableList shadowRenderables, int flags )
		{
			// Edge groups should be 1:1 with shadow renderables
			Debug.Assert( edgeData.edgeGroups.Count == shadowRenderables.Count );

			LightType lightType = light.Type;

			bool extrudeToInfinity = ( flags & (int)ShadowRenderableFlags.ExtrudeToInfinity ) > 0;

			// Lock index buffer for writing
			IntPtr idxPtr = indexBuffer.Lock( BufferLocking.Discard );

			int indexStart = 0;

			unsafe
			{
				// TODO: Will currently cause an overflow for 32 bit indices, revisit
				short* pIdx = (short*)idxPtr.ToPointer();
				int count = 0;

				// Iterate over the groups and form renderables for each based on their
				// lightFacing
				for ( int groupCount = 0; groupCount < edgeData.edgeGroups.Count; groupCount++ )
				{
					EdgeData.EdgeGroup eg = (EdgeData.EdgeGroup)edgeData.edgeGroups[ groupCount ];
					ShadowRenderable si = (ShadowRenderable)shadowRenderables[ groupCount ];

					RenderOperation lightShadOp = null;

					// Initialize the index bounds for this shadow renderable
					RenderOperation shadOp = si.GetRenderOperationForUpdate();
					shadOp.indexData.indexCount = 0;
					shadOp.indexData.indexStart = indexStart;

					// original number of verts (without extruded copy)
					int originalVertexCount = eg.vertexData.vertexCount;
					bool firstDarkCapTri = true;
					int darkCapStart = 0;

					for ( int edgeCount = 0; edgeCount < eg.edges.Count; edgeCount++ )
					{
						EdgeData.Edge edge = (EdgeData.Edge)eg.edges[ edgeCount ];

						EdgeData.Triangle t1 = (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 0 ] ];
						EdgeData.Triangle t2 =
							edge.isDegenerate ? (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 0 ] ] : (EdgeData.Triangle)edgeData.triangles[ edge.triIndex[ 1 ] ];

						if ( t1.lightFacing && ( edge.isDegenerate || !t2.lightFacing ) )
						{
							/* Silhouette edge, first tri facing the light
															Also covers degenerate tris where only tri 1 is valid
															Remember verts run anticlockwise along the edge from
															tri 0 so to point shadow volume tris outward, light cap
															indexes have to be backwards

															We emit 2 tris if light is a point light, 1 if light
															is directional, because directional lights cause all
															points to converge to a single point at infinity.

															First side tri = near1, near0, far0
															Second tri = far0, far1, near1

															'far' indexes are 'near' index + originalVertexCount
															because 'far' verts are in the second half of the
															buffer
															*/
							pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
							pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
							pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
							shadOp.indexData.indexCount += 3;

							if ( !( lightType == LightType.Directional && extrudeToInfinity ) )
							{
								// additional tri to make quad
								pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
								pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
								pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
								shadOp.indexData.indexCount += 3;
							}

							// Do dark cap tri
							// Use McGuire et al method, a triangle fan covering all silhouette
							// edges and one point (taken from the initial tri)
							if ( ( flags & (int)ShadowRenderableFlags.IncludeDarkCap ) > 0 )
							{
								if ( firstDarkCapTri )
								{
									darkCapStart = edge.vertIndex[ 0 ] + originalVertexCount;
									firstDarkCapTri = false;
								}
								else
								{
									pIdx[ count++ ] = (short)darkCapStart;
									pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
									pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
									shadOp.indexData.indexCount += 3;
								}
							}
						}
						else if ( !t1.lightFacing && ( edge.isDegenerate || t2.lightFacing ) )
						{
							// Silhouette edge, second tri facing the light
							// Note edge indexes inverse of when t1 is light facing
							pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
							pIdx[ count++ ] = (short)edge.vertIndex[ 1 ];
							pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
							shadOp.indexData.indexCount += 3;

							if ( !( lightType == LightType.Directional && extrudeToInfinity ) )
							{
								// additional tri to make quad
								pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
								pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
								pIdx[ count++ ] = (short)edge.vertIndex[ 0 ];
								shadOp.indexData.indexCount += 3;
							}

							// Do dark cap tri
							// Use McGuire et al method, a triangle fan covering all silhouette
							// edges and one point (taken from the initial tri)
							if ( ( flags & (int)ShadowRenderableFlags.IncludeDarkCap ) > 0 )
							{
								if ( firstDarkCapTri )
								{
									darkCapStart = edge.vertIndex[ 1 ] + originalVertexCount;
									firstDarkCapTri = false;
								}
								else
								{
									pIdx[ count++ ] = (short)darkCapStart;
									pIdx[ count++ ] = (short)( edge.vertIndex[ 0 ] + originalVertexCount );
									pIdx[ count++ ] = (short)( edge.vertIndex[ 1 ] + originalVertexCount );
									shadOp.indexData.indexCount += 3;
								}
							}
						}
					}

					// Do light cap
					if ( ( flags & (int)ShadowRenderableFlags.IncludeLightCap ) > 0 )
					{
						ShadowRenderable lightCapRend = null;

						if ( si.IsLightCapSeperate )
						{
							// separate light cap
							lightCapRend = si.LightCapRenderable;
							lightShadOp = lightCapRend.GetRenderOperationForUpdate();
							lightShadOp.indexData.indexCount = 0;
							// start indexes after the current total
							// NB we don't update the total here since that's done below
							lightShadOp.indexData.indexStart =
								indexStart + shadOp.indexData.indexCount;
						}

						for ( int triCount = 0; triCount < edgeData.triangles.Count; triCount++ )
						{
							EdgeData.Triangle t = (EdgeData.Triangle)edgeData.triangles[ triCount ];

							// Light facing, and vertex set matches
							if ( t.lightFacing && t.vertexSet == eg.vertexSet )
							{
								pIdx[ count++ ] = (short)t.vertIndex[ 0 ];
								pIdx[ count++ ] = (short)t.vertIndex[ 1 ];
								pIdx[ count++ ] = (short)t.vertIndex[ 2 ];

								if ( lightShadOp != null )
								{
									lightShadOp.indexData.indexCount += 3;
								}
								else
								{
									shadOp.indexData.indexCount += 3;
								}
							}
						}
					}

					// update next indexStart (all renderables sharing the buffer)
					indexStart += shadOp.indexData.indexCount;

					// add on the light cap too
					if ( lightShadOp != null )
					{
						indexStart += lightShadOp.indexData.indexCount;
					}
				}
			}

			// Unlock index buffer
			indexBuffer.Unlock();

			Debug.Assert( indexStart <= indexBuffer.IndexCount, "Index buffer overrun while generating shadow volume!" );
		}