Beispiel #1
0
        public Scene()
        {
            Primitives = new List<Primitive>();
            Lights = new List<Light>();
            Extends = new AxisAlignedBox();

            _state = 0;
        }
Beispiel #2
0
        //public void Subdivide(KdTreeNode node, AxisAlignedBox box, int depth, int prims) {
        //    // recycle used split list nodes
        //    _list = null;
        //    // determine split axis
        //    Vector3D s = box.Size;
        //    if ((s.X >= s.Y) && (s.X >= s.Z))
        //        node.Axis = 0;
        //    else if ((s.Y >= s.X) && (s.Y >= s.Z))
        //        node.Axis = 1;
        //    int axis = node.Axis;
        //    // make a list of the split position candidates
        //    ObjectList l = node.List;
        //    double p1, p2;
        //    double pos1 = box.Position[axis];
        //    double pos2 = box.Position[axis] + box.Size[axis];
        //    bool[] pright = new bool[prims];
        //    double[] eleft = new double[prims];
        //    double[] eright = new double[prims];
        //    Primitive[] parray = new Primitive[prims];
        //    int aidx = 0;
        //    while (l != null) {
        //        parray[aidx] = l.Primitive;
        //        Primitive p = parray[aidx];
        //        pright[aidx] = true;
        //        p.CalculateRange(ref eleft[aidx], ref eright[aidx], axis);
        //        aidx++;
        //        if (p.Type == PrimitiveType.Sphere) {
        //            p1 = p.Center[axis] - p.Radius;
        //            p2 = p.Center[axis] + p.Radius;
        //            if ((p1 >= pos1) && (p1 <= pos2)) InsertSplitPos( p1 );
        //            if ((p2 >= pos1) && (p2 <= pos2)) InsertSplitPos( p2 );
        //        }
        //        else {
        //            for (int i = 0; i < 3; i++ ) {
        //                p1 = p.GetVertex(i).Position[axis];
        //                if ((p1 >= pos1) && (p1 <= pos2)) InsertSplitPos( p1 );
        //            }
        //        }
        //        l = l.Next;
        //    }
        //    // determine n1count / n2count for each split position
        //    AxisAlignedBox b1 = null, b2 = null, b3, b4;
        //    b3 = box;
        //    b4 = box;
        //    SplitList splist = _list;
        //    double b3p1 = b3.Position[axis];
        //    double b4p2 = b4.Position[axis] + b4.Size[axis];
        //    while (splist != null) {
        //        b4.Position[axis] = splist.SplitPos;
        //        b4.Size[axis] = pos2 - splist.SplitPos;
        //        b3.Size[axis] = splist.SplitPos - pos1;
        //        double b3p2 = b3.Position[axis] + b3.Size[axis];
        //        double b4p1 = b4.Position[axis];
        //        for (int i = 0; i < prims; i++) {
        //            if (pright[i]) {
        //                Primitive p = parray[i];
        //                if ((eleft[i] <= b3p2) && (eright[i] >= b3p1))
        //                    if (p.IntersectBox(b3))
        //                        splist.N1Count++;
        //                if ((eleft[i] <= b4p2) && (eright[i] >= b4p1))
        //                    if (p.IntersectBox(b4))
        //                        splist.N2Count++;
        //                    else
        //                        pright[i] = false;
        //            }
        //            else
        //                splist.N1Count++;
        //        }
        //        splist = splist.Next;
        //    }
        //    // calculate surface area for current node
        //    double SAV = 0.5f / (box.W * box.D + box.W * box.H + box.D * box.H);
        //    // calculate cost for not splitting
        //    double Cleaf = prims * 1.0f;
        //    // determine optimal split plane position
        //    splist = _list;
        //    double lowcost = 10000;
        //    double bestpos = 0;
        //    while (splist != null) {
        //        // calculate child node extends
        //        b4.Position[axis] = splist.SplitPos;
        //        b4.Size[axis] = pos2 - splist.SplitPos;
        //        b3.Size[axis] = splist.SplitPos - pos1;
        //        // calculate child node cost
        //        double SA1 = 2 * (b3.W * b3.D + b3.W * b3.H + b3.D * b3.H);
        //        double SA2 = 2 * (b4.W * b4.D + b4.W * b4.H + b4.D * b4.H);
        //        double splitcost = 0.3f + 1.0f * (SA1 * SAV * splist.N1Count + SA2 * SAV * splist.N2Count);
        //        // update best cost tracking variables
        //        if (splitcost < lowcost) {
        //            lowcost = splitcost;
        //            bestpos = splist.SplitPos;
        //            b1 = b3;
        //            b2 = b4;
        //        }
        //        splist = splist.Next;
        //    }
        //    if (lowcost > Cleaf)
        //        return;
        //    node.SplitPosition = bestpos;
        //    // construct child nodes
        //    KdTreeNode tmpLeft = new KdTreeNode();
        //    KdTreeNode tmpRight = new KdTreeNode();
        //    int n1count = 0, n2count = 0, total = 0;
        //    // assign primitives to both sides
        //    double b1p1 = b1.Position[axis];
        //    double b2p2 = b2.Position[axis] + b2.Size[axis];
        //    double b1p2 = b1.Position[axis] + b1.Size[axis];
        //    double b2p1 = b2.Position[axis];
        //    for ( int i = 0; i < prims; i++ ) {
        //        Primitive p = parray[i];
        //        total++;
        //        if (eleft[i] <= b1p2 && eright[i] >= b1p1) {
        //            if (p.IntersectBox(b1)) {
        //                tmpLeft.Add(p);
        //                n1count++;
        //            }
        //        }
        //        if (eleft[i] <= b2p2 && eright[i] >= b2p1) {
        //            if (p.IntersectBox(b2)) {
        //                tmpRight.Add(p);
        //                n2count++;
        //            }
        //        }
        //    }
        //    node.List = null;
        //    if (n1count > 0) node.Left = tmpLeft;
        //    if (n2count > 0) node.Right = tmpRight;
        //    if (depth < Constants.MaxTreeDepth) {
        //        if (n1count > 2) Subdivide(tmpLeft, b1, depth + 1, n1count);
        //        if (n2count > 2) Subdivide(tmpRight, b2, depth + 1, n2count);
        //    }
        //}
        public void Subdivide(KdTreeNode node, AxisAlignedBox box, int depth, int prims)
        {
            // recycle used split list nodes
            _sortedList = null;

            // determine split axis
            Vector3D s = box.Size;
            if ((s.X >= s.Y) && (s.X >= s.Z))
                node.Axis = 0;
            else if ((s.Y >= s.X) && (s.Y >= s.Z))
                node.Axis = 1;

            int axis = node.Axis;
            // make a list of the split position candidates
            ObjectList l = node.List;
            double p1, p2;
            double pos1 = box.Position[axis];
            double pos2 = box.Position[axis] + box.Size[axis];

            bool[] pright = new bool[prims];
            double[] eleft = new double[prims];
            double[] eright = new double[prims];
            Primitive[] parray = new Primitive[prims];

            int aidx = 0;
            while (l != null) {
                parray[aidx] = l.Primitive;
                Primitive p = parray[aidx];
                pright[aidx] = true;
                p.CalculateRange(ref eleft[aidx], ref eright[aidx], axis);
                aidx++;

                if (p.Type == PrimitiveType.Sphere) {
                    p1 = p.Center[axis] - p.Radius;
                    p2 = p.Center[axis] + p.Radius;
                    if ((p1 >= pos1) && (p1 <= pos2)) InsertSplitPos(p1);
                    if ((p2 >= pos1) && (p2 <= pos2)) InsertSplitPos(p2);
                }
                else {
                    for (int i = 0; i < 3; i++) {
                        p1 = p.GetVertex(i).Position[axis];
                        if ((p1 >= pos1) && (p1 <= pos2)) InsertSplitPos(p1);
                    }
                }
                l = l.Next;
            }
            // determine n1count / n2count for each split position
            AxisAlignedBox b1 = null, b2 = null, b3, b4;
            b3 = box;
            b4 = box;

            double b3p1 = b3.Position[axis];
            double b4p2 = b4.Position[axis] + b4.Size[axis];

            if (_sortedList == null)
                return;

            foreach (KeyValuePair<double, SplitListItem> pair in _sortedList) {
                SplitListItem spListItem = pair.Value;

                b4.Position[axis] = spListItem.SplitPos;
                b4.Size[axis] = pos2 - spListItem.SplitPos;
                b3.Size[axis] = spListItem.SplitPos - pos1;
                double b3p2 = b3.Position[axis] + b3.Size[axis];
                double b4p1 = b4.Position[axis];
                for (int i = 0; i < prims; i++) {
                    if (pright[i]) {
                        Primitive p = parray[i];
                        if ((eleft[i] <= b3p2) && (eright[i] >= b3p1))
                            if (p.IntersectBox(b3))
                                spListItem.N1Count++;

                        if ((eleft[i] <= b4p2) && (eright[i] >= b4p1))
                            if (p.IntersectBox(b4))
                                spListItem.N2Count++;
                            else
                                pright[i] = false;
                    }
                    else
                        spListItem.N1Count++;
                }
            }

            // calculate surface area for current node
            double SAV = 0.5f / (box.W * box.D + box.W * box.H + box.D * box.H);
            // calculate cost for not splitting
            double Cleaf = prims * 1.0f;

            // determine optimal split plane position
            double lowcost = 10000;
            double bestpos = 0;

            foreach (KeyValuePair<double, SplitListItem> pair in _sortedList) {
                SplitListItem spListItem = pair.Value;

                // calculate child node extends
                b4.Position[axis] = spListItem.SplitPos;
                b4.Size[axis] = pos2 - spListItem.SplitPos;
                b3.Size[axis] = spListItem.SplitPos - pos1;
                // calculate child node cost
                double SA1 = 2 * (b3.W * b3.D + b3.W * b3.H + b3.D * b3.H);
                double SA2 = 2 * (b4.W * b4.D + b4.W * b4.H + b4.D * b4.H);
                double splitcost = 0.3f + 1.0f * (SA1 * SAV * spListItem.N1Count + SA2 * SAV * spListItem.N2Count);
                // update best cost tracking variables
                if (splitcost < lowcost) {
                    lowcost = splitcost;
                    bestpos = spListItem.SplitPos;
                    b1 = b3;
                    b2 = b4;
                }
            }

            if (lowcost > Cleaf)
                return;

            node.SplitPosition = bestpos;
            // construct child nodes
            KdTreeNode tmpLeft = new KdTreeNode();
            KdTreeNode tmpRight = new KdTreeNode();
            int n1count = 0, n2count = 0, total = 0;
            // assign primitives to both sides
            double b1p1 = b1.Position[axis];
            double b2p2 = b2.Position[axis] + b2.Size[axis];
            double b1p2 = b1.Position[axis] + b1.Size[axis];
            double b2p1 = b2.Position[axis];
            for (int i = 0; i < prims; i++) {
                Primitive p = parray[i];
                total++;
                if (eleft[i] <= b1p2 && eright[i] >= b1p1) {
                    if (p.IntersectBox(b1)) {
                        tmpLeft.Add(p);
                        n1count++;
                    }
                }
                if (eleft[i] <= b2p2 && eright[i] >= b2p1) {
                    if (p.IntersectBox(b2)) {
                        tmpRight.Add(p);
                        n2count++;
                    }
                }
            }

            node.List = null;
            if (n1count > 0) node.Left = tmpLeft;
            if (n2count > 0) node.Right = tmpRight;

            if (depth < Constants.MaxTreeDepth) {
                if (n1count > 2) Subdivide(tmpLeft, b1, depth + 1, n1count);
                if (n2count > 2) Subdivide(tmpRight, b2, depth + 1, n2count);
            }
        }
