//--------------------------------------------------------------- #region Variables and Properties //--------------------------------------------------------------- //--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Initialisation //--------------------------------------------------------------- //--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- /// <summary> /// Fills a positionStream with skinned position data. /// </summary> /// <param name="target">The target position stream.</param> /// <param name="source">The source vector data.</param> /// <param name="bis">The stream containing the bone indices.</param> /// <param name="bws">The stream containing the bone weights.</param> /// <param name="joints">The bones to use for skinning.</param> /// <param name="skinShadow">Should the shadow part also be skinned?</param> public static void SoftSkin(PositionStream target, Vector3[] source, IBoneIndicesStream bis, IBoneWeightsStream bws, Matrix4[] joints, bool skinShadow) { // For every vertex, multiply the source vector with the influencing bones, weight and add the // result to the final result. Vector3[] targetData = (Vector3[])target.Data; Array.Clear(targetData, 0, targetData.Length); for (int i = 0; i < source.Length; i++) { //targetData[i].SetZero(); byte[] indices = bis.GetIndices(i); float[] weights = bws.GetWeights(i); int length = indices.Length; for (int iWeight = 0; iWeight < length; iWeight++) { targetData[i].AddSkinned(source[i], ref joints[indices[iWeight]], weights[iWeight]); /*Vector3 sourceVec = source[i]; * sourceVec.Mul( ref joints[ indices[iWeight] ] ); * targetData[i].AddWeighted( sourceVec, weights[iWeight] );*/ } } if (skinShadow) { // is is ShadowVolumePrepared? if (target.Size != source.Length) { System.Diagnostics.Debug.Assert(target.Size == source.Length * 2, "Target positionStream must be the same size as source array - or twice the size of shadowVolumePrepared meshes!"); Array.Copy(target.Data, 0, target.Data, source.Length, source.Length); } } }
/// <summary> /// Blends two meshes. /// </summary> /// <param name="fromIndexA">The index of the first mesh to blend from.</param> /// <param name="toIndexA">The index of the first mesh to blend to.</param> /// <param name="factorA">The blend factor of the first mesh.</param> /// <param name="fromIndexB">The index of the second mesh to blend from.</param> /// <param name="toIndexB">The index of the second mesh to blend to.</param> /// <param name="factorB">The blend factor of the second mesh.</param> /// <param name="factor">The blend factor between meshA and meshB.</param> public void Blend(int fromIndexA, int toIndexA, float factorA, int fromIndexB, int toIndexB, float factorB, float factor) { CreateMesh(); if (factor < float.Epsilon) { Blend(fromIndexA, toIndexA, factorA); } else if (factor >= 1.0f - float.Epsilon) { Blend(fromIndexB, toIndexB, factorB); } else { for (int i = 0; i < tempMesh.SubSets.Count; i++) { SubSet ssTarget = (SubSet)tempMesh.SubSets[i]; PositionStream psTarget = (PositionStream)ssTarget.VertexUnit[typeof(PositionStream)]; SubSet ssSourceA = (SubSet)meshes[fromIndexA].SubSets[i]; PositionStream psSourceA = (PositionStream)ssSourceA.VertexUnit[typeof(PositionStream)]; SubSet ssSourceB = (SubSet)meshes[toIndexA].SubSets[i]; PositionStream psSourceB = (PositionStream)ssSourceB.VertexUnit[typeof(PositionStream)]; SubSet ssSourceC = (SubSet)meshes[fromIndexB].SubSets[i]; PositionStream psSourceC = (PositionStream)ssSourceC.VertexUnit[typeof(PositionStream)]; SubSet ssSourceD = (SubSet)meshes[toIndexB].SubSets[i]; PositionStream psSourceD = (PositionStream)ssSourceD.VertexUnit[typeof(PositionStream)]; for (int l = 0; l < psTarget.Size; l++) { psTarget[l] = Vector3.Lerp(Vector3.Lerp(psSourceA[l], psSourceB[l], factorA), Vector3.Lerp(psSourceC[l], psSourceD[l], factorB), factor); } psTarget.Upload(); } } }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- /// <summary> /// Does the manipulation. /// </summary> public void Do() { for (int iSubSet = 0; iSubSet < subSets.Length; iSubSet++) { //Interpolate(animatedJoints, anim.Frames[player.FrameIndex].JointArray, // anim.Frames[player.NextFrameIndex].JointArray, player.Weight); //player.Interpolate(animatedJoints, anim.Frames); if (bindings[iSubSet] == -1) { tags[iSubSet] = Matrix4.Identity; } else { tags[iSubSet] = Matrix4.Invert(anim.Frames[0].JointArray[bindings[iSubSet]]) * animatedJoints[bindings[iSubSet]]; } if (subSets[iSubSet] != null) { PositionStream posStream = (PositionStream)subSets[iSubSet].VertexUnit[typeof(PositionStream), 0]; Skinning.PreBind(animatedJoints, animatedJoints, skeleton.InvertedBindingPose); Skinning.SoftSkin(posStream, source[iSubSet], boneIndicesStream[iSubSet], boneWeightsStream[iSubSet], animatedJoints, false); posStream.Upload(); } } }
/// <summary> /// Calculates the face normals for the current subSet in object space. /// </summary> /// <returns>The face normals for the current subSet.</returns> public unsafe Vector3[] CalcFaceNormals() { Vector3[] faceNormals = new Vector3[this.PrimitiveCount]; PositionStream positionStream = (PositionStream)vertexUnit[typeof(PositionStream)]; Vector3[] positionStreamData = (Vector3[])positionStream.Data; if (indexStream.Type == typeof(ushort)) { ushort[] indexStreamData = (ushort[])indexStream.Data; for (int i = 0, j = 0; i < this.primitiveCount; i++) { Vector3 v0 = positionStreamData[indexStreamData[j++]]; Vector3 v1 = positionStreamData[indexStreamData[j++]]; Vector3 v2 = positionStreamData[indexStreamData[j++]]; faceNormals[i] = Vector3.Cross(v2 - v0, v1 - v0);//Vector3.CrossUnit( v2 - v0, v1 - v0); } return(faceNormals); } else { int[] indexStreamData = (int[])indexStream.Data; for (int i = 0, j = 0; i < this.primitiveCount; i++) { Vector3 v0 = positionStreamData[indexStreamData[j++]]; Vector3 v1 = positionStreamData[indexStreamData[j++]]; Vector3 v2 = positionStreamData[indexStreamData[j++]]; faceNormals[i] = Vector3.Cross(v2 - v0, v1 - v0);//Vector3.CrossUnit( v2 - v0, v1 - v0); } return(faceNormals); } }
/// <summary> /// Blends two meshes. /// </summary> /// <param name="fromIndex">The index of the mesh to blend from.</param> /// <param name="toIndex">The index of the mesh to blend to.</param> /// <param name="factor">The blend factor.</param> private void Blend(int fromIndex, int toIndex, float factor) { CreateMesh(); if (fromIndex == toIndex || factor < float.Epsilon) { Fill(fromIndex); } else if (factor >= 1.0f - float.Epsilon) { Fill(toIndex); } else { for (int i = 0; i < tempMesh.SubSets.Count; i++) { SubSet ssTarget = (SubSet)tempMesh.SubSets[i]; PositionStream psTarget = (PositionStream)ssTarget.VertexUnit[typeof(PositionStream)]; SubSet ssSourceA = (SubSet)meshes[fromIndex].SubSets[i]; PositionStream psSourceA = (PositionStream)ssSourceA.VertexUnit[typeof(PositionStream)]; SubSet ssSourceB = (SubSet)meshes[toIndex].SubSets[i]; PositionStream psSourceB = (PositionStream)ssSourceB.VertexUnit[typeof(PositionStream)]; for (int l = 0; l < psTarget.Size; l++) { psTarget[l] = Vector3.Lerp(psSourceA[l], psSourceB[l], factor); } psTarget.Upload(); } } }
public override int Read(byte[] buffer, int offset, int count) { int num = this.stream.Read(buffer, offset, count); PositionStream bytesRead = this; bytesRead.BytesRead = bytesRead.BytesRead + num; return(num); }
public override int ReadByte() { int num = this.stream.ReadByte(); PositionStream bytesRead = this; bytesRead.BytesRead = bytesRead.BytesRead + 1; return(num); }
public Edge[] CalcEdges() { // The stream containing the positions PositionStream positionStream = (PositionStream)vertexUnit[typeof(PositionStream)]; int[] indexMapping = new int[positionStream.Size]; Hashtable positions = new Hashtable( ); // Find equal vertices but with different index (may be different because of other texture coordinates ... for (int i = 0; i < positionStream.Size; i++) { Vector3 pos = positionStream[i]; if (positions.Contains(pos)) { indexMapping[i] = (int)positions[pos]; } else { positions.Add(pos, i); indexMapping[i] = i; } } Hashtable edges = new Hashtable(); for (int i = 0; i < indexStream.Size / 3; i++) { int index0 = indexMapping[indexStream[i * 3]]; int index1 = indexMapping[indexStream[i * 3 + 1]]; int index2 = indexMapping[indexStream[i * 3 + 2]]; AddEdge(edges, index0, index1, i); AddEdge(edges, index1, index2, i); AddEdge(edges, index2, index0, i); } int oneSided = 0; foreach (Edge e in edges.Values) { if (e.FaceB == -1 || e.FaceA == -1) { oneSided++; } } Edge[] retEdges = new Edge[edges.Count - oneSided]; int l = 0; foreach (Edge e in edges.Values) { if (e.FaceB != -1 && e.FaceA != -1) { retEdges[l++] = e; } } return(retEdges); }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- /// <summary> /// Generates a heightmap from a Bitmap. /// </summary> /// <param name="bmp">The bitmap to use.</param> public Mesh Generate(Bitmap bmp) { VertexUnit vertexUnit = new VertexUnit(VertexFormat.PositionTexture, bmp.Width * bmp.Height); PositionStream positionStream = (PositionStream)vertexUnit[typeof(PositionStream)]; TextureStream textureStream = (TextureStream)vertexUnit[typeof(TextureStream)]; BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); byte[] data = new byte[bitmapData.Stride * bitmapData.Height]; System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, data, 0, data.Length); int quadsX = bmp.Width - 1; int quadsY = bmp.Height - 1; Vector3 scale = new Vector3(0.1f, 0.02f, 0.1f); //Vector3 scale = new Vector3(5.0f, 0.1f, 5.0f); for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { int byteOffset = x * 4 + y * bitmapData.Stride; byte b = data[byteOffset]; byte g = data[byteOffset + 1]; byte r = data[byteOffset + 2]; byte a = data[byteOffset + 3]; Vector3 vec = Vector3.Scale(new Vector3(x - quadsX * 0.5f, r, -y + quadsY * 0.5f), scale); positionStream[x + y * bmp.Width] = vec; Vector2 texVec = new Vector2((float)x / quadsX, (float)y / quadsY); textureStream[x + y * bmp.Width] = texVec; } } bmp.UnlockBits(bitmapData); IndexStream indexStream = IndexStream.Create(quadsX * quadsY * 6, (quadsX + 1) * (quadsY + 1)); int offset = 0; for (int y = 0; y < quadsY; y++) { for (int x = 0; x < quadsX; x++) { indexStream[offset] = (x + y * bmp.Width); indexStream[offset + 1] = (x + 1 + y * bmp.Width); indexStream[offset + 2] = (x + (y + 1) * bmp.Width); indexStream[offset + 3] = (x + 1 + y * bmp.Width); indexStream[offset + 4] = (x + 1 + (y + 1) * bmp.Width); indexStream[offset + 5] = (x + (y + 1) * bmp.Width); offset += 6; } } Mesh mesh = new Mesh(); mesh.SubSets.Add(new SubSet(vertexUnit, indexStream)); return(mesh); }
private void SetSubSet(SubSet subSet, int i) { if (subSet.VertexUnit.Format.Contains(Semantic.BoneIndices)) { PositionStream posStream = (PositionStream)subSet.VertexUnit[typeof(PositionStream)]; boneIndicesStream[i] = (IBoneIndicesStream)subSet.VertexUnit[typeof(IBoneIndicesStream)]; boneWeightsStream[i] = (IBoneWeightsStream)subSet.VertexUnit[typeof(IBoneWeightsStream)]; source[i] = (Vector3[])posStream.Data.Clone(); subSets[i] = subSet; } }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- /// <summary> /// Updates the particle system. /// </summary> /// <param name="deltaTime">The time since the last update.</param> public override void Update(float deltaTime) { base.Update(deltaTime); Matrix4 m = Device.Instance.Transformations.View; Vector3 right = m.RightVector; Vector3 up = m.UpVector; // update streams PositionStream posStream = (PositionStream)vertexUnit[typeof(PositionStream)]; ColorStream colorStream = (ColorStream)vertexUnit[typeof(ColorStream)]; TextureStream textureStream = (TextureStream)vertexUnit[typeof(TextureStream)]; // Update all particles for (int i = 0; i < particles.Count; i++) { int offset = i * 4; IParticle particle = particles[i] as IParticle; IParticle3d particle3d = particles[i] as IParticle3d; if (particle3d != null) { Vector3 position = particle3d.Position; posStream[offset] = position - particle.Size.X * right + particle.Size.Y * up; posStream[offset + 1] = position + particle.Size.X * right + particle.Size.Y * up; posStream[offset + 2] = position + particle.Size.X * right - particle.Size.Y * up; posStream[offset + 3] = position - particle.Size.X * right - particle.Size.Y * up; } IParticleColor particleColor = particles[i] as IParticleColor; if (particleColor != null) { colorStream[offset] = particleColor.Color; colorStream[offset + 1] = particleColor.Color; colorStream[offset + 2] = particleColor.Color; colorStream[offset + 3] = particleColor.Color; } IParticleIndex particleIndex = particles[i] as IParticleIndex; System.Drawing.RectangleF tc; if (particleIndex == null || subTextures == null) { tc = (Texture as ITexture2d).TextureCoordinates; } else { tc = subTextures[(int)particleIndex.TextureIndex % subTextures.Length].TextureCoordinates; } textureStream[offset] = new Vector2(tc.Left, tc.Top); textureStream[offset + 1] = new Vector2(tc.Right, tc.Top); textureStream[offset + 2] = new Vector2(tc.Right, tc.Bottom); textureStream[offset + 3] = new Vector2(tc.Left, tc.Bottom); } posStream.Upload(); colorStream.Upload(); textureStream.Upload(); }
/// <summary> /// Calculates a the ShadowVolume for a certain lightPosition. /// </summary> /// <param name="light">The light that is used for casting the ShadowVolume.</param> /// <param name="world">The object to world space matrix.</param> /// <param name="recalcFaceNormals">Recalculates the face normals. This is just necessary if the vertices /// of the mesh are manipulated by the CPU like for SoftwareSkinning.</param> /// <returns>The ShadowVolume in form of an Mesh.</returns> public Mesh Calculate(Light light, Matrix4 world, bool recalcFaceNormals) { // Init variables int j = 0; // Calculate the object space light vector this.world = world; Vector4 osLight = light.Vector4 * Matrix4.Invert(world); // calc the method to use if (method == StencilMethod.Automatic) { currentMethod = CalcMethod(light, world); } else { currentMethod = method; } SetTechnique(currentMethod); // for all subsets of the mesh add the silohuette for (int iSubSet = 0; iSubSet < mesh.SubSets.Count; iSubSet++) { SubSet subset = mesh.SubSets[iSubSet]; SubSet shadow = shadowVolume.SubSets[iSubSet]; // get indices and positions PositionStream positionStream = (PositionStream)subset.VertexUnit[typeof(PositionStream)]; // recalc face normals if (recalcFaceNormals) { faceNormals[iSubSet] = subset.CalcFaceNormals(); } shadow.IndexBufferStart = j; CalcVisibilityInfo(ref j, iSubSet, osLight); if (indexStream.ElementSize == 2) { AddShadowVolume16(ref j, iSubSet, light, positionStream.Size / 2); } else { AddShadowVolume32(ref j, iSubSet, light, positionStream.Size / 2); } shadow.PrimitiveCount = (j - shadow.IndexBufferStart) / 3; } indexStream.Upload(); return(shadowVolume); }
/// <summary> /// Fills the temporary mesh with the mesh at a certain index. /// </summary> /// <param name="index">Index of source mesh.</param> /// <returns>The temporary mesh.</returns> private void Fill(int index) { CreateMesh(); for (int i = 0; i < tempMesh.SubSets.Count; i++) { SubSet ssTarget = (SubSet)tempMesh.SubSets[i]; PositionStream psTarget = (PositionStream)ssTarget.VertexUnit[typeof(PositionStream)]; SubSet ssSource = (SubSet)meshes[index].SubSets[i]; PositionStream psSource = (PositionStream)ssSource.VertexUnit[typeof(PositionStream)]; Array.Copy(psSource.Data, 0, psTarget.Data, 0, psTarget.Size); psTarget.Upload(); } }
private int read(PositionStream stream, Packet p) { if (stopped) { return(0); } p.Session = session; p.Reliable = true; int ret = Packet.DeserializeLengthDelimited(stream, stream.BinaryReader, p); p.Reliable = p.Reliable.GetValueOrDefault(true); return(ret); }
public void SkipKey() { var version2before = MyMessageV2.TestInstance(); //Write var buffer = MyMessageV2.SerializeToBytes(version2before); //Read by older version, lots of values will be skipped var noseek = new NonSeekableMemoryStream(buffer); var ps = new PositionStream(noseek); var version1 = MyMessageV1NoPreserve.Deserialize(ps); Assert.AreEqual(version2before.FieldA, version1.FieldA); }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- /// <summary> /// Updates the particle system. /// </summary> /// <param name="deltaTime">The time since the last update.</param> public override void Update(float deltaTime) { UpdateAge(deltaTime); // delete dead particles FixedRoundBuffer buffer = particles as FixedRoundBuffer; while (buffer.Count > 0 && !(buffer[0] as IParticle).IsAlive) { buffer.RemoveFirst(); } UpdateParticles(deltaTime); EmitParticles(deltaTime); ITexture2d texture = Texture; if (particles.Count >= 2) { // update streams PositionStream posStream = (PositionStream)vertexUnit[typeof(PositionStream)]; ColorStream colorStream = (ColorStream)vertexUnit[typeof(ColorStream)]; TextureStream textureStream = (TextureStream)vertexUnit[typeof(TextureStream)]; // Update all particles for (int i = 0; i < particles.Count; i++) { int offset = i * 2; IParticle particle = particles[i] as IParticle; IParticle3d particle3d = particles[i] as IParticle3d; if (particle3d != null) { Vector3 position = particle3d.Position; posStream[offset] = position + particle.Size.X * (particle as IParticleOrientation).Orientation; posStream[offset + 1] = position - particle.Size.X * (particle as IParticleOrientation).Orientation; } IParticleColor particleColor = particles[i] as IParticleColor; if (particleColor != null) { colorStream[offset] = particleColor.Color; colorStream[offset + 1] = particleColor.Color; } float tx = texture.TextureCoordinates.Left + texture.TextureCoordinates.Width * particle.Age / particle.LifeTime; textureStream[offset] = new Vector2(tx, texture.TextureCoordinates.Top); textureStream[offset + 1] = new Vector2(tx, texture.TextureCoordinates.Bottom); } posStream.Upload(); colorStream.Upload(); textureStream.Upload(); } }
private void CalcVisibilityInfo(ref int j, int iSubSet, Vector4 osLight) { IndexStream iStream = mesh.SubSets[iSubSet].IndexStream; PositionStream positionStream = (PositionStream)mesh.SubSets[iSubSet].VertexUnit[typeof(PositionStream)]; // sad but true the following variables are for optimization bool[] currentBackFace = backface[iSubSet]; Vector3[] currentFaceNormals = faceNormals[iSubSet]; Vector3 osLight3 = osLight.Vector3; float w = osLight.W; int size = iStream.Size / 3; Vector3[] posStreamData = (Vector3[])positionStream.Data; ushort[] iStreamDataShort = iStream.Data as ushort[]; int[] iStreamDataInt = iStream.Data as int[]; // fill backface array with visibility information for (int i = 0; i < size; i++) { int index0 = iStream[i * 3]; Vector3 v0 = posStreamData[index0]; Vector3 lightDirection = v0 * w - osLight3; bool back = currentFaceNormals[i] * lightDirection > 0.0f; currentBackFace[i] = back; // for the zFail method - add the front and back caps if (currentMethod == StencilMethod.ZFail) { int index1 = iStream[i * 3 + 1]; int index2 = iStream[i * 3 + 2]; if (!back) { ResizeIndexStream(indexStream, j + 3); indexStream[j] = (index0 + positionStream.Size / 2); indexStream[j + 2] = (index1 + positionStream.Size / 2); indexStream[j + 1] = (index2 + positionStream.Size / 2); j += 3; ResizeIndexStream(indexStream, j + 3); indexStream[j] = index0; indexStream[j + 1] = index1; indexStream[j + 2] = index2; j += 3; } } } }
void SoftSkin(Matrix4[] preBound) { // Apply skinning on all subSets for (int iSubSet = 0; iSubSet < data.Length; iSubSet++) { SubSetData ssData = data[iSubSet]; if (ssData != null) { VertexUnit vu = mesh.SubSets[iSubSet].VertexUnit; PositionStream ps = (PositionStream)vu[typeof(PositionStream)]; IBoneIndicesStream bis = (IBoneIndicesStream)vu[typeof(IBoneIndicesStream)]; IBoneWeightsStream bws = (IBoneWeightsStream)vu[typeof(IBoneWeightsStream)]; // currently just the position stream is skinned! Skinning.SoftSkin(ps, ssData.Position, bis, bws, preBound, Shadowed); ps.Upload(); } } }
/// <summary> /// Calculates the face normals for the current subSet in object space. /// </summary> /// <returns>The face normals for the current subSet.</returns> public Vector3[] CalcFaceNormalsOld() { Vector3[] faceNormals = new Vector3[this.PrimitiveCount]; PositionStream positionStream = (PositionStream)vertexUnit[typeof(PositionStream)]; for (int i = 0; i < this.PrimitiveCount; i++) { int index0 = indexStream[i * 3]; int index1 = indexStream[i * 3 + 1]; int index2 = indexStream[i * 3 + 2]; Vector3 v0 = positionStream[index0]; Vector3 v1 = positionStream[index1]; Vector3 v2 = positionStream[index2]; faceNormals[i] = Vector3.Unit(Vector3.Cross(v2 - v0, v1 - v0)); } return(faceNormals); }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Properties //--------------------------------------------------------------- //--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Initialisation //--------------------------------------------------------------- /// <summary> /// Creates a sky box entity. /// </summary> /// <param name="size">Size of sky box.</param> /// <param name="format"><see cref="VertexFormat"/> to use for skybox.</param> public SkyBoxEntity(Vector3 size, VertexFormat format) { // create streams VertexUnit vertexUnit = new VertexUnit(format, 8); PositionStream position = (PositionStream)vertexUnit[typeof(PositionStream)]; //TextureStream texture = (TextureStream)vertexUnit[ typeof(TextureStream) ]; IndexStream index = new IndexStream16(24); // fill position data position[0] = new Vector3(-size.X, -size.Y, size.Z); position[1] = new Vector3(size.X, -size.Y, size.Z); position[2] = new Vector3(size.X, -size.Y, -size.Z); position[3] = new Vector3(-size.X, -size.Y, -size.Z); position[4] = new Vector3(-size.X, size.Y, size.Z); position[5] = new Vector3(size.X, size.Y, size.Z); position[6] = new Vector3(size.X, size.Y, -size.Z); position[7] = new Vector3(-size.X, size.Y, -size.Z); subSet = new SubSet(vertexUnit, index); }
//--------------------------------------------------------------- #endregion //--------------------------------------------------------------- //--------------------------------------------------------------- #region Methods //--------------------------------------------------------------- private void Bind() { BinormalStream.Bind(); BoneIndicesStream.Bind(); BoneWeightsStream.Bind(); SoftwareBoneIndicesStream.Bind(); SoftwareBoneWeightsStream.Bind(); ColorStream.Bind(); CompressedNormalStream.Bind(); FloatStream.Bind(); IndexStream16.Bind(); IndexStream32.Bind(); IntStream.Bind(); NormalStream.Bind(); PositionStream.Bind(); PositionStream2.Bind(); PositionStream4.Bind(); TangentStream.Bind(); TextureStream.Bind(); }
/// <summary> /// Loads the model. /// </summary> /// <param name="stream">Stream to load model from.</param> /// <returns>The loaded model.</returns> public Model LoadModel(Stream stream) { BlendMesh mesh; // get header and check if it is ok MD2_Header header = (MD2_Header)RawSerializer.Deserialize(stream, typeof(MD2_Header)); if (header.Ident != 844121161 || header.Version != 8) { return(null); } // Load skins MD2_Skin[] skinNames = (MD2_Skin[])RawSerializer.DeserializeArray(stream, typeof(MD2_Skin), header.NumSkins); // Load texture coordinates MD2_TextureCoordinate[] textureCoordinates = (MD2_TextureCoordinate[])RawSerializer.DeserializeArray(stream, typeof(MD2_TextureCoordinate), header.NumTextureCoordinates); // Load triangless MD2_Triangle[] triangles = (MD2_Triangle[])RawSerializer.DeserializeArray(stream, typeof(MD2_Triangle), header.NumTris); IndexStream indexStream = new IndexStream16(triangles.Length); for (int i = 0; i < triangles.Length; i++) { // indexStream[i] = triangles[i].VertexIndex[j; } mesh = new BlendMesh(header.NumFrames); // Load frames for (int i = 0; i < header.NumFrames; i++) { MD2_Frame frame = (MD2_Frame)RawSerializer.Deserialize(stream, typeof(MD2_Frame)); MD2_Vertex[] vertices = (MD2_Vertex[])RawSerializer.DeserializeArray(stream, typeof(MD2_Vertex), header.NumVertices); VertexUnit vu = new VertexUnit(VertexFormat.Position, vertices.Length); PositionStream ps = (PositionStream)vu[typeof(Purple.Graphics.VertexStreams.PositionStream)]; mesh.Meshes[i] = new Mesh(new SubSet(vu, indexStream)); } return(new Model(mesh, null)); }
private SubSetData CreateSubSetData(SubSet subSet) { VertexUnit vu = subSet.VertexUnit; if (!vu.Format.Contains(Semantic.BoneIndices) || !vu.Format.Contains(Semantic.BoneIndices) || !vu.Format.Contains(Semantic.Position)) { return(null); } SubSetData ssData = new SubSetData(); PositionStream posStream = (PositionStream)vu[typeof(PositionStream)]; ssData.Position = (Vector3[])posStream.Data.Clone(); if (vu.Format.Contains(typeof(NormalStream))) { NormalStream normalStream = (NormalStream)vu[typeof(NormalStream)]; ssData.Normal = (Vector3[])normalStream.Data.Clone(); } return(ssData); }
/// <summary> /// Import a mesh from a stream. /// </summary> /// <param name="stream">Stream containing mesh data.</param> public void Import(Stream stream) { Profiler.Instance.Begin("Import binary mesh"); // Header BinaryReader reader = new BinaryReader(stream); if (ReadString(reader) != "mesh" || ReadString(reader) != "v0.3") { throw new NotSupportedException("Can't load mesh, file not supported!"); } // Joints int jointNum = ReadInt(reader); Joint[] joints = new Joint[jointNum]; Matrix4[] jointArray = new Matrix4[jointNum]; Hashtable jointTable = new Hashtable(joints.Length); for (int i = 0; i < joints.Length; i++) { string name = ReadString(reader); string parent = ReadString(reader); reader.Read(matrixBytes, 0, matrixBytes.Length); Matrix4 m = Matrix4.From(matrixBytes); Joint parentJoint = null; if (parent != null && jointTable.Contains(parent)) { parentJoint = (Joint)jointTable[parent]; } joints[i] = new Joint(name, i, parentJoint); jointArray[i] = m; jointTable[name] = joints[i]; } skeleton = new Skeleton(jointArray, joints); // SubSet int subSetNum = ReadInt(reader); for (int i = 0; i < subSetNum; i++) { ArrayList streams = new ArrayList(10); // Header if (ReadString(reader) != "subset") { throw new NotSupportedException("Error on loading subSet!"); } string name = ReadString(reader); string parentJoint = ReadString(reader); int attributeCount = ReadInt(reader); StringDictionary attributes = new StringDictionary(); for (int t = 0; t < attributeCount; t++) { attributes.Add(ReadString(reader), ReadString(reader)); } // IndexStream // Todo Replace ushort.MaxValue with size of vertex unit IndexStream indexStream = IndexStream.Create(ReadInt(reader), ushort.MaxValue); byte[] indexBuffer = new byte[indexStream.Size * 4]; reader.Read(indexBuffer, 0, indexStream.Size * 4); for (int t = 0; t < indexStream.Size; t++) { indexStream[t] = BitConverter.ToInt32(indexBuffer, t * 4); } int vertexSize = ReadInt(reader); PositionStream posStream = new PositionStream(vertexSize); streams.Add(posStream); byte[] vertexBuffer = new byte[vertexSize * 12]; reader.Read(vertexBuffer, 0, vertexSize * 12); for (int t = 0; t < vertexSize; t++) { posStream[t] = Vector3.From(vertexBuffer, 12 * t); } NormalStream normalStream = new NormalStream(vertexSize); streams.Add(normalStream); reader.Read(vertexBuffer, 0, vertexSize * 12); for (int t = 0; t < vertexSize; t++) { normalStream[t] = Vector3.From(vertexBuffer, t * 12); } ColorStream colorStream = new ColorStream(vertexSize); streams.Add(colorStream); reader.Read(vertexBuffer, 0, vertexSize * 12); for (int t = 0; t < vertexSize; t++) { int r = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, t * 12) * 255 + 0.5f), 0, 255); int g = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, 4 + t * 12) * 255 + 0.5f), 0, 255); int b = Math.Basic.Clamp((int)(System.BitConverter.ToSingle(vertexBuffer, 8 + t * 12) * 255 + 0.5f), 0, 255); colorStream[t] = System.Drawing.Color.FromArgb(r, g, b).ToArgb(); } TextureStream[] textureStreams = new TextureStream[ReadInt(reader)]; for (int t = 0; t < textureStreams.Length; t++) { TextureStream texStream = new TextureStream(vertexSize); streams.Add(texStream); reader.Read(vertexBuffer, 0, vertexSize * 8); for (int j = 0; j < vertexSize; j++) { texStream[j] = Vector2.From(vertexBuffer, j * 8); } textureStreams[t] = texStream; } IBoneIndicesStream boneStream = null; IBoneWeightsStream weightsStream = null; int weightNum = ReadInt(reader); if (weightNum != 0) { if (HardwareSkinning) { boneStream = new BoneIndicesStream(vertexSize); weightsStream = new BoneWeightsStream(vertexSize); } else { boneStream = new SoftwareBoneIndicesStream(vertexSize); weightsStream = new SoftwareBoneWeightsStream(vertexSize); } streams.Add(boneStream); streams.Add(weightsStream); ArrayList[] indicesList = new ArrayList[vertexSize]; ArrayList[] weightsList = new ArrayList[vertexSize]; for (int t = 0; t < vertexSize; t++) { indicesList[t] = new ArrayList(8); weightsList[t] = new ArrayList(8); } byte[] weightBuffer = new byte[weightNum * 12]; reader.Read(weightBuffer, 0, weightNum * 12); for (int t = 0; t < weightNum; t++) { int vertexIndex = BitConverter.ToInt32(weightBuffer, t * 12); int jointIndex = BitConverter.ToInt32(weightBuffer, 4 + t * 12); float weight = BitConverter.ToSingle(weightBuffer, 8 + t * 12); indicesList[vertexIndex].Add((byte)jointIndex); weightsList[vertexIndex].Add(weight); } for (int t = 0; t < vertexSize; t++) { boneStream.SetIndices(t, (byte[])indicesList[t].ToArray(typeof(byte))); weightsStream.SetWeights(t, (float[])weightsList[t].ToArray(typeof(float))); } } VertexUnit vertexUnit = new VertexUnit(streams); Mesh mesh = new Mesh(new SubSet(vertexUnit, indexStream)); if (model == null) { if (skeleton.Joints.Length != 0) { model = new Model(new SkinnedMesh(mesh, skeleton), skeleton); } else { model = new Model(mesh, skeleton); } } else { Joint attachTo = skeleton.RootJoint; if (parentJoint != "") { attachTo = (jointTable[parentJoint] as Joint); } model.AttachModel(new Model(mesh, skeleton), attachTo); } } reader.Close(); Profiler.Instance.End("Import binary mesh"); }
private Task OpenStream(Action <ISegmentMetadata> setMetadata, CancellationToken cancellationToken) { this.ThrowIfDisposed(); WebResponse webResponse = new WebResponse(); IRetry retry = this._retryManager.CreateRetry(2, 200, new Func <Exception, bool>(RetryPolicy.IsWebExceptionRetryable)); return(RetryExtensions.CallAsync(retry, (Func <Task>)(async() => { long?nullable1; long?nullable2; while (true) { if (this._startOffset.HasValue && this._endOffset.HasValue) { nullable1 = this._endOffset; nullable2 = this._startOffset; nullable1 = nullable1.HasValue & nullable2.HasValue ? new long?(nullable1.GetValueOrDefault() - nullable2.GetValueOrDefault()) : new long?(); long?nullable3; if (!nullable1.HasValue) { nullable2 = new long?(); nullable3 = nullable2; } else { nullable3 = new long?(nullable1.GetValueOrDefault() + 1L); } this._expectedBytes = nullable3; } else { this._expectedBytes = new long?(); } this._response = await this._webReader.GetWebStreamAsync(this._actualUrl ?? this._segment.Url, false, cancellationToken, this._segment.ParentUrl, this._startOffset, this._endOffset, webResponse).ConfigureAwait(false); if (!this._response.IsSuccessStatusCode) { HttpStatusCode statusCode = (HttpStatusCode)this._response.HttpStatusCode; if (HttpStatusCode.NotFound != statusCode && !RetryPolicy.IsRetryable(statusCode)) { this._response.EnsureSuccessStatusCode(); } bool canRetry = await retry.CanRetryAfterDelayAsync(cancellationToken).ConfigureAwait(false); if (!canRetry) { if ((Uri)null != this._actualUrl && this._actualUrl != this._segment.Url) { this._actualUrl = (Uri)null; } else { this._response.EnsureSuccessStatusCode(); } } this._response.Dispose(); this._response = (IWebStreamResponse)null; } else { break; } } this._actualUrl = this._response.ActualUrl; long?contentLength = this._response.ContentLength; if (!this._endOffset.HasValue) { nullable1 = contentLength; long?nullable3; if (!nullable1.HasValue) { nullable2 = new long?(); nullable3 = nullable2; } else { nullable3 = new long?(nullable1.GetValueOrDefault() - 1L); } this._endOffset = nullable3; } if (!this._expectedBytes.HasValue) { this._expectedBytes = contentLength; } SegmentReader segmentReader1 = this; ConfiguredTaskAwaitable <Stream> configuredTaskAwaitable = this._response.GetStreamAsync(cancellationToken).ConfigureAwait(false); PositionStream positionStream = new PositionStream(await configuredTaskAwaitable); segmentReader1._responseStream = (Stream)positionStream; Task <Stream> filterStreamTask = this._segment.CreateFilterAsync(this._responseStream, cancellationToken); if (null != filterStreamTask) { SegmentReader segmentReader2 = this; configuredTaskAwaitable = filterStreamTask.ConfigureAwait(false); Stream stream = await configuredTaskAwaitable; segmentReader2._readStream = stream; } else { this._readStream = this._responseStream; } ISegmentMetadata segmentMetadata = this._webMetadataFactory.CreateSegmentMetadata(webResponse, (ContentType)null); setMetadata(segmentMetadata); }), cancellationToken)); }
/// <summary> /// import a mesh from a stream /// </summary> /// <param name="stream">stream containing mesh data</param> public void Import(Stream stream) { model = null; skeleton = null; IndexStream indexStream = null; IVertexStream currentStream = null; ArrayList streams = new ArrayList(); StringDictionary attributes = new StringDictionary(); XmlTextReader reader = new XmlTextReader(stream); Matrix4[] jointArray = null; Joint[] joints = null; Hashtable jointTable = null; int index = 0; int currentJoint = 0; int vertexCount = 0; int binding = -1; ArrayList[] indicesList = null; ArrayList[] weightsList = null; while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.Name) { // <mesh> case "mesh": if (model != null) { throw new GraphicsException("Only one mesh allowed in mesh stream!"); } model = new Model(); break; // <subset> case "subset": string parentJoint = reader.GetAttribute("parentJoint"); if (parentJoint != null && parentJoint != "") { binding = (jointTable[parentJoint] as Joint).Index; } else { binding = -1; } break; // <attributes> case "attributes": break; case "attribute": // todo !!! attributes.Add(reader.GetAttribute("name"), reader.GetAttribute("value")); break; //<indexStream> case "indexStream": { index = 0; int size = int.Parse(reader.GetAttribute("size"), culture); indexStream = new IndexStream16(size); } break; //<triangle> case "triangle": { int a = int.Parse(reader.GetAttribute("a"), culture); int b = int.Parse(reader.GetAttribute("b"), culture); int c = int.Parse(reader.GetAttribute("c"), culture); indexStream[index++] = a; indexStream[index++] = b; indexStream[index++] = c; } break; //<positionStream> case "positionStream": { index = 0; vertexCount = int.Parse(reader.GetAttribute("size"), culture); currentStream = new PositionStream(vertexCount); streams.Add(currentStream); } break; //<vector3> case "vector3": { float x = float.Parse(reader.GetAttribute("x"), culture); float y = float.Parse(reader.GetAttribute("y"), culture); float z = float.Parse(reader.GetAttribute("z"), culture); (currentStream as PositionStream)[index++] = new Vector3(x, y, z); } break; //<normalStream> case "normalStream": { index = 0; int size = int.Parse(reader.GetAttribute("size"), culture); currentStream = new NormalStream(size); streams.Add(currentStream); } break; //<colorStream> case "colorStream": { index = 0; int size = int.Parse(reader.GetAttribute("size"), culture); currentStream = new ColorStream(size); streams.Add(currentStream); } break; //<color> case "color": { int r = (int)((float.Parse(reader.GetAttribute("r"), culture)) * 255.0f + 0.5f); int g = (int)((float.Parse(reader.GetAttribute("g"), culture)) * 255.0f + 0.5f); int b = (int)((float.Parse(reader.GetAttribute("b"), culture)) * 255.0f + 0.5f); (currentStream as ColorStream)[index++] = System.Drawing.Color.FromArgb(r, g, b).ToArgb(); } break; //<textureStream> case "textureStream": { index = 0; int size = int.Parse(reader.GetAttribute("size"), culture); currentStream = new TextureStream(size); streams.Add(currentStream); } break; //<vector2> case "vector2": { float x = float.Parse(reader.GetAttribute("x"), culture); float y = float.Parse(reader.GetAttribute("y"), culture); (currentStream as TextureStream)[index++] = new Vector2(x, y); } break; case "joints": { int size = int.Parse(reader.GetAttribute("size"), culture); jointArray = new Matrix4[size]; joints = new Joint[size]; jointTable = new Hashtable(); currentJoint = 0; } break; case "joint": { string jointName = reader.GetAttribute("name"); string parentName = reader.GetAttribute("parent"); Matrix4 m = new Matrix4(float.Parse(reader.GetAttribute("a1"), culture), float.Parse(reader.GetAttribute("a2"), culture), float.Parse(reader.GetAttribute("a3"), culture), float.Parse(reader.GetAttribute("a4"), culture), float.Parse(reader.GetAttribute("b1"), culture), float.Parse(reader.GetAttribute("b2"), culture), float.Parse(reader.GetAttribute("b3"), culture), float.Parse(reader.GetAttribute("b4"), culture), float.Parse(reader.GetAttribute("c1"), culture), float.Parse(reader.GetAttribute("c2"), culture), float.Parse(reader.GetAttribute("c3"), culture), float.Parse(reader.GetAttribute("c4"), culture), float.Parse(reader.GetAttribute("d1"), culture), float.Parse(reader.GetAttribute("d2"), culture), float.Parse(reader.GetAttribute("d3"), culture), float.Parse(reader.GetAttribute("d4"), culture)); jointArray[currentJoint] = m; //new Joint(jointName, m); Joint parent = null; if (parentName != null && jointTable.Contains(parentName)) { parent = (Joint)jointTable[parentName]; } joints[currentJoint] = new Joint(jointName, currentJoint, parent); jointTable[jointName] = joints[currentJoint]; currentJoint++; } break; case "weights": { index = 0; //vertexCount = int.Parse(reader.GetAttribute("size"), culture); indicesList = new ArrayList[vertexCount]; weightsList = new ArrayList[vertexCount]; for (int i = 0; i < vertexCount; i++) { indicesList[i] = new ArrayList(8); weightsList[i] = new ArrayList(8); } } break; case "weight": { int vertexIndex = int.Parse(reader.GetAttribute("vertexIndex")); byte jointIndex = byte.Parse(reader.GetAttribute("jointIndex")); float value = float.Parse(reader.GetAttribute("weight"), culture); indicesList[vertexIndex].Add(jointIndex); weightsList[vertexIndex].Add(value); } break; } } if (reader.NodeType == XmlNodeType.EndElement) { if (reader.Name.Equals("weights")) { IBoneIndicesStream bis = null; IBoneWeightsStream bws = null; if (HardwareSkinning) { bis = new BoneIndicesStream(vertexCount); bws = new BoneWeightsStream(vertexCount); } else { bis = new SoftwareBoneIndicesStream(vertexCount); bws = new SoftwareBoneWeightsStream(vertexCount); } for (int i = 0; i < vertexCount; i++) { bis.SetIndices(i, (byte[])indicesList[i].ToArray(typeof(byte))); bws.SetWeights(i, (float[])weightsList[i].ToArray(typeof(float))); } streams.Add(bis); streams.Add(bws); } else if (reader.Name.Equals("subset")) { VertexUnit vertexUnit = new VertexUnit(streams); if (binding == -1) { model.Mesh = new Mesh(new SubSet(vertexUnit, indexStream)); } else { model.AttachModel(new Model(new Mesh(new SubSet(vertexUnit, indexStream)), null), binding); } streams.Clear(); } } } ; reader.Close(); if (jointArray != null && joints != null) { skeleton = new Skeleton(jointArray, joints); } model.Skeleton = skeleton; }
private void ConnectCallback(IAsyncResult result) #endif { //We can get here is the connection fails and the monotor thread // calls close. We should just do nothing at this point #if __WINDOWS__ if (client == null || !connected) { return; } if (stopped) { if (connected) { client.Dispose(); } return; } #else if ((client != null && !client.Connected)) { return; } if (stopped) { if (client.Connected) { client.Close(); } return; } clientStream = GSTlsClient.WrapStream(client.GetStream(), remotehost); #endif //Each time a tcp connection is established we re-authenticate try { LoginCommand loginCmd = new LoginCommand(session.ConnectToken); Send(loginCmd); Packet p = PooledObjects.PacketPool.Pop(); PositionStream rss = PooledObjects.PositionStreamPool.Pop(); #if __WINDOWS__ rss.Wrap(client.InputStream.AsStreamForRead()); #else rss.Wrap(clientStream); #endif int bytesRead = 0; while ((bytesRead = read(rss, p)) != 0) { OnPacketReceived(p, bytesRead); PooledObjects.PacketPool.Push(p); p = PooledObjects.PacketPool.Pop(); } PooledObjects.PacketPool.Push(p); PooledObjects.PositionStreamPool.Push(rss); } #if __WINDOWS__ /*catch (AggregateException exception) * { * foreach (Exception ex in exception.InnerExceptions) * { * System.Diagnostics.Debug.WriteLine(ex); * } * }*/ #endif catch (Exception e) { if (session != null && !stopped) { session.ConnectState = GameSparksRT.ConnectState.Disconnected; session.Log("ReliableConnection", GameSparksRT.LogLevel.DEBUG, e.Message); try{ session.OnReady(false); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); } } } }
private MD3Part LoadMD3(string part) { using (Stream stream = fileSystem.Open(path + part + ".md3")) { // get header and check if it is ok MD3_Header header = (MD3_Header)RawSerializer.Deserialize(stream, typeof(MD3_Header)); if (header.Id != 860898377 || header.Version != 15) { return(null); } // load bone frames MD3_Frame[] frames = (MD3_Frame[])RawSerializer.DeserializeArray(stream, typeof(MD3_Frame), header.NumFrames); // load tags SortedList links = GetLinks((MD3_Tag[])RawSerializer.DeserializeArray(stream, typeof(MD3_Tag), header.NumTags * header.NumFrames)); long meshOffset = stream.Position; // one mesh for every frame BlendMesh mesh = new BlendMesh(header.NumFrames); // load meshes for (int iMesh = 0; iMesh < header.NumMeshes; iMesh++) { stream.Position = meshOffset; MD3_MeshHeader meshHeader = (MD3_MeshHeader)RawSerializer.Deserialize(stream, typeof(MD3_MeshHeader)); MD3_Skin[] skins = (MD3_Skin[])RawSerializer.DeserializeArray(stream, typeof(MD3_Skin), meshHeader.NumSkins); stream.Position = meshOffset + meshHeader.TriangleOffset; MD3_Triangle[] triangles = (MD3_Triangle[])RawSerializer.DeserializeArray(stream, typeof(MD3_Triangle), meshHeader.NumTriangles); stream.Position = meshOffset + meshHeader.TexCoordOffset; MD3_TexCoord[] texCoords = (MD3_TexCoord[])RawSerializer.DeserializeArray(stream, typeof(MD3_TexCoord), meshHeader.NumVertices); stream.Position = meshOffset + meshHeader.VertexOffset; MD3_Vertex[] vertices = (MD3_Vertex[])RawSerializer.DeserializeArray(stream, typeof(MD3_Vertex), meshHeader.NumFrames * meshHeader.NumVertices); float scale = 64.0f; string name = StringHelper.Convert(meshHeader.Name); ITexture tx = (ITexture)textures[name]; Triangle[] tris = new Triangle[triangles.Length]; for (int i = 0; i < triangles.Length; i++) { tris[i].A = (triangles[i]).A; tris[i].B = (triangles[i]).B; tris[i].C = (triangles[i]).C; } IndexStream indexStream = IndexStream16.FromTriangles(tris); int vertCount = meshHeader.NumVertices; // *meshHeader.NumFrames; for (int iFrame = 0; iFrame < meshHeader.NumFrames; iFrame++) { VertexUnit vertexUnit = new VertexUnit(VertexFormat.PositionNormalTexture, vertCount); PositionStream pos = (PositionStream)vertexUnit[typeof(PositionStream)]; NormalStream normal = (NormalStream)vertexUnit[typeof(NormalStream)]; TextureStream tex = (TextureStream)vertexUnit[typeof(TextureStream)]; for (int i = 0; i < vertCount; i++) { int vertIndex = iFrame * meshHeader.NumVertices + i; pos[i] = new Vector3(vertices[vertIndex].X / scale, vertices[vertIndex].Z / scale, -vertices[vertIndex].Y / scale); int texIndex = i % meshHeader.NumVertices; tex[i] = new Vector2(texCoords[texIndex].U, texCoords[texIndex].V); //Normal vector int compressedNormal = ((MD3_Vertex)vertices[vertIndex]).Normal; float lng = (compressedNormal & 0xFF) * Math.Basic.PI / 128; float lat = ((compressedNormal >> 8) & 0xFF) * Math.Basic.PI / 128; normal[i] = new Vector3(Math.Trigonometry.Cos(lat) * Math.Trigonometry.Sin(lng), Math.Trigonometry.Cos(lng), -Math.Trigonometry.Sin(lat) * Math.Trigonometry.Sin(lng)); } if (mesh.Meshes[iFrame] == null) { mesh.Meshes[iFrame] = new Mesh(); } mesh.Meshes[iFrame].SubSets.Add(new SubSet(vertexUnit, indexStream)); mesh.Meshes[iFrame].Textures.Add(new Textures("color", tx)); } // Increase the offset into the file meshOffset += meshHeader.MeshSize; } return(new MD3Part(mesh, links)); } }
/// <summary> /// loads a quake3 level from a stream /// </summary> /// <param name="stream">stream to load from</param> /// <returns>level as a mesh</returns> public Mesh Load(Stream stream) { Mesh mesh = new Mesh(); this.stream = stream; // get header and check if it is ok QuakeHeader header = (QuakeHeader)RawSerializer.Deserialize(stream, typeof(QuakeHeader)); if (header.ID != 1347633737 || header.Version != 0x2e) { return(null); } // get locations of lumps locations = RawSerializer.DeserializeArray(stream, typeof(LumpLocation), (int)QuakeLumps.LumpNumber); // get lumps IList quakeVertices = LoadLump(QuakeLumps.Vertices, typeof(QuakeVertex)); IList quakeFaces = LoadLump(QuakeLumps.Faces, typeof(QuakeFace)); IList quakeTextures = LoadLump(QuakeLumps.Textures, typeof(QuakeTexture)); IList quakeLightMaps = LoadLump(QuakeLumps.Lightmaps, typeof(QuakeLightMap)); // Load all texture images and put into array IList textures = LoadTextures(quakeTextures); // Load lightMaps, create texture and put into array IList lightMaps = LoadLightMaps(quakeLightMaps); // create list from vertices VertexUnit vertexUnit = new VertexUnit(VertexFormat.PositionTexture2, quakeVertices.Count); PositionStream pos = (PositionStream)vertexUnit[typeof(PositionStream)]; TextureStream texStream = (TextureStream)vertexUnit[typeof(TextureStream)]; TextureStream light = (TextureStream)vertexUnit[typeof(TextureStream), 1]; int i = 0; foreach (QuakeVertex v in quakeVertices) { pos[i] = new Math.Vector3(v.Position[0], v.Position[2], -v.Position[1]); texStream[i] = new Math.Vector2(v.TextureCoord[0], v.TextureCoord[1]); light[i] = new Math.Vector2(v.LightmapCoord[0], v.LightmapCoord[1]); i++; } // presort faces Array.Sort(((Array)quakeFaces)); // create mesh int oldLightMap = ((QuakeFace)quakeFaces[0]).LightmapID; int oldTexture = ((QuakeFace)quakeFaces[0]).TextureID; ArrayList indices = new ArrayList(); for (i = 0; i < quakeFaces.Count; ++i) { QuakeFace qf = (QuakeFace)quakeFaces[i]; if (qf.Type == 1) { if (qf.TextureID != oldTexture || qf.LightmapID != oldLightMap) { mesh.SubSets.Add(new SubSet(vertexUnit, IndexStream.Create(indices, vertexUnit.Size))); Textures texs = new Textures("color", (ITexture)textures[oldTexture]); if (oldLightMap == -1) { texs["lightMap"] = null; } else { texs["lightMap"] = (ITexture)lightMaps[oldLightMap]; } mesh.Textures.Add(texs); indices.Clear(); } // add indices => convert from fan to list for (int j = 2; j < qf.NumOfVerts; j++) { indices.Add(qf.VertexIndex); indices.Add(qf.VertexIndex + j - 1); indices.Add(qf.VertexIndex + j); } oldTexture = qf.TextureID; oldLightMap = qf.LightmapID; } } return(mesh); }
bool ReadMeshes() { Advance("nummeshes"); int meshNum = int.Parse(NextToken); mesh = new Mesh(); for (int i = 0; i < 1 /*meshNum*/; i++) { Advance("mesh"); // sanity check int num = int.Parse(NextToken); System.Diagnostics.Debug.Assert(num == i, "Invalid mesh num!"); // read mesh data - shader, verts Advance("shader"); string shaderPath = NextToken; FileInfo info = new FileInfo(shaderPath); string localPath = shaderPath.Insert(shaderPath.Length - info.Extension.Length, "_local"); string diffusePath = shaderPath.Insert(shaderPath.Length - info.Extension.Length, "_d"); Textures textures = new Textures(); ITexture texture = null; try { texture = TextureManager.Instance.Load(shaderPath); } catch { texture = TextureManager.Instance.Load(diffusePath); } ITexture normalMap = TextureManager.Instance.Load(localPath); textures["color"] = texture; textures["normal"] = normalMap; if (!ReadVertices()) { return(false); } if (!ReadTriangles()) { return(false); } if (!ReadWeights()) { return(false); } // let's test it VertexUnit vertexUnit = new VertexUnit(VertexFormat.PositionTexture2Tangent, vertices.Length); PositionStream positionStream = (PositionStream)vertexUnit[0]; TextureStream textureStream = (TextureStream)vertexUnit[1]; TextureStream normalStream = (TextureStream)vertexUnit[2]; for (int j = 0; j < vertices.Length; j++) { Vector3 pos = Vector3.Zero; MD5Vertex vertex = vertices[j]; for (int k = 0; k < vertex.WeightCount; k++) { MD5Weight weight = weights[vertex.WeightIndex + k]; MD5Bone bone = bones[weight.BoneIndex]; pos += weight.Vector * bone.Matrix * weight.BiasFactor; } positionStream[j] = pos; textureStream[j] = vertex.UV; normalStream[j] = vertex.UV; } // add tangent space stuff IGraphicsStream[] streams = Util.CalcTangentSpaceStreams(positionStream, textureStream, indexStream); Array.Copy(streams[0].Data, vertexUnit[3].Data, vertices.Length); Array.Copy(streams[1].Data, vertexUnit[4].Data, vertices.Length); Array.Copy(streams[2].Data, vertexUnit[5].Data, vertices.Length); //mesh.SubSets.Add( new SubSet(vertexUnit, indexStream, material)); } return(true); }