void _AssembleShape(ShapeStream shapeStream)
        {
            int i;

            // get counts...
            int numNodes = shapeStream.ReadS32();
            int numObjects = shapeStream.ReadS32();
            int numDecals = shapeStream.ReadS32();
            int numSubShapes = shapeStream.ReadS32();
            int numIflMaterials = shapeStream.ReadS32();
            int numNodeRots = shapeStream.ReadS32();
            int numNodeTrans = shapeStream.ReadS32();
            int numNodeUniformScales = shapeStream.ReadS32();
            int numNodeAlignedScales = shapeStream.ReadS32();
            int numNodeArbitraryScales = shapeStream.ReadS32();
            int numGroundFrames = shapeStream.ReadS32();
            int numObjectStates = shapeStream.ReadS32();
            int numDecalStates = shapeStream.ReadS32();
            int numTriggers = shapeStream.ReadS32();
            int numDetails = shapeStream.ReadS32();
            int numMeshes = shapeStream.ReadS32();
            int numNames = shapeStream.ReadS32();
            _shape.SmallestVisibleSize = shapeStream.ReadF32();
            _shape.SmallestVisibleDL = shapeStream.ReadS32();

            shapeStream.CheckGuard();

            // get bounds...
            _shape.Radius = shapeStream.ReadF32();
            _shape.TubeRadius = shapeStream.ReadF32();
            shapeStream.ReadPoint3F(ref _shape.Center);
            shapeStream.ReadPoint3F(ref _shape.Bounds.Min);
            shapeStream.ReadPoint3F(ref _shape.Bounds.Max);

            shapeStream.CheckGuard();

            // allocate some storage
            _shape.SubShapeFirstTranslucentObject = new int[numSubShapes];

            // Read in nodes
            _shape.Nodes = new Node[numNodes];
            for (i = 0; i < numNodes; i++)
            {
                _shape.Nodes[i].NameIndex = shapeStream.ReadS32();
                _shape.Nodes[i].ParentIndex = shapeStream.ReadS32();
                _shape.Nodes[i].FirstObject = shapeStream.ReadS32();
                _shape.Nodes[i].FirstChild = shapeStream.ReadS32();
                _shape.Nodes[i].NextSibling = shapeStream.ReadS32();
            }

            shapeStream.CheckGuard();

            // Read in objects
            _shape.Objects = new Object[numObjects];
            for (i = 0; i < numObjects; i++)
            {
                _shape.Objects[i].NameIndex = shapeStream.ReadS32();
                _shape.Objects[i].MeshCount = shapeStream.ReadS32();
                _shape.Objects[i].FirstMesh = shapeStream.ReadS32();
                _shape.Objects[i].NodeIndex = shapeStream.ReadS32();
                _shape.Objects[i].NextSibling = shapeStream.ReadS32();
                shapeStream.ReadS32(); // decals are deprecated
            }

            shapeStream.CheckGuard();

            // should be no decals, but Read them in and ignore if they are there
            shapeStream.ReadS32s(numDecals * 5);

            shapeStream.CheckGuard();

            // ifl materials
            _shape.IflMaterials = new IflMaterial[numIflMaterials];
            for (i = 0; i < numIflMaterials; i++)
            {
                _shape.IflMaterials[i].NameIndex = shapeStream.ReadS32();
                _shape.IflMaterials[i].MaterialSlot = shapeStream.ReadS32();
                _shape.IflMaterials[i].FirstFrame = shapeStream.ReadS32();
                _shape.IflMaterials[i].FirstFrameOffTimeIndex = shapeStream.ReadS32();
                _shape.IflMaterials[i].FrameCount = shapeStream.ReadS32();
            }

            shapeStream.CheckGuard();

            // subshape first lists...
            _shape.SubShapeFirstNode = shapeStream.ReadS32s(numSubShapes);
            _shape.SubShapeFirstObject = shapeStream.ReadS32s(numSubShapes);
            shapeStream.ReadS32s(numSubShapes); // no decal support

            shapeStream.CheckGuard();

            // subshape num lists...
            _shape.SubShapeNodeCount = shapeStream.ReadS32s(numSubShapes);
            _shape.SubShapeObjectCount = shapeStream.ReadS32s(numSubShapes);
            shapeStream.ReadS32s(numSubShapes); // no decal support

            shapeStream.CheckGuard();

            // get default rotations and translations
            _shape.DefaultRotations = shapeStream.ReadQuat16s(numNodes);
            _shape.DefaultTranslations = shapeStream.ReadPoint3Fs(numNodes);

            // get _sequence rotation and translations
            _shape.NodeTranslations = shapeStream.ReadPoint3Fs(numNodeTrans);
            _shape.NodeRotations = shapeStream.ReadQuat16s(numNodeRots);

            shapeStream.CheckGuard();

            // more node _sequence data...Scale
            _shape.NodeUniformScales = shapeStream.ReadF32s(numNodeUniformScales);
            _shape.NodeAlignedScales = shapeStream.ReadPoint3Fs(numNodeAlignedScales);
            _shape.NodeArbitraryScaleFactors = shapeStream.ReadPoint3Fs(numNodeArbitraryScales);
            _shape.NodeArbitraryScaleRotations = shapeStream.ReadQuat16s(numNodeArbitraryScales);

            shapeStream.CheckGuard();

            // ground _sequence data
            _shape.GroundTranslations = shapeStream.ReadPoint3Fs(numGroundFrames);
            _shape.GroundRotations = shapeStream.ReadQuat16s(numGroundFrames);

            shapeStream.CheckGuard();

            // object states
            _shape.ObjectStates = new ObjectState[numObjectStates];
            for (i = 0; i < numObjectStates; i++)
            {
                _shape.ObjectStates[i].Visibility = shapeStream.ReadF32();
                _shape.ObjectStates[i].FrameIndex = shapeStream.ReadS32();
                _shape.ObjectStates[i].MaterialFrameIndex = shapeStream.ReadS32();

            }

            shapeStream.CheckGuard();

            shapeStream.ReadS32s(numDecalStates); // no decal support

            shapeStream.CheckGuard();

            // frame triggers
            _shape.Triggers = new Trigger[numTriggers];
            for (i = 0; i < numTriggers; i++)
            {
                _shape.Triggers[i].State = shapeStream.ReadS32();
                _shape.Triggers[i].Pos = shapeStream.ReadF32();
            }

            shapeStream.CheckGuard();

            // details
            _shape.Details = new Detail[numDetails];
            for (i = 0; i < numDetails; i++)
            {
                _shape.Details[i].NameIndex = shapeStream.ReadS32();
                _shape.Details[i].SubShapeNumber = shapeStream.ReadS32();
                _shape.Details[i].ObjectDetailNumber = shapeStream.ReadS32();
                _shape.Details[i].PixelSize = shapeStream.ReadF32();
                _shape.Details[i].AverageError = shapeStream.ReadF32();
                _shape.Details[i].MaxError = shapeStream.ReadF32();
                _shape.Details[i].PolyCount = shapeStream.ReadS32();

                if (Shape.ReadVersion >= 26)
                {
                    shapeStream.ReadU32s(6);
                }
            }

            shapeStream.CheckGuard();

            // Read in meshes...this is much simpler than in C++ code because
            // we never skip a detail level on load
            _shape.Meshes = new Mesh[numMeshes];
            for (i = 0; i < numMeshes; i++)
            {
                Mesh.MeshEnum meshType = (Mesh.MeshEnum)shapeStream.ReadS32();
                _shape.Meshes[i] = _AssembleMesh(shapeStream, meshType);
            }

            shapeStream.CheckGuard();

            _shape.Names = new String[numNames];
            for (i = 0; i < numNames; i++)
            {
                _shape.Names[i] = shapeStream.ReadCString();
            }

            shapeStream.CheckGuard();
        }