Beispiel #1
0
        public static uint IntRead(BufferBase src, int n)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                switch (n)
                {
                case 1:
                    return(src.ToBytePointer()[0]);

                case 2:
                    return(src.ToUShortPointer()[0]);

                case 3:
                    var s = src.ToBytePointer();
#if AXIOM_BIG_ENDIAN
                    return((uint)(s[0] << 16 |
                                  (s[1] << 8) |
                                  (s[2])));
#else
                    return((uint)(s[0] | (s[1] << 8) | (s[2] << 16)));
#endif
                case 4:
                    return(src.ToUIntPointer()[0]);
                }

                return(0); // ?
            }
        }
Beispiel #2
0
        public static void IntWrite(BufferBase dest, int n, uint value)
        {
#if !AXIOM_SAFE_ONLY
            unsafe
#endif
            {
                switch (n)
                {
                case 1:
                    dest.ToBytePointer()[0] = (byte)value;
                    break;

                case 2:
                    dest.ToUShortPointer()[0] = (ushort)value;
                    break;

                case 3:
                    var d = dest.ToBytePointer();
#if AXIOM_BIG_ENDIAN
                    d[0] = (byte)((value >> 16) & 0xFF);
                    d[1] = (byte)((value >> 8) & 0xFF);
                    d[2] = (byte)(value & 0xFF);
#else
                    d[2] = (byte)((value >> 16) & 0xFF);
                    d[1] = (byte)((value >> 8) & 0xFF);
                    d[0] = (byte)(value & 0xFF);
#endif
                    break;

                case 4:
                    dest.ToUIntPointer()[0] = value;
                    break;
                }
            }
        }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToUShortPointer();
                    var outputPtr = output.ToBytePointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = (byte)(inp >> 8);
                }
            }
            public void Convert(BufferBase input, BufferBase output, int offset)
            {
#if !AXIOM_SAFE_ONLY
                unsafe
#endif
                {
                    var inputPtr  = input.ToBytePointer();
                    var outputPtr = output.ToUShortPointer();
                    var inp       = inputPtr[offset];

                    outputPtr[offset] = (ushort)((((uint)inp) << 8) | (((uint)inp)));
                }
            }
Beispiel #5
0
		/// <summary>
		///		Caches a face group and calculates texture lighting coordinates.
		/// </summary>
		protected int CacheLightGeometry( TextureLight light, BufferBase pIndexesBuf, BufferBase pTexLightMapsBuf,
		                                  BufferBase pVerticesBuf, BspStaticFaceGroup faceGroup )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				// Skip sky always
				if ( faceGroup.isSky )
				{
					return 0;
				}

				int idxStart = 0;
				int numIdx = 0;
				int vertexStart = 0;

				if ( faceGroup.type == FaceGroup.FaceList )
				{
					idxStart = faceGroup.elementStart;
					numIdx = faceGroup.numElements;
					vertexStart = faceGroup.vertexStart;
				}
				else if ( faceGroup.type == FaceGroup.Patch )
				{
					idxStart = faceGroup.patchSurf.IndexOffset;
					numIdx = faceGroup.patchSurf.CurrentIndexCount;
					vertexStart = faceGroup.patchSurf.VertexOffset;
				}
				else
				{
					// Unsupported face type
					return 0;
				}

				var idxSize = this.level.Indexes.IndexSize;
				var idxSrc = this.level.Indexes.Lock( idxStart*idxSize, numIdx*idxSize, BufferLocking.ReadOnly );
#if SILVERLIGHT
				var src = idxSrc.ToUShortPointer();
#else
				var src = idxSrc.ToUIntPointer();
