public void UpdateBuffer(BufferedGeometryData buffer, Vector3 viewPos, Matrix worldMat, IAtom[] atoms) { int stride = buffer.vBuffers[0].Stride; int objs = buffer.vBuffers[0].NumElements; GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); long pos = 0; foreach (IAtom atom in atoms) { // transform atom point to world-space Vector3 atomPos = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); Vector4 atomPosT = Vector3.Transform(atomPos, worldMat); // calc V to view pos Vector3 atomToView = new Vector3(atomPosT.X, atomPosT.Y, atomPosT.Z) - viewPos; atomToView.Normalize(); Vector3 atomNewPos = (atomToView * 0.3f) + atomPos; data.Seek(pos, SeekOrigin.Begin); data.Write(atomNewPos.X); data.Write(atomNewPos.Y); data.Write(atomNewPos.Z); pos += stride; } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int sizePos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "SIZEFLOAT") { sizePos = geomStream.FieldPositions[gf]; } break; } } } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(typeof(MetaBlobsEffect.PointVertex), objs.Count, device, Usage.None, VertexFormats.Position | VertexFormats.PointSize | VertexFormats.Diffuse, Pool.SystemMemory); /*new VertexBuffer(device, geomStream.Stride * objs.Count, * Usage.WriteOnly, geomStream.Format, Pool.SystemMemory);*/ buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count; buffer.vBuffers[0].Format = geomStream.Format; buffer.DataValidity = BufferedGeometryData.DataValidityType.Source; buffer.Target = BufferedGeometryData.DataTarget.Geometry; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields // create points AtomShadingDesc aShading = coDesc.AtomShadingDesc; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) { period = (int)atom.Properties["Period"]; } if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write((float)atom.X3d); data.Write((float)atom.Y3d); data.Write((float)atom.Z3d); } if (sizePos != -1) { data.Seek(pos + sizePos, SeekOrigin.Begin); data.Write((float)period); } if (diffusePos != -1) { IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) { material = matTemp.BySymbol; } else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) { material = lookup.GetBySeries(pe.ChemicalSerie); } } if (material != null) { data.Seek(pos + diffusePos, SeekOrigin.Begin); //data.Write((float)material.BaseColor.ToArgb()); if (material.BaseColor.R > 0) { data.Write(255f / material.BaseColor.R); } else { data.Write((float)0); } if (material.BaseColor.G > 0) { data.Write(255f / material.BaseColor.G); } else { data.Write((float)0); } if (material.BaseColor.B > 0) { data.Write(255f / material.BaseColor.B); } else { data.Write((float)0); } } } pos += geomStream.Stride; } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection <IBond> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "NORMAL") { normalPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "TEXTURE0") { texPos = geomStream.FieldPositions[gf]; } //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } // count bond orders via preview data int numActualBonds = 0; foreach (IBond bond in objs) { numActualBonds += (int)bond.Order; } int numVerts = 0; if (coDesc.BondShadingDesc.BlendEndClrs) { numVerts = numActualBonds * 2; } else { numVerts = numActualBonds * 4; } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = numVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = numVerts / 2; buffer.iBuffers[0].PrimType = PrimitiveType.LineList; buffer.vBuffers[0].NumElements = numVerts; buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numVerts, Usage.WriteOnly, geomStream.Format, Pool.Managed); // write bonds to buffer Vector3 direction, directionUV; IAtom[] atoms; Vector3[] atomsPos; IMoleculeMaterial materialA, materialB; Vector3[] bondInstances = null; float midPos; BondShadingDesc bShading = coDesc.BondShadingDesc; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); long pos = 0; foreach (IBond bond in objs) { GenericBondSetup(bond, false, bShading, out direction, out directionUV, out atoms, out atomsPos, out materialA, out materialB); // calc bond positioning / instances GenericBondCalcPositions(bond, bShading, direction, directionUV, atoms, atomsPos, 0.1f, out bondInstances, out midPos, true); // draw bond instances for (int bInst = 0; bInst < bondInstances.Length; bInst += 2) { if (bShading.BlendEndClrs) { GenericDrawBondSolidBlended(bondInstances[bInst], bondInstances[bInst + 1], materialA, materialB, data, ref pos, geomStream.Stride, positionPos, diffusePos); //GenericDrawBondDashedBlended(bondInstances[bInst], bondInstances[bInst + 1], // materialA, materialB); } else { Vector3 sectA = directionUV * midPos; // convert into points (2 lines) if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(bondInstances[bInst].X); data.Write(bondInstances[bInst].Y); data.Write(bondInstances[bInst].Z); data.Seek(pos + geomStream.Stride + positionPos, SeekOrigin.Begin); Vector3 p = bondInstances[bInst] + sectA; data.Write(p.X); data.Write(p.Y); data.Write(p.Z); data.Seek(pos + geomStream.Stride + geomStream.Stride + positionPos, SeekOrigin.Begin); data.Write(p.X); data.Write(p.Y); data.Write(p.Z); data.Seek(pos + geomStream.Stride + geomStream.Stride + geomStream.Stride + positionPos, SeekOrigin.Begin); data.Write(bondInstances[bInst + 1].X); data.Write(bondInstances[bInst + 1].Y); data.Write(bondInstances[bInst + 1].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); int clr = materialA.BaseColor.ToArgb(); data.Write(clr); data.Seek(pos + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); clr = materialB.BaseColor.ToArgb(); data.Seek(pos + geomStream.Stride + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); data.Seek(pos + geomStream.Stride + geomStream.Stride + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); } pos += geomStream.Stride * 4; } } } buffer.vBuffers[0].Buffer.Unlock(); }
public override void UpdateFrameData(BufferedGeometryData[] geomData, GraphicsPipeline3D pipeline) { PointVertex[] blobPoints = (PointVertex[])geomData[0].vBuffers[0].Buffer.Lock(0, LockFlags.None); numPoints = blobPoints.Length; if (needsReset) OnReset(); FillBlobVB(pipeline.WorldMatrix * pipeline.ViewMatrix, pipeline.ProjectionMatrix, ref blobPoints); geomData[0].vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection<IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "NORMAL") normalPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; break; } } } // actually create the metaball triangles or points IVolume[] volumes = new IVolume[objs.Count]; int sIdx = 0; AtomShadingDesc aShading = coDesc.AtomShadingDesc; IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; foreach (IAtom atom in objs) { IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } volumes[sIdx++] = new Metaball(new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d), 0.17f, material.BaseColor); } // process volume into triangles GenericVolumeScene scene = new GenericVolumeScene(volumes); int[] triangles = null; Vector3[] vertices; Color[] colours; Vector3[] normals = null; if (!pointsOnly) { IsosurfaceGenerator3D.GenerateSimpleMesh(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, false, out triangles, out vertices, out colours); MeshOptimzer.GenerateTriPointNormals(triangles, vertices, out normals); } else IsosurfaceGenerator3D.GenerateSimplePointOutline(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, out vertices, out colours); // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * vertices.Length, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = vertices.Length; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; if (pointsOnly) { buffer.iBuffers[0].NumPrimitives = vertices.Length; buffer.iBuffers[0].PrimType = PrimitiveType.PointList; buffer.Light = false; } else { buffer.iBuffers[0].NumPrimitives = triangles.Length / 3; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; buffer.iBuffers[0].Buffer = new IndexBuffer(typeof(int), triangles.Length, device, Usage.WriteOnly, Pool.Managed); } // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields int clr = Color.FromArgb(255, 255, 255).ToArgb(); long pos = 0; for (int i = 0; i < vertices.Length; i++) { if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(vertices[i].X); data.Write(vertices[i].Y); data.Write(vertices[i].Z); } if (normalPos != -1 && !pointsOnly) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(normals[i].X); data.Write(normals[i].Y); data.Write(normals[i].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(colours[i].ToArgb()); } //verts[i].Color = colours[i].ToArgb(); pos += geomStream.Stride; } buffer.vBuffers[0].Buffer.Unlock(); if (!pointsOnly) buffer.iBuffers[0].Buffer.SetData(triangles, 0, LockFlags.None); // dispose of temp data }
public override void CreateGeometryForObjects(Device device, ICollection<IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { if (spriteTexture == null) { Stream texstm = Assembly.GetExecutingAssembly().GetManifestResourceStream("NuGenSVisualLib.Resources.Atom.PNG"); spriteTexture = TextureLoader.FromStream(device, texstm); } // fillable fields int positionPos = -1; int sizePos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "POINTSIZE") sizePos = geomStream.FieldPositions[gf]; break; } } } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(typeof(PointSprite), objs.Count, device, Usage.WriteOnly, geomStream.Format, Pool.Managed); /*new VertexBuffer(device, geomStream.Stride * objs.Count, Usage.None, geomStream.Format, Pool.Managed);*/ buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Sprites; buffer.iBuffers[0].NumPrimitives = objs.Count; buffer.iBuffers[0].PrimType = PrimitiveType.PointList; buffer.iBuffers[0].Textures = new Texture[] { spriteTexture }; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); AtomShadingDesc aShading = coDesc.AtomShadingDesc; long pos = 0; foreach (IAtom atom in objs) { if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write((float)atom.X3d); data.Write((float)atom.Y3d); data.Write((float)atom.Z3d); } if (sizePos != -1) { data.Seek(pos + sizePos, SeekOrigin.Begin); int period = 1; if (atom.Properties.ContainsKey("Period")) period = (int)atom.Properties["Period"]; data.Write((float)period * 0.4f); } if (diffusePos != -1) { IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(material.BaseColor.ToArgb()); } pos += geomStream.Stride; } /*Dictionary<int, List<int>> atomSizeGroups = new Dictionary<int, List<int>>(); // first split into group counts int aIdx = 0; foreach (IAtom[] atoms in atomSets) { foreach (IAtom atom in atoms) { int period = 1; if (atom.Properties.ContainsKey("Period")) period = (int)atom.Properties["Period"]; List<int> groupAtoms = null; if (!atomSizeGroups.TryGetValue(period, out groupAtoms)) atomSizeGroups.Add(period, groupAtoms = new List<int>()); groupAtoms.Add(aIdx++); } } int vertsIdx = 0; Dictionary<int, List<int>>.Enumerator group = atomSizeGroups.GetEnumerator(); sBuffer.groupLengths = new int[atomSizeGroups.Count]; sBuffer.groupSizes = new int[atomSizeGroups.Count]; sBuffer.groupStarts = new int[atomSizeGroups.Count]; int bIdx = 0; while (group.MoveNext()) { int groupPeriod = group.Current.Key; List<int> groupMembers = group.Current.Value; aIdx = 0; int gIdx = 0; sBuffer.groupSizes[bIdx] = groupPeriod; sBuffer.groupStarts[bIdx] = vertsIdx; sBuffer.groupLengths[bIdx] = groupMembers.Count; foreach (IAtom[] atoms in atomSets) { foreach (IAtom atom in atoms) { if (aIdx == groupMembers[gIdx]) { IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } atomVerts[vertsIdx].Position = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); atomVerts[vertsIdx].Color = material.BaseColor.ToArgb(); vertsIdx++; gIdx++; } if (gIdx == groupMembers.Count) break; aIdx++; } if (gIdx == groupMembers.Count) break; } bIdx++; }*/ buffer.vBuffers[0].Buffer.Unlock(); }
public virtual void UpdateFrameData(BufferedGeometryData[] geomData, GraphicsPipeline3D pipeline) { }
public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "NORMAL") { normalPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } break; } } } // actually create the metaball triangles or points IVolume[] volumes = new IVolume[objs.Count]; int sIdx = 0; AtomShadingDesc aShading = coDesc.AtomShadingDesc; IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; foreach (IAtom atom in objs) { IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) { material = matTemp.BySymbol; } else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) { material = lookup.GetBySeries(pe.ChemicalSerie); } } volumes[sIdx++] = new Metaball(new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d), 0.17f, material.BaseColor); } // process volume into triangles GenericVolumeScene scene = new GenericVolumeScene(volumes); int[] triangles = null; Vector3[] vertices; Color[] colours; Vector3[] normals = null; if (!pointsOnly) { IsosurfaceGenerator3D.GenerateSimpleMesh(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, false, out triangles, out vertices, out colours); MeshOptimzer.GenerateTriPointNormals(triangles, vertices, out normals); } else { IsosurfaceGenerator3D.GenerateSimplePointOutline(scene, new Vector3(), scene.EstimateVolumeMaxSize(), 40, out vertices, out colours); } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * vertices.Length, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = vertices.Length; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; if (pointsOnly) { buffer.iBuffers[0].NumPrimitives = vertices.Length; buffer.iBuffers[0].PrimType = PrimitiveType.PointList; buffer.Light = false; } else { buffer.iBuffers[0].NumPrimitives = triangles.Length / 3; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; buffer.iBuffers[0].Buffer = new IndexBuffer(typeof(int), triangles.Length, device, Usage.WriteOnly, Pool.Managed); } // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields int clr = Color.FromArgb(255, 255, 255).ToArgb(); long pos = 0; for (int i = 0; i < vertices.Length; i++) { if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(vertices[i].X); data.Write(vertices[i].Y); data.Write(vertices[i].Z); } if (normalPos != -1 && !pointsOnly) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(normals[i].X); data.Write(normals[i].Y); data.Write(normals[i].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(colours[i].ToArgb()); } //verts[i].Color = colours[i].ToArgb(); pos += geomStream.Stride; } buffer.vBuffers[0].Buffer.Unlock(); if (!pointsOnly) { buffer.iBuffers[0].Buffer.SetData(triangles, 0, LockFlags.None); } // dispose of temp data }
public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "NORMAL") { normalPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "TEXTURE0") { texPos = geomStream.FieldPositions[gf]; } //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } int numVerts = sphereDetail1 * sphereDetail2 * 6; int numTris = sphereDetail1 * sphereDetail2 * 2; // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numVerts * objs.Count, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count * numVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = objs.Count * numTris; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields bool newWay = true; if (!newWay) { // create template sphere SphereMathHelper.SphereN sphere = SphereMathHelper.CalcSphereWNormals(sphereDetail1, sphereDetail2, 1.0f, new Vector3(), true); // clone and scale template for each size required Vector3 center = new Vector3(); Dictionary <int, Vector3[]> spheres = new Dictionary <int, Vector3[]>(); AtomShadingDesc aShading = coDesc.AtomShadingDesc; //int vertsIdx = 0; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) { period = (int)atom.Properties["Period"]; } // check for existing if (!spheres.ContainsKey(period)) { // scale template float size = period * _Scaling; Vector4[] vertices = Vector3.Transform(sphere.Positions, Matrix.Scaling(size, size, size)); Vector3[] vertices3 = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { vertices3[i] = new Vector3(vertices[i].X, vertices[i].Y, vertices[i].Z); } spheres.Add(period, vertices3); } Vector3[] sphereData = spheres[period]; // write to buffer IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) { material = matTemp.BySymbol; } else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) { material = lookup.GetBySeries(pe.ChemicalSerie); } } // copy sphere Vector3 atomSpace = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); /*Vector4 clr = new Vector4((float)material.BaseColor.R / 255f, (float)material.BaseColor.G / 255f, * (float)material.BaseColor.B / 255f, (float)material.BaseColor.A / 255f);*/ int clr = material.BaseColor.ToArgb(); for (int v = 0; v < sphereData.Length; v++) { if (positionPos != -1) { Vector3 position = sphereData[v] + atomSpace; data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(position.X); data.Write(position.Y); data.Write(position.Z); } if (texPos != -1) { data.Seek(pos + texPos, SeekOrigin.Begin); data.Write(0f); //sphere.TexCoords[v].X); data.Write(0f); //sphere.TexCoords[v].Y); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(sphere.Normals[v].X); data.Write(sphere.Normals[v].Y); data.Write(sphere.Normals[v].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); /*data.Write(clr.X); * data.Write(clr.Y); * data.Write(clr.Z); * data.Write(clr.W);*/ data.Write((Int32)clr); } pos += geomStream.Stride; } } } else { Vector3[] Positions, normals; Vector2[] texCoords; SphereMathHelper.CreateSphereTriangles(new Vector3(), 1, sphereDetail1, out Positions, out normals, out texCoords); // clone and scale template for each size required Vector3 center = new Vector3(); Dictionary <int, Vector3[]> spheres = new Dictionary <int, Vector3[]>(); AtomShadingDesc aShading = coDesc.AtomShadingDesc; int vertsIdx = 0; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) { period = (int)atom.Properties["Period"]; } // check for existing if (!spheres.ContainsKey(period)) { // scale template float size = period * _Scaling; Vector4[] vertices = Vector3.Transform(Positions, Matrix.Scaling(size, size, size)); Vector3[] vertices3 = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { vertices3[i] = new Vector3(vertices[i].X, vertices[i].Y, vertices[i].Z); } spheres.Add(period, vertices3); } Vector3[] sphereData = spheres[period]; // write to buffer IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) { material = matTemp.BySymbol; } else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) { material = lookup.GetBySeries(pe.ChemicalSerie); } } // copy sphere Vector3 atomSpace = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); int clr = material.BaseColor.ToArgb(); for (int v = 0; v < sphereData.Length; v++) { if (positionPos != -1) { Vector3 position = sphereData[v] + atomSpace; data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(position.X); data.Write(position.Y); data.Write(position.Z); } if (texPos != -1) { data.Seek(pos + texPos, SeekOrigin.Begin); data.Write(texCoords[v].X); data.Write(texCoords[v].Y); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(normals[v].X); data.Write(normals[v].Y); data.Write(normals[v].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); /*data.Write(clr.X); * data.Write(clr.Y); * data.Write(clr.Z); * data.Write(clr.W);*/ data.Write((Int32)clr); } pos += geomStream.Stride; } } } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int sizePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "POINTSIZE") { sizePos = geomStream.FieldPositions[gf]; } break; } } } // pre-scan for index groups Dictionary <string, List <int> > groups = new Dictionary <string, List <int> >(); int aIdx = 0; foreach (IAtom atom in objs) { if (!groups.ContainsKey(atom.Symbol)) { groups[atom.Symbol] = new List <int>(); } groups[atom.Symbol].Add(aIdx++); } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(typeof(PointSprite), objs.Count, device, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count; buffer.vBuffers[0].Format = geomStream.Format; buffer.DataValidity = BufferedGeometryData.DataValidityType.View; ChemSymbolTextures cTex = ChemSymbolTextures.Instance; buffer.iBuffers = new BufferedGeometryData.IndexData[groups.Count]; int gIdx = 0; foreach (KeyValuePair <string, List <int> > group in groups) { buffer.iBuffers[gIdx] = new BufferedGeometryData.IndexData(); buffer.iBuffers[gIdx].Desc = BufferedGeometryData.IndexData.Description.Sprites; buffer.iBuffers[gIdx].NumPrimitives = group.Value.Count; buffer.iBuffers[gIdx].PrimType = PrimitiveType.PointList; buffer.iBuffers[gIdx].Textures = new Texture[] { cTex[group.Key] }; buffer.iBuffers[gIdx].Buffer = new IndexBuffer(typeof(int), group.Value.Count, device, Usage.WriteOnly, Pool.Managed); int[] indices = (int[])buffer.iBuffers[gIdx].Buffer.Lock(0, LockFlags.None); for (int i = 0; i < indices.Length; i++) { indices[i] = group.Value[i]; } buffer.iBuffers[gIdx].Buffer.Unlock(); gIdx++; } // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); AtomShadingDesc aShading = coDesc.AtomShadingDesc; long pos = 0; foreach (IAtom atom in objs) { if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write((float)atom.X3d); data.Write((float)atom.Y3d); data.Write((float)atom.Z3d); } if (sizePos != -1) { data.Seek(pos + sizePos, SeekOrigin.Begin); int period = 1; if (atom.Properties.ContainsKey("Period")) { period = (int)atom.Properties["Period"]; } data.Write((float)period * 0.2f); } pos += geomStream.Stride; } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection <IBond> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "NORMAL") { normalPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "TEXTURE0") { texPos = geomStream.FieldPositions[gf]; } //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } // count bond orders via preview data int numActualBonds = 0; foreach (IBond bond in objs) { numActualBonds += (int)bond.Order; } if (!coDesc.BondShadingDesc.BlendEndClrs) { numActualBonds *= 2; } int numTriangles = objs.Count * (numSides * 2); SphereMathHelper.EndType endType = SphereMathHelper.EndType.Open; float offset = 0.0f; switch (coDesc.BondShadingDesc.EndType) { case BondShadingDesc.BondEndTypes.Open: break; case BondShadingDesc.BondEndTypes.Closed: numTriangles += numActualBonds * (numSides * 2); endType = SphereMathHelper.EndType.Flat; break; case BondShadingDesc.BondEndTypes.Point: offset = 0.05f; numTriangles += numActualBonds * (numSides * 2); endType = SphereMathHelper.EndType.Flat; break; case BondShadingDesc.BondEndTypes.Rounded: offset = 0.075f; numTriangles += numActualBonds * (numSides * 6); endType = SphereMathHelper.EndType.Rounded; break; } // build template bond Vector3[] tCylinderPoints, tCylinderEndPoints1, tCylinderEndPoints2; Vector3[] tCylinderNormals, tCylinderEndNormals1, tCylinderEndNormals2; int[] tCylinderTris, tCylinderEndTris1, tCylinderEndTris2; SphereMathHelper.CalcCylinderTriangles(numSides, 1, 1.0f, new Vector3(0, 0, 0), new Vector3(0, 0, 1), true, endType, offset, out tCylinderPoints, out tCylinderNormals, out tCylinderTris, out tCylinderEndPoints1, out tCylinderEndNormals1, out tCylinderEndTris1, out tCylinderEndPoints2, out tCylinderEndNormals2, out tCylinderEndTris2); int numActualVerts = tCylinderPoints.Length + tCylinderEndPoints1.Length + tCylinderEndPoints2.Length; int numActualTris = tCylinderTris.Length + tCylinderEndTris1.Length + tCylinderEndTris2.Length; // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = numActualVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.vBuffers[0].NumElements = numActualVerts * numActualBonds; buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numActualTris * numActualBonds * 3, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = numActualTris; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; buffer.iBuffers[0].NumPrimitives = (numActualTris * numActualBonds) / 3; /*buffer.iBuffers[0].Buffer = new IndexBuffer(typeof(int), numActualTris * numActualBonds, device, * Usage.WriteOnly, Pool.Managed);*/ // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // write bonds to buffer Vector3 direction, directionUV; IAtom[] atoms; Vector3[] atomsPos; IMoleculeMaterial matA, matB; foreach (IBond bond in objs) { BondLinesBufferCreator.GenericBondSetup(bond, true, coDesc.BondShadingDesc, out direction, out directionUV, out atoms, out atomsPos, out matA, out matB); // calc bond positioning / instances Vector3[] bondInstances = null; float midPos; BondLinesBufferCreator.GenericBondCalcPositions(bond, coDesc.BondShadingDesc, direction, directionUV, atoms, atomsPos, 0.15f, out bondInstances, out midPos, false); long pos = 0; for (int bInst = 0; bInst < bondInstances.Length; bInst += 2) { // translation Matrix translate = Matrix.Translation(bondInstances[bInst]); // rotation double x = direction.X; double y = direction.Y; double z = direction.Z; double alpha = (z == 0) ? Math.PI / 2 : Math.Atan(x / z); double r = (alpha == 0) ? z : x / Math.Sin(alpha); float sign = 1f; if (z != 0) { sign *= Math.Sign(z); } else if (x != 0) { sign *= Math.Sign(x); } if (y != 0) { sign *= Math.Sign(y); } double theta = -sign *Math.Abs((r == 0)?Math.PI / 2 : Math.Atan(y / r)); Matrix rotation = Matrix.RotationX((float)theta) * Matrix.RotationY((float)alpha); // scaling float zScale; if (coDesc.BondShadingDesc.BlendEndClrs) { zScale = (bondInstances[1] - bondInstances[0]).Length();//(atomsPos[1] - atomsPos[0]).Length();//direction.Length(); } else { zScale = midPos; } float xyScale = 0.05f; // thickness Matrix scale = Matrix.Scaling(xyScale, xyScale, zScale); // rotate & translate ends if (tCylinderEndPoints1 != null) { Matrix endFinal = Matrix.Scaling(xyScale, xyScale, 1f) * rotation * translate; Vector4[] tfEndTriangles = Vector3.Transform(tCylinderEndPoints1, endFinal); // first end for (int point = 0; point < tCylinderEndTris1.Length; point++) { int pointIdx = tCylinderEndTris1[point]; if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(tfEndTriangles[pointIdx].X); data.Write(tfEndTriangles[pointIdx].Y); data.Write(tfEndTriangles[pointIdx].Z); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(tCylinderEndNormals1[pointIdx].X); data.Write(tCylinderEndNormals1[pointIdx].Y); data.Write(tCylinderEndNormals1[pointIdx].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(matA.BaseColor.ToArgb()); } pos += geomStream.Stride; } // second end endFinal = Matrix.Scaling(xyScale, xyScale, 1f) * rotation * Matrix.Translation(bondInstances[bInst + 1]); tfEndTriangles = Vector3.Transform(tCylinderEndPoints2, endFinal); // first end for (int point = 0; point < tCylinderEndTris2.Length; point++) { int pointIdx = tCylinderEndTris2[point]; if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(tfEndTriangles[pointIdx].X); data.Write(tfEndTriangles[pointIdx].Y); data.Write(tfEndTriangles[pointIdx].Z); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(tCylinderEndNormals2[pointIdx].X); data.Write(tCylinderEndNormals2[pointIdx].Y); data.Write(tCylinderEndNormals2[pointIdx].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(matB.BaseColor.ToArgb()); } pos += geomStream.Stride; } } Matrix final = scale * rotation * translate; if (coDesc.BondShadingDesc.BlendEndClrs) { DrawSolidBondBlended(tCylinderPoints, tCylinderNormals, tCylinderTris, matA, matB, final, data, positionPos, normalPos, diffusePos, ref pos, geomStream.Stride, rotation); } else { float bLen2 = (bondInstances[bInst + 1] - (bondInstances[bInst] + (directionUV * midPos))).Length(); DrawSolidBondDistinct(tCylinderPoints, tCylinderNormals, tCylinderTris, matA, matB, final, data, xyScale, bLen2, rotation, bondInstances[bInst], directionUV, midPos, positionPos, normalPos, diffusePos, ref pos, geomStream.Stride); } } } }
public override void CreateGeometryForObjects(Device device, ICollection<IBond> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "NORMAL") normalPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "TEXTURE0") texPos = geomStream.FieldPositions[gf]; //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } // count bond orders via preview data int numActualBonds = 0; foreach (IBond bond in objs) { numActualBonds += (int)bond.Order; } if (!coDesc.BondShadingDesc.BlendEndClrs) numActualBonds *= 2; int numTriangles = objs.Count * (numSides * 2); SphereMathHelper.EndType endType = SphereMathHelper.EndType.Open; float offset = 0.0f; switch (coDesc.BondShadingDesc.EndType) { case BondShadingDesc.BondEndTypes.Open: break; case BondShadingDesc.BondEndTypes.Closed: numTriangles += numActualBonds * (numSides * 2); endType = SphereMathHelper.EndType.Flat; break; case BondShadingDesc.BondEndTypes.Point: offset = 0.05f; numTriangles += numActualBonds * (numSides * 2); endType = SphereMathHelper.EndType.Flat; break; case BondShadingDesc.BondEndTypes.Rounded: offset = 0.075f; numTriangles += numActualBonds * (numSides * 6); endType = SphereMathHelper.EndType.Rounded; break; } // build template bond Vector3[] tCylinderPoints, tCylinderEndPoints1, tCylinderEndPoints2; Vector3[] tCylinderNormals, tCylinderEndNormals1, tCylinderEndNormals2; int[] tCylinderTris, tCylinderEndTris1, tCylinderEndTris2; SphereMathHelper.CalcCylinderTriangles(numSides, 1, 1.0f, new Vector3(0, 0, 0), new Vector3(0, 0, 1), true, endType, offset, out tCylinderPoints, out tCylinderNormals, out tCylinderTris, out tCylinderEndPoints1, out tCylinderEndNormals1, out tCylinderEndTris1, out tCylinderEndPoints2, out tCylinderEndNormals2, out tCylinderEndTris2); int numActualVerts = tCylinderPoints.Length + tCylinderEndPoints1.Length + tCylinderEndPoints2.Length; int numActualTris = tCylinderTris.Length + tCylinderEndTris1.Length + tCylinderEndTris2.Length; // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = numActualVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.vBuffers[0].NumElements = numActualVerts * numActualBonds; buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numActualTris * numActualBonds * 3, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = numActualTris; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; buffer.iBuffers[0].NumPrimitives = (numActualTris * numActualBonds) / 3; /*buffer.iBuffers[0].Buffer = new IndexBuffer(typeof(int), numActualTris * numActualBonds, device, Usage.WriteOnly, Pool.Managed);*/ // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // write bonds to buffer Vector3 direction, directionUV; IAtom[] atoms; Vector3[] atomsPos; IMoleculeMaterial matA, matB; foreach (IBond bond in objs) { BondLinesBufferCreator.GenericBondSetup(bond, true, coDesc.BondShadingDesc, out direction, out directionUV, out atoms, out atomsPos, out matA, out matB); // calc bond positioning / instances Vector3[] bondInstances = null; float midPos; BondLinesBufferCreator.GenericBondCalcPositions(bond, coDesc.BondShadingDesc, direction, directionUV, atoms, atomsPos, 0.15f, out bondInstances, out midPos, false); long pos = 0; for (int bInst = 0; bInst < bondInstances.Length; bInst += 2) { // translation Matrix translate = Matrix.Translation(bondInstances[bInst]); // rotation double x = direction.X; double y = direction.Y; double z = direction.Z; double alpha = (z == 0) ? Math.PI / 2 : Math.Atan(x / z); double r = (alpha == 0) ? z : x / Math.Sin(alpha); float sign = 1f; if (z != 0) sign *= Math.Sign(z); else if (x != 0) sign *= Math.Sign(x); if (y != 0) sign *= Math.Sign(y); double theta = -sign * Math.Abs((r == 0) ? Math.PI / 2 : Math.Atan(y / r)); Matrix rotation = Matrix.RotationX((float)theta) * Matrix.RotationY((float)alpha); // scaling float zScale; if (coDesc.BondShadingDesc.BlendEndClrs) zScale = (bondInstances[1] - bondInstances[0]).Length();//(atomsPos[1] - atomsPos[0]).Length();//direction.Length(); else zScale = midPos; float xyScale = 0.05f; // thickness Matrix scale = Matrix.Scaling(xyScale, xyScale, zScale); // rotate & translate ends if (tCylinderEndPoints1 != null) { Matrix endFinal = Matrix.Scaling(xyScale, xyScale, 1f) * rotation * translate; Vector4[] tfEndTriangles = Vector3.Transform(tCylinderEndPoints1, endFinal); // first end for (int point = 0; point < tCylinderEndTris1.Length; point++) { int pointIdx = tCylinderEndTris1[point]; if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(tfEndTriangles[pointIdx].X); data.Write(tfEndTriangles[pointIdx].Y); data.Write(tfEndTriangles[pointIdx].Z); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(tCylinderEndNormals1[pointIdx].X); data.Write(tCylinderEndNormals1[pointIdx].Y); data.Write(tCylinderEndNormals1[pointIdx].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(matA.BaseColor.ToArgb()); } pos += geomStream.Stride; } // second end endFinal = Matrix.Scaling(xyScale, xyScale, 1f) * rotation * Matrix.Translation(bondInstances[bInst + 1]); tfEndTriangles = Vector3.Transform(tCylinderEndPoints2, endFinal); // first end for (int point = 0; point < tCylinderEndTris2.Length; point++) { int pointIdx = tCylinderEndTris2[point]; if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(tfEndTriangles[pointIdx].X); data.Write(tfEndTriangles[pointIdx].Y); data.Write(tfEndTriangles[pointIdx].Z); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(tCylinderEndNormals2[pointIdx].X); data.Write(tCylinderEndNormals2[pointIdx].Y); data.Write(tCylinderEndNormals2[pointIdx].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(matB.BaseColor.ToArgb()); } pos += geomStream.Stride; } } Matrix final = scale * rotation * translate; if (coDesc.BondShadingDesc.BlendEndClrs) { DrawSolidBondBlended(tCylinderPoints, tCylinderNormals, tCylinderTris, matA, matB, final, data, positionPos, normalPos, diffusePos, ref pos, geomStream.Stride, rotation); } else { float bLen2 = (bondInstances[bInst + 1] - (bondInstances[bInst] + (directionUV * midPos))).Length(); DrawSolidBondDistinct(tCylinderPoints, tCylinderNormals, tCylinderTris, matA, matB, final, data, xyScale, bLen2, rotation, bondInstances[bInst], directionUV, midPos, positionPos, normalPos, diffusePos, ref pos, geomStream.Stride); } } } }
public override void CreateGeometryForObjects(Device device, ICollection<IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int sizePos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "SIZEFLOAT") sizePos = geomStream.FieldPositions[gf]; break; } } } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(typeof(MetaBlobsEffect.PointVertex), objs.Count, device, Usage.None, VertexFormats.Position | VertexFormats.PointSize | VertexFormats.Diffuse, Pool.SystemMemory); /*new VertexBuffer(device, geomStream.Stride * objs.Count, Usage.WriteOnly, geomStream.Format, Pool.SystemMemory);*/ buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count; buffer.vBuffers[0].Format = geomStream.Format; buffer.DataValidity = BufferedGeometryData.DataValidityType.Source; buffer.Target = BufferedGeometryData.DataTarget.Geometry; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields // create points AtomShadingDesc aShading = coDesc.AtomShadingDesc; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) period = (int)atom.Properties["Period"]; if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write((float)atom.X3d); data.Write((float)atom.Y3d); data.Write((float)atom.Z3d); } if (sizePos != -1) { data.Seek(pos + sizePos, SeekOrigin.Begin); data.Write((float)period); } if (diffusePos != -1) { IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } if (material != null) { data.Seek(pos + diffusePos, SeekOrigin.Begin); //data.Write((float)material.BaseColor.ToArgb()); if (material.BaseColor.R > 0) data.Write(255f / material.BaseColor.R); else data.Write((float)0); if (material.BaseColor.G > 0) data.Write(255f / material.BaseColor.G); else data.Write((float)0); if (material.BaseColor.B > 0) data.Write(255f / material.BaseColor.B); else data.Write((float)0); } } pos += geomStream.Stride; } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection <IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { if (spriteTexture == null) { Stream texstm = Assembly.GetExecutingAssembly().GetManifestResourceStream("NuGenSVisualLib.Resources.Atom.PNG"); spriteTexture = TextureLoader.FromStream(device, texstm); } // fillable fields int positionPos = -1; int sizePos = -1; int diffusePos = -1; // match field locations for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") { positionPos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "DIFFUSE") { diffusePos = geomStream.FieldPositions[gf]; } else if (fields[i].Usage == "POINTSIZE") { sizePos = geomStream.FieldPositions[gf]; } break; } } } // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(typeof(PointSprite), objs.Count, device, Usage.WriteOnly, geomStream.Format, Pool.Managed); /*new VertexBuffer(device, geomStream.Stride * objs.Count, * Usage.None, geomStream.Format, Pool.Managed);*/ buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Sprites; buffer.iBuffers[0].NumPrimitives = objs.Count; buffer.iBuffers[0].PrimType = PrimitiveType.PointList; buffer.iBuffers[0].Textures = new Texture[] { spriteTexture }; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); AtomShadingDesc aShading = coDesc.AtomShadingDesc; long pos = 0; foreach (IAtom atom in objs) { if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write((float)atom.X3d); data.Write((float)atom.Y3d); data.Write((float)atom.Z3d); } if (sizePos != -1) { data.Seek(pos + sizePos, SeekOrigin.Begin); int period = 1; if (atom.Properties.ContainsKey("Period")) { period = (int)atom.Properties["Period"]; } data.Write((float)period * 0.4f); } if (diffusePos != -1) { IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) { material = matTemp.BySymbol; } else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) { material = lookup.GetBySeries(pe.ChemicalSerie); } } data.Seek(pos + diffusePos, SeekOrigin.Begin); data.Write(material.BaseColor.ToArgb()); } pos += geomStream.Stride; } /*Dictionary<int, List<int>> atomSizeGroups = new Dictionary<int, List<int>>(); * // first split into group counts * int aIdx = 0; * foreach (IAtom[] atoms in atomSets) * { * foreach (IAtom atom in atoms) * { * int period = 1; * if (atom.Properties.ContainsKey("Period")) * period = (int)atom.Properties["Period"]; * * List<int> groupAtoms = null; * if (!atomSizeGroups.TryGetValue(period, out groupAtoms)) * atomSizeGroups.Add(period, groupAtoms = new List<int>()); * * groupAtoms.Add(aIdx++); * } * } * * int vertsIdx = 0; * Dictionary<int, List<int>>.Enumerator group = atomSizeGroups.GetEnumerator(); * sBuffer.groupLengths = new int[atomSizeGroups.Count]; * sBuffer.groupSizes = new int[atomSizeGroups.Count]; * sBuffer.groupStarts = new int[atomSizeGroups.Count]; * int bIdx = 0; * while (group.MoveNext()) * { * int groupPeriod = group.Current.Key; * List<int> groupMembers = group.Current.Value; * aIdx = 0; * int gIdx = 0; * sBuffer.groupSizes[bIdx] = groupPeriod; * sBuffer.groupStarts[bIdx] = vertsIdx; * sBuffer.groupLengths[bIdx] = groupMembers.Count; * foreach (IAtom[] atoms in atomSets) * { * foreach (IAtom atom in atoms) * { * if (aIdx == groupMembers[gIdx]) * { * IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; * IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); * IMoleculeMaterial material = null; * if (matTemp != null) * material = matTemp.BySymbol; * else * { * PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; * if (pe != null) * material = lookup.GetBySeries(pe.ChemicalSerie); * } * * atomVerts[vertsIdx].Position = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); * atomVerts[vertsIdx].Color = material.BaseColor.ToArgb(); * vertsIdx++; * gIdx++; * } * if (gIdx == groupMembers.Count) * break; * aIdx++; * } * if (gIdx == groupMembers.Count) * break; * } * bIdx++; * }*/ buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection<IAtom> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "NORMAL") normalPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "TEXTURE0") texPos = geomStream.FieldPositions[gf]; //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } int numVerts = sphereDetail1 * sphereDetail2 * 6; int numTris = sphereDetail1 * sphereDetail2 * 2; // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numVerts * objs.Count, Usage.WriteOnly, geomStream.Format, Pool.Managed); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = objs.Count * numVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = objs.Count * numTris; buffer.iBuffers[0].PrimType = PrimitiveType.TriangleList; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); // fill fields bool newWay = true; if (!newWay) { // create template sphere SphereMathHelper.SphereN sphere = SphereMathHelper.CalcSphereWNormals(sphereDetail1, sphereDetail2, 1.0f, new Vector3(), true); // clone and scale template for each size required Vector3 center = new Vector3(); Dictionary<int, Vector3[]> spheres = new Dictionary<int, Vector3[]>(); AtomShadingDesc aShading = coDesc.AtomShadingDesc; //int vertsIdx = 0; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) period = (int)atom.Properties["Period"]; // check for existing if (!spheres.ContainsKey(period)) { // scale template float size = period * _Scaling; Vector4[] vertices = Vector3.Transform(sphere.Positions, Matrix.Scaling(size, size, size)); Vector3[] vertices3 = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { vertices3[i] = new Vector3(vertices[i].X, vertices[i].Y, vertices[i].Z); } spheres.Add(period, vertices3); } Vector3[] sphereData = spheres[period]; // write to buffer IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } // copy sphere Vector3 atomSpace = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); /*Vector4 clr = new Vector4((float)material.BaseColor.R / 255f, (float)material.BaseColor.G / 255f, (float)material.BaseColor.B / 255f, (float)material.BaseColor.A / 255f);*/ int clr = material.BaseColor.ToArgb(); for (int v = 0; v < sphereData.Length; v++) { if (positionPos != -1) { Vector3 position = sphereData[v] + atomSpace; data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(position.X); data.Write(position.Y); data.Write(position.Z); } if (texPos != -1) { data.Seek(pos + texPos, SeekOrigin.Begin); data.Write(0f);//sphere.TexCoords[v].X); data.Write(0f);//sphere.TexCoords[v].Y); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(sphere.Normals[v].X); data.Write(sphere.Normals[v].Y); data.Write(sphere.Normals[v].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); /*data.Write(clr.X); data.Write(clr.Y); data.Write(clr.Z); data.Write(clr.W);*/ data.Write((Int32)clr); } pos += geomStream.Stride; } } } else { Vector3[] Positions, normals; Vector2[] texCoords; SphereMathHelper.CreateSphereTriangles(new Vector3(), 1, sphereDetail1, out Positions, out normals, out texCoords); // clone and scale template for each size required Vector3 center = new Vector3(); Dictionary<int, Vector3[]> spheres = new Dictionary<int, Vector3[]>(); AtomShadingDesc aShading = coDesc.AtomShadingDesc; int vertsIdx = 0; long pos = 0; foreach (IAtom atom in objs) { int period = 1; if (atom.Properties.ContainsKey("Period")) period = (int)atom.Properties["Period"]; // check for existing if (!spheres.ContainsKey(period)) { // scale template float size = period * _Scaling; Vector4[] vertices = Vector3.Transform(Positions, Matrix.Scaling(size, size, size)); Vector3[] vertices3 = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { vertices3[i] = new Vector3(vertices[i].X, vertices[i].Y, vertices[i].Z); } spheres.Add(period, vertices3); } Vector3[] sphereData = spheres[period]; // write to buffer IMoleculeMaterialLookup lookup = aShading.MoleculeMaterials; IMoleculeMaterialTemplate matTemp = lookup.ResolveBySymbol(atom.Symbol); IMoleculeMaterial material = null; if (matTemp != null) material = matTemp.BySymbol; else { PeriodicTableElement pe = (PeriodicTableElement)atom.Properties["PeriodicTableElement"]; if (pe != null) material = lookup.GetBySeries(pe.ChemicalSerie); } // copy sphere Vector3 atomSpace = new Vector3((float)atom.X3d, (float)atom.Y3d, (float)atom.Z3d); int clr = material.BaseColor.ToArgb(); for (int v = 0; v < sphereData.Length; v++) { if (positionPos != -1) { Vector3 position = sphereData[v] + atomSpace; data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(position.X); data.Write(position.Y); data.Write(position.Z); } if (texPos != -1) { data.Seek(pos + texPos, SeekOrigin.Begin); data.Write(texCoords[v].X); data.Write(texCoords[v].Y); } if (normalPos != -1) { data.Seek(pos + normalPos, SeekOrigin.Begin); data.Write(normals[v].X); data.Write(normals[v].Y); data.Write(normals[v].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); /*data.Write(clr.X); data.Write(clr.Y); data.Write(clr.Z); data.Write(clr.W);*/ data.Write((Int32)clr); } pos += geomStream.Stride; } } } buffer.vBuffers[0].Buffer.Unlock(); }
public override void CreateGeometryForObjects(Device device, ICollection<IBond> objs, GeomDataBufferStream geomStream, int stream, ref BufferedGeometryData buffer, CompleteOutputDescription coDesc) { // fillable fields int positionPos = -1; int normalPos = -1; int diffusePos = -1; int texPos = -1; // match field locations //int[] fieldsPos = new int[fields.Length]; for (int i = 0; i < fields.Length; i++) { for (int gf = 0; gf < geomStream.Fields.Length; gf++) { if (fields[i].Format == geomStream.Fields[gf]) { if (fields[i].Usage == "POSITION") positionPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "NORMAL") normalPos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "DIFFUSE") diffusePos = geomStream.FieldPositions[gf]; else if (fields[i].Usage == "TEXTURE0") texPos = geomStream.FieldPositions[gf]; //fieldsPos[i] = geomStream.FieldPositions[gf]; break; } } } // count bond orders via preview data int numActualBonds = 0; foreach (IBond bond in objs) { numActualBonds += (int)bond.Order; } int numVerts = 0; if (coDesc.BondShadingDesc.BlendEndClrs) numVerts = numActualBonds * 2; else numVerts = numActualBonds * 4; // create buffers buffer = new BufferedGeometryData(device, objs.Count); buffer.vBuffers = new BufferedGeometryData.VertexData[1]; buffer.vBuffers[0] = new BufferedGeometryData.VertexData(); buffer.vBuffers[0].Stride = geomStream.Stride; buffer.vBuffers[0].NumElements = numVerts; buffer.vBuffers[0].Format = geomStream.Format; buffer.iBuffers = new BufferedGeometryData.IndexData[1]; buffer.iBuffers[0] = new BufferedGeometryData.IndexData(); buffer.iBuffers[0].Desc = BufferedGeometryData.IndexData.Description.Geometry; buffer.iBuffers[0].NumPrimitives = numVerts / 2; buffer.iBuffers[0].PrimType = PrimitiveType.LineList; buffer.vBuffers[0].NumElements = numVerts; buffer.vBuffers[0].Buffer = new VertexBuffer(device, geomStream.Stride * numVerts, Usage.WriteOnly, geomStream.Format, Pool.Managed); // write bonds to buffer Vector3 direction, directionUV; IAtom[] atoms; Vector3[] atomsPos; IMoleculeMaterial materialA, materialB; Vector3[] bondInstances = null; float midPos; BondShadingDesc bShading = coDesc.BondShadingDesc; // lock stream GraphicsStream data = buffer.vBuffers[0].Buffer.Lock(0, 0, LockFlags.None); long pos = 0; foreach (IBond bond in objs) { GenericBondSetup(bond, false, bShading, out direction, out directionUV, out atoms, out atomsPos, out materialA, out materialB); // calc bond positioning / instances GenericBondCalcPositions(bond, bShading, direction, directionUV, atoms, atomsPos, 0.1f, out bondInstances, out midPos, true); // draw bond instances for (int bInst = 0; bInst < bondInstances.Length; bInst += 2) { if (bShading.BlendEndClrs) { GenericDrawBondSolidBlended(bondInstances[bInst], bondInstances[bInst + 1], materialA, materialB, data, ref pos, geomStream.Stride, positionPos, diffusePos); //GenericDrawBondDashedBlended(bondInstances[bInst], bondInstances[bInst + 1], // materialA, materialB); } else { Vector3 sectA = directionUV * midPos; // convert into points (2 lines) if (positionPos != -1) { data.Seek(pos + positionPos, SeekOrigin.Begin); data.Write(bondInstances[bInst].X); data.Write(bondInstances[bInst].Y); data.Write(bondInstances[bInst].Z); data.Seek(pos + geomStream.Stride + positionPos, SeekOrigin.Begin); Vector3 p = bondInstances[bInst] + sectA; data.Write(p.X); data.Write(p.Y); data.Write(p.Z); data.Seek(pos + geomStream.Stride + geomStream.Stride + positionPos, SeekOrigin.Begin); data.Write(p.X); data.Write(p.Y); data.Write(p.Z); data.Seek(pos + geomStream.Stride + geomStream.Stride + geomStream.Stride + positionPos, SeekOrigin.Begin); data.Write(bondInstances[bInst + 1].X); data.Write(bondInstances[bInst + 1].Y); data.Write(bondInstances[bInst + 1].Z); } if (diffusePos != -1) { data.Seek(pos + diffusePos, SeekOrigin.Begin); int clr = materialA.BaseColor.ToArgb(); data.Write(clr); data.Seek(pos + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); clr = materialB.BaseColor.ToArgb(); data.Seek(pos + geomStream.Stride + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); data.Seek(pos + geomStream.Stride + geomStream.Stride + geomStream.Stride + diffusePos, SeekOrigin.Begin); data.Write(clr); } pos += geomStream.Stride * 4; } } } buffer.vBuffers[0].Buffer.Unlock(); }