public Scene() { Primitives = new List<Primitive>(); Lights = new List<Light>(); Extends = new AxisAlignedBox(); _state = 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); } }
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 }