#endif

				int maxIndex = 0;
				for ( int i = 0; i < numIdx; i++ )
				{
					var index = (int)src[ i ];
					if ( index > maxIndex )
					{
						maxIndex = index;
					}
				}

				var vertexPos = new Vector3[maxIndex + 1];
				var vertexIsStored = new bool[maxIndex + 1];

				for ( int i = 0; i < numIdx; i++ )
				{
					var index = (int)src[ i ];
					var pVertices = pVerticesBuf.ToBspVertexPointer();
					if ( !vertexIsStored[ index ] )
					{
						vertexPos[ index ] = pVertices[ vertexStart + index ].position;
						vertexIsStored[ index ] = true;
					}
					pVerticesBuf.UnPin();
				}

				Vector2[] texCoors;
				ColorEx[] colors;

				bool res = light.CalculateTexCoordsAndColors( faceGroup.plane, vertexPos, out texCoors, out colors );

				if ( res )
				{
					var pTexLightMaps = pTexLightMapsBuf.ToTextureLightMapPointer();
					for ( int i = 0; i <= maxIndex; i++ )
					{
						pTexLightMaps[ vertexStart + i ] = new TextureLightMap
						                                   {
						                                   	color = Root.Instance.RenderSystem.ConvertColor( colors[ i ] ),
						                                   	textureLightMap = texCoors[ i ]
						                                   };
					}
					pTexLightMapsBuf.UnPin();

					// Offset the indexes here
					// we have to do this now rather than up-front because the
					// indexes are sometimes reused to address different vertex chunks
					if ( this.level.Indexes.Type == IndexType.Size16 )
					{
						var pIndexes = pIndexesBuf.ToUShortPointer();
						for ( int i = 0; i < numIdx; i++ )
						{
							pIndexes[ i ] = (ushort)( src[ i ] + vertexStart );
						}
					}
					else
					{
						var pIndexes = pIndexesBuf.ToUIntPointer();
						for ( int i = 0; i < numIdx; i++ )
						{
							pIndexes[ i ] = (uint)( src[ i ] + vertexStart );
						}
					}
					this.level.Indexes.Unlock();

					// return number of elements
					return numIdx;
				}
				else
				{
					this.level.Indexes.Unlock();

					return 0;
				}
			}
		}
Beispiel #6
0
		/// <summary>
		///		Caches a face group for imminent rendering.
		/// </summary>
		protected int CacheGeometry( BufferBase indexes, BspStaticFaceGroup faceGroup )
		{
			// Skip sky always
			if ( faceGroup.isSky )
			{
				return 0;
			}

			int idxStart = 0;
			int numIdx = 0;
			int vertexStart = 0;

			if ( faceGroup.type == FaceGroup.FaceList )
			{
				idxStart = faceGroup.elementStart;
				numIdx = faceGroup.numElements;
				vertexStart = faceGroup.vertexStart;
			}
			else if ( faceGroup.type == FaceGroup.Patch )
			{
				idxStart = faceGroup.patchSurf.IndexOffset;
				numIdx = faceGroup.patchSurf.CurrentIndexCount;
				vertexStart = faceGroup.patchSurf.VertexOffset;
			}
			else
			{
				// Unsupported face type
				return 0;
			}

#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				// Offset the indexes here
				// we have to do this now rather than up-front because the
				// indexes are sometimes reused to address different vertex chunks
				var idxSize = this.level.Indexes.IndexSize;
				var idxSrc = this.level.Indexes.Lock( idxStart*idxSize, numIdx*idxSize, BufferLocking.ReadOnly );
				if ( this.level.Indexes.Type == IndexType.Size16 )
				{
					var src = idxSrc.ToUShortPointer();
					var pIndexes = indexes.ToUShortPointer();
					for ( int i = 0; i < numIdx; i++ )
					{
						pIndexes[ i ] = (ushort)( src[ i ] + vertexStart );
					}
				}
				else
				{
					var src = idxSrc.ToUIntPointer();
					var pIndexes = indexes.ToUIntPointer();
					for ( int i = 0; i < numIdx; i++ )
					{
						pIndexes[ i ] = (uint)( src[ i ] + vertexStart );
					}
				}
				this.level.Indexes.Unlock();
			}

			// return number of elements
			return numIdx;
		}
		public int StitchEdge( Neighbor neighbor, int hiLOD, int loLOD, bool omitFirstTri, bool omitLastTri, BufferBase ppIdx )
