コード例 #1
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();
        }
コード例 #2
0
        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);
                    }
                }
            }
        }