Beispiel #3
0
        public bool InitScene()
        {
            Material mat;
            int x;
            Vector3D p1, p2;
            switch (_state) {
                case 0:
                    //constructing geometry...
                    break;
                case 1:
                    // ground plane
                    mat = new Material();
                    //Changed to water
                    mat.SetParameters(0.3, 0.7, new Color3D(0, 128, 255), 0.2, 0.1);
                    mat.RefractionIndex = 1.33157;
                    mat.DiffuseReflection = .1;
                    //mat.SetParameters(0.0f, 0.0f, new Color3D(0.4f, 0.3f, 0.3f), 1.0f, 0.0f);
                    AddPlane(new Vector3D(-13, -4.4f, -5.5f), new Vector3D(13, -4.4f, -5.5f),
                              new Vector3D(13, -4.4f, 29), new Vector3D(-13, -4.4f, 29), mat);
                    // back plane
                    mat = new Material();
                    mat.SetParameters(0.0, 0.0, new Color3D(0.5, 0.3, 0.5), 0.6, 0.0);
                    AddPlane(new Vector3D(-13, -4.4f, 12), new Vector3D(13, -4.4f, 12),
                              new Vector3D(13, 7.4f, 12), new Vector3D(-13, 7.4f, 12), mat);

                    //AddPlane(new Vector3D(-13, -4.4f, 8), new Vector3D(13, -4.4f, 16),
                    //          new Vector3D(13, 7.4f, 16), new Vector3D(-13, 7.4f, 8), mat);

                    // ceiling plane
                    mat = new Material();
                    mat.SetParameters(0.0, 0.0, new Color3D(0.4, 0.7, 0.7), 0.5, 0.0);
                    AddPlane(new Vector3D(13, 7.4f, -5.5f), new Vector3D(-13, 7.4f, -5.5f),
                              new Vector3D(-13, 7.4f, 29), new Vector3D(13, 7.4f, 29), mat);

                    // big sphere
                    // m_Primitive[m_Primitives] = new Primitive( Primitive::SPHERE, vector3( 2, 0.8f, 3 ), 2.5f );
                    // m_Primitive[m_Primitives++]->GetMaterial()->SetParameters( 0.2f, 0.8f, Color( 0.7f, 0.7f, 1.0f ), 0.2f, 0.8f );
                    // small sphere
                    Primitive p = new Primitive(PrimitiveType.Sphere, new Vector3D(-5.5f, -0.5f, 7), 2);
                    p.Material.SetParameters(0.5f, 0.0f, new Color3D(.7f, .7f, 1), .1f, .8f);
                    Primitives.Add(p);

                    Light l;
                    /*
                    // area lights
                    l = new Light(Light.LightType.Area, new Vector3D(-1, 6, 4), new Vector3D(1, 6, 4), new Vector3D(-1, 6, 6), new Color3D(0.7f, 0.7f, 0.7f));
                    Lights.Add(l);
                    l = new Light(Light.LightType.Area, new Vector3D(-1, 6, -1), new Vector3D(1, 6, -1), new Vector3D(-1, 6, 1), new Color3D(0.7f, 0.7f, 0.7f));
                    Lights.Add(l);
                    */

                    // point lights
                    l = new Light(Light.LightType.Point, new Vector3D(0, 5, 5), new Color3D(0.4f, 0.4f, 0.4f));
                    Lights.Add(l);
                    l = new Light(Light.LightType.Point, new Vector3D(-3, 5, 1), new Color3D(0.6f, 0.6f, 0.8f));
                    Lights.Add(l);

                    // extra sphere
                    p = new Primitive(PrimitiveType.Sphere, new Vector3D(-1.5f, -3.8f, 1), 1.5f);
                    p.Material.SetParameters(0.0f, 0.8f, new Color3D(1.0f, 0.4f, 0.4f), 0.2f, 0.8f);
                    Primitives.Add(p);

                    // grid
                    for ( x = 0; x < 8; x++ ) {
                        for ( int y = 0; y < 7; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-4.5f + x*1.5f, -4.3f + y*1.5f, 10), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    for ( x = 0; x < 8; x++ ) {
                        for ( int y = 0; y < 8; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-4.5f + x*1.5f, -4.3f, 10.0f - y*1.5f), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    for ( x = 0; x < 16; x++ ) {
                        for ( int y = 0; y < 8; y++ ) {
                            p = new Primitive(PrimitiveType.Sphere, new Vector3D(-8.5f + x*1.5f, 4.3f, 10.0f - y), 0.3f);
                            p.Material.SetParameters(0.0f, 0.0f, new Color3D(0.3f, 1.0f, 0.4f), 0.6f, 0.6f);
                            Primitives.Add(p);
                        }
                    }
                    mat = new Material();
                    mat.SetParameters( 0.9f, 0, new Color3D( 0.9f, 0.9f, 1 ), 0.3f, 0.7f );
                    mat.RefractionIndex = 1.3f;
                    // mat->SetTexture( new Texture( "textures/wood.tga" ) );
                    //Load3DS("meshes\\knot.3ds", mat, new Vector3D(0, 0.5f, 4), 6);
                    break;
                case 2:
                    //building kdtree, please wait
                    break;
                case 3:
                    //Build the KD-tree
                    p1 = new Vector3D(-14, -6, -6);
                    p2 = new Vector3D(14, 8, 30);
                    Extends = new AxisAlignedBox(p1, p2 - p1);
                    KdTree = new KdTree();
                    KdTree.Build(this);
                    break;
                default:
                    return true; //done initializing
            }

            _state++;
            return false; //still initializing
        }