#endif
		{
			Debug.Assert( loLOD > hiLOD, "TerrainZoneRenderable.StitchEdge" );
			/*
			Now do the stitching; we can stitch from any level to any level.
			The stitch pattern is like this for each pair of vertices in the lower LOD
			(excuse the poor ascii art):

			lower LOD
			*-----------*
			|\  \ 3 /  /|
			|1\2 \ / 4/5|
			*--*--*--*--*
			higher LOD

			The algorithm is, for each pair of lower LOD vertices:
			1. Iterate over the higher LOD vertices, generating tris connected to the
			first lower LOD vertex, up to and including 1/2 the span of the lower LOD
			over the higher LOD (tris 1-2). Skip the first tri if it is on the edge
			of the tile and that edge is to be stitched itself.
			2. Generate a single tri for the middle using the 2 lower LOD vertices and
			the middle vertex of the higher LOD (tri 3).
			3. Iterate over the higher LOD vertices from 1/2 the span of the lower LOD
			to the end, generating tris connected to the second lower LOD vertex
			(tris 4-5). Skip the last tri if it is on the edge of a tile and that
			edge is to be stitched itself.

			The same algorithm works for all edges of the patch; stitching is done
			clockwise so that the origin and steps used change, but the general
			approach does not.
			*/

			// Get pointer to be updated
			var pIdx = ppIdx.ToUShortPointer();
			var idx = 0;

			// Work out the steps ie how to increment indexes
			// Step from one vertex to another in the high detail version
			var step = 1 << hiLOD;
			// Step from one vertex to another in the low detail version
			var superstep = 1 << loLOD;
			// Step half way between low detail steps
			var halfsuperstep = superstep >> 1;

			// Work out the starting points and sign of increments
			// We always work the strip clockwise
			int startx, starty, endx, rowstep;
			startx = starty = endx = rowstep = 0;
			var horizontal = false;
			switch ( neighbor )
			{
				case Neighbor.NORTH:
					startx = starty = 0;
					endx = this.mOptions.tileSize - 1;
					rowstep = step;
					horizontal = true;
					break;
				case Neighbor.SOUTH:
					// invert x AND y direction, helps to keep same winding
					startx = starty = this.mOptions.tileSize - 1;
					endx = 0;
					rowstep = -step;
					step = -step;
					superstep = -superstep;
					halfsuperstep = -halfsuperstep;
					horizontal = true;
					break;
				case Neighbor.EAST:
					startx = 0;
					endx = this.mOptions.tileSize - 1;
					starty = this.mOptions.tileSize - 1;
					rowstep = -step;
					horizontal = false;
					break;
				case Neighbor.WEST:
					startx = this.mOptions.tileSize - 1;
					endx = 0;
					starty = 0;
					rowstep = step;
					step = -step;
					superstep = -superstep;
					halfsuperstep = -halfsuperstep;
					horizontal = false;
					break;
			}

			var numIndexes = 0;

			for ( var j = startx; j != endx; j += superstep )
			{
				int k;
				for ( k = 0; k != halfsuperstep; k += step )
				{
					var jk = j + k;
					//skip the first bit of the corner?
					if ( j != startx || k != 0 || !omitFirstTri )
					{
						if ( horizontal )
						{
							pIdx[ idx++ ] = Index( jk, starty + rowstep );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( jk + step, starty + rowstep );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( j, starty );
							numIndexes++; // original order: 1
						}
						else
						{
							pIdx[ idx++ ] = Index( starty + rowstep, jk );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( starty + rowstep, jk + step );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( starty, j );
							numIndexes++; // original order: 1
						}
					}
				}

				// Middle tri
				if ( horizontal )
				{
					pIdx[ idx++ ] = Index( j + halfsuperstep, starty + rowstep );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( j + superstep, starty );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( j, starty );
					numIndexes++; // original order: 1
				}
				else
				{
					pIdx[ idx++ ] = Index( starty + rowstep, j + halfsuperstep );
					numIndexes++; // original order: 2
					pIdx[ idx++ ] = Index( starty, j + superstep );
					numIndexes++; // original order: 3
					pIdx[ idx++ ] = Index( starty, j );
					numIndexes++; // original order: 1
				}

				for ( k = halfsuperstep; k != superstep; k += step )
				{
					var jk = j + k;
					if ( j != endx - superstep || k != superstep - step || !omitLastTri )
					{
						if ( horizontal )
						{
							pIdx[ idx++ ] = Index( jk, starty + rowstep );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( jk + step, starty + rowstep );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( j + superstep, starty );
							numIndexes++; // original order: 1
						}
						else
						{
							pIdx[ idx++ ] = Index( starty + rowstep, jk );
							numIndexes++; // original order: 2
							pIdx[ idx++ ] = Index( starty + rowstep, jk + step );
							numIndexes++; // original order: 3
							pIdx[ idx++ ] = Index( starty, j + superstep );
							numIndexes++; // original order: 1
						}
					}
				}
			}

			ppIdx.Ptr += idx*sizeof ( ushort );

			return numIndexes;
		}
Beispiel #8
0
		internal static void PopulateIndexBuffer( BufferBase pIndexes, ushort batchSize, ushort vdatasize, int vertexIncrement,
												  ushort xoffset, ushort yoffset, ushort numSkirtRowsCols,
												  ushort skirtRowColSkip )
		{
			/* For even / odd tri strip rows, triangles are this shape:
			6---7---8
			| \ | \ |
			3---4---5
			| / | / |
			0---1---2
			Note how vertex rows count upwards. In order to match up the anti-clockwise
			winding and this upward transitioning list, we need to start from the
			right hand side. So we get (2,5,1,4,0,3) etc on even lines (right-left)
			and (3,6,4,7,5,8) etc on odd lines (left-right). At the turn, we emit the end index 
			twice, this forms a degenerate triangle, which lets us turn without any artefacts. 
			So the full list in this simple case is (2,5,1,4,0,3,3,6,4,7,5,8)

			Skirts are part of the same strip, so after finishing on 8, where sX is
			the skirt vertex corresponding to main vertex X, we go
			anticlockwise around the edge, (s8,7,s7,6,s6) to do the top skirt, 
			then (3,s3,0,s0),(1,s1,2,s2),(5,s5,8,s8) to finish the left, bottom, and
			right skirts respectively.
			*/

			// to issue a complete row, it takes issuing the upper and lower row
			// and one extra index, which is the degenerate triangle and also turning
			// around the winding
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				var rowSize = vdatasize*vertexIncrement;
				var numRows = batchSize - 1;
				var pI = pIndexes.ToUShortPointer();
				var offset = 0;

				// Start on the right
				var currentVertex = (ushort)( ( batchSize - 1 )*vertexIncrement );
				// but, our quad area might not start at 0 in this vertex data
				// offsets are at main terrain resolution, remember
				var columnStart = xoffset;
				var rowStart = yoffset;
				currentVertex += (ushort)( rowStart*vdatasize + columnStart );
				var rightToLeft = true;
				for ( ushort r = 0; r < numRows; ++r )
				{
					for ( var c = 0; c < batchSize; ++c )
					{
						pI[ offset++ ] = currentVertex;
						pI[ offset++ ] = (ushort)( currentVertex + rowSize );

						// don't increment / decrement at a border, keep this vertex for next
						// row as we 'snake' across the tile
						if ( c + 1 < batchSize )
						{
							currentVertex = rightToLeft
												? (ushort)( currentVertex - vertexIncrement )
												: (ushort)( currentVertex + vertexIncrement );
						}
					}
					rightToLeft = !rightToLeft;
					currentVertex += (ushort)rowSize;
					// issue one extra index to turn winding around
					pI[ offset++ ] = currentVertex;
				}

				// Skirts
				for ( ushort s = 0; s < 4; ++s )
				{
					// edgeIncrement is the index offset from one original edge vertex to the next
					// in this row or column. Columns skip based on a row size here
					// skirtIncrement is the index offset from one skirt vertex to the next, 
					// because skirts are packed in rows/cols then there is no row multiplier for
					// processing columns
					int edgeIncrement = 0, skirtIncrement = 0;
					switch ( s )
					{
						case 0: // top
							edgeIncrement = -(int)vertexIncrement;
							skirtIncrement = -(int)vertexIncrement;
							break;

						case 1: // left
							edgeIncrement = -(int)rowSize;
							skirtIncrement = -(int)vertexIncrement;
							break;

						case 2: // bottom
							edgeIncrement = (int)vertexIncrement;
							skirtIncrement = (int)vertexIncrement;
							break;

						case 3: // right
							edgeIncrement = (int)rowSize;
							skirtIncrement = (int)vertexIncrement;
							break;
					}
					// Skirts are stored in contiguous rows / columns (rows 0/2, cols 1/3)
					var skirtIndex = CalcSkirtVertexIndex( currentVertex, vdatasize, ( s%2 ) != 0, numSkirtRowsCols, skirtRowColSkip );

					for ( var c = 0; c < batchSize - 1; ++c )
					{
						pI[ offset++ ] = currentVertex;
						pI[ offset++ ] = skirtIndex;
						currentVertex += (ushort)edgeIncrement;
						skirtIndex += (ushort)skirtIncrement;
					}

					if ( s == 3 )
					{
						// we issue an extra 2 indices to finish the skirt off
						pI[ offset++ ] = currentVertex;
						pI[ offset++ ] = skirtIndex;
						currentVertex += (ushort)edgeIncrement;
						skirtIndex += (ushort)skirtIncrement;
					}
				}
			}
		}
