예제 #1
0
 public AtomShadingDesc(AtomShadingDesc toClone)
 {
     this.fillMode          = toClone.fillMode;
     this.symbolText        = toClone.symbolText;
     this.moleculeMaterials = toClone.moleculeMaterials;
     this.Draw = toClone.Draw;
 }
예제 #2
0
 public AtomShadingDesc(AtomShadingDesc toClone)
 {
     this.fillMode = toClone.fillMode;
     this.symbolText = toClone.symbolText;
     this.moleculeMaterials = toClone.moleculeMaterials;
     this.Draw = toClone.Draw;
 }
 public CompleteOutputDescription(CompleteOutputDescription toClone)
 {
     generalShadingDesc = new GeneralShadingDesc(toClone.GeneralShadingDesc);
     generalLightingDesc = new GeneralLightingDesc(toClone.GeneralLightingDesc);
     atomShadingDesc = new AtomShadingDesc(toClone.AtomShadingDesc);
     bondShadingDesc = new BondShadingDesc(toClone.BondShadingDesc);
     //structuresShadingDesc = new GeneralStructuresShadingDesc(toClone.GeneralStructuresShadingDesc);
     schemeSettings = (MoleculeSchemeSettings)toClone.schemeSettings.Clone();
 }
예제 #4
0
        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();
        }
예제 #5
0
        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
        }
예제 #6
0
        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 <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();
        }