Beispiel #9
0
		public static uint IntRead( BufferBase src, int n )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				switch ( n )
				{
					case 1:
						return src.ToBytePointer()[ 0 ];

					case 2:
						return src.ToUShortPointer()[ 0 ];

					case 3:
						var s = src.ToBytePointer();
#if AXIOM_BIG_ENDIAN
						return (uint)( s[ 0 ] << 16 |
									   ( s[ 1 ] << 8 ) |
									   ( s[ 2 ] ) );
#else
						return (uint)( s[ 0 ] | ( s[ 1 ] << 8 ) | ( s[ 2 ] << 16 ) );
#endif
					case 4:
						return src.ToUIntPointer()[ 0 ];
				}

				return 0; // ?
			}
		}
Beispiel #10
0
		public static void IntWrite( BufferBase dest, int n, uint value )
		{
#if !AXIOM_SAFE_ONLY
			unsafe
#endif
			{
				switch ( n )
				{
					case 1:
						dest.ToBytePointer()[ 0 ] = (byte)value;
						break;

					case 2:
						dest.ToUShortPointer()[ 0 ] = (ushort)value;
						break;

					case 3:
						var d = dest.ToBytePointer();
#if AXIOM_BIG_ENDIAN
						d[ 0 ] = (byte)( ( value >> 16 ) & 0xFF );
						d[ 1 ] = (byte)( ( value >> 8 ) & 0xFF );
						d[ 2 ] = (byte)( value & 0xFF );
#else
						d[ 2 ] = (byte)( ( value >> 16 ) & 0xFF );
						d[ 1 ] = (byte)( ( value >> 8 ) & 0xFF );
						d[ 0 ] = (byte)( value & 0xFF );
#endif
						break;

					case 4:
						dest.ToUIntPointer()[ 0 ] = value;
						break;
				}
			}
		}