Exemplo n.º 1
0
        protected void EnsureObjectsCreated()
        {
            ClearCreatedObjects();
            Texture prototypeTexture = null;
            if (useTextures)
            {
                prototypeMaterial = MaterialManager.Instance.Load("barrel.barrel");
                if (uniqueTextures)
                    prototypeTexture = TextureManager.Instance.Load("blank.dds");
            }
            else
                prototypeMaterial = MaterialManager.Instance.Load("unit_box.unit_box");
            prototypeMaterial.Compile();
            if (objectCount == 0)
                return;
            int materialCount = (animatedObjects ? 0 :
                                 (numObjectsSharingMaterial == 0 ? objectCount :
                                  (numObjectsSharingMaterial >= objectCount ? 1 :
                                   (objectCount + numObjectsSharingMaterial - 1) / numObjectsSharingMaterial)));
            materialCountLabel.Text = "Material Count: " + materialCount;
            if (whichObjects == WhichObjectsEnum.woPlane || whichObjects == WhichObjectsEnum.woRandom) {
                Mesh plane = meshes[(int)WhichObjectsEnum.woPlane];
                if (plane != null)
                    plane.Unload();
                // Create the plane
                float planeSide = 1000f;
                int planeUnits = Int32.Parse(planeUnitsTextBox.Text);
                plane = MeshManager.Instance.CreatePlane("testerPlane", new Plane(Vector3.UnitZ, Vector3.Zero), planeSide, planeSide, planeUnits, planeUnits, true,
                    1, planeSide / planeUnits, planeSide / planeUnits, Vector3.UnitY);
                meshes[(int)WhichObjectsEnum.woPlane] = plane;
            }
            // Create the new materials
            for (int i = 0; i < materialCount; i++)
            {
                Material mat = prototypeMaterial.Clone("mat" + i);
                Pass p = mat.GetTechnique(0).GetPass(0);
                if (!animatedObjects && uniqueTextures) {
                    Texture t = prototypeTexture;
                    Texture texture = TextureManager.Instance.CreateManual("texture" + i, t.TextureType, t.Width, t.Height, t.NumMipMaps, t.Format, t.Usage);
                    textureList.Add(texture);
                    p.CreateTextureUnitState(texture.Name);
                }
                // Make the materials lovely shades of blue
                p.Ambient = new ColorEx(1f, .2f, .2f, (1f / materialCount) * i);
                p.Diffuse = new ColorEx(p.Ambient);
                p.Specular = new ColorEx(1f, 0f, 0f, 0f);
                materialList.Add(mat);
            }

            // Create the entities and scene nodes
            for (int i=0; i<objectCount; i++) {
                Mesh mesh = selectMesh();
                Material mat = null;
                if (materialCount > 0)
                    mat = materialList[i % materialCount];
                Entity entity = scene.CreateEntity("entity" + i, mesh);
                if (animatedObjects) {
                    string[] visibleSubs = visibleSubMeshes[(int)whichObjects - (int) WhichObjectsEnum.woZombie];
                    for (int j = 0; j < entity.SubEntityCount; ++j) {
                        SubEntity sub = entity.GetSubEntity(j);
                        bool visible = false;
                        foreach (string s in visibleSubs) {
                            if (s == sub.SubMesh.Name) {
                                visible = true;
                                break;
                            }
                        }
                        sub.IsVisible = visible;
                        if (visible)
                            totalVertexCount += sub.SubMesh.VertexData.vertexCount;
                    }
                }
                else {
                    if (mesh.SharedVertexData != null)
                        totalVertexCount += mesh.SharedVertexData.vertexCount;
                    else {
                        for (int j=0; j<mesh.SubMeshCount; j++) {
                            SubMesh subMesh = mesh.GetSubMesh(j);
                            totalVertexCount += subMesh.VertexData.vertexCount;
                        }
                    }
                }
                if (animatedObjects && animateCheckBox.Checked) {
                    AnimationState currentAnimation = entity.GetAnimationState(GetAnimationName());
                    currentAnimation.IsEnabled = true;
                    if (!animationInitialized)
                    {
                        currentAnimationLength = entity.GetAnimationState(GetAnimationName()).Length;
                        animationInitialized = true;
                    }
                }
                if (mat != null)
                    entity.MaterialName = mat.Name;
                entityList.Add(entity);
                SceneNode node = scene.RootSceneNode.CreateChildSceneNode();
                sceneNodeList.Add(node);
                node.AttachObject(entity);
                node.Position = new Vector3(randomCoord(), randomCoord(), randomCoord());
                if (randomSizes)
                    node.ScaleFactor = Vector3.UnitScale * randomScale();
                else if (randomScales)
                    node.ScaleFactor = new Vector3(randomScale(), randomScale(), randomScale());
                else
                    node.ScaleFactor = Vector3.UnitScale * 1f;
                if (randomOrientations)
                {
                    Vector3 axis = new Vector3((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble());
                    node.Orientation = Vector3.UnitY.GetRotationTo(axis.ToNormalized());
                }
                else
                    node.Orientation = Quaternion.Identity;
            }
        }
        // Decide, based on the normal to the collision object, if the
        // moving object can slide across the obstacle, and if it can,
        // return the updated displacement.  This displacement may in fact
        // run into _another_ obstacle, however, so the call must again
        // run the collision test.
        private static bool DecideToSlide(MovingObject mo, Vector3 mobNodePosition, 
										  CollisionParms parms, ref Vector3 displacement)
        {
            Vector3 normDisplacement = displacement.ToNormalized();
            Vector3 normObstacle = parms.normObstacle.ToNormalized();
            if (MO.DoLog) {
                MO.Log(" DecideToSlide: normObstacle {0}, normDisplacement {1}",
                       normObstacle.ToString(), normDisplacement.ToString());
                MO.Log(" DecideToSlide: displacement {0}", displacement);
            }
            // First we find the angle between the normal and the
            // direction of travel, and reject the displacement if
            // it's too small
            float slideAngle = (NormalizeAngle((float)Math.Acos((double)normDisplacement.Dot(normObstacle))) -
                                .5f * (float)Math.PI);
            if (Math.Abs(slideAngle) > CollisionAPI.MinSlideAngle) {
                if (MO.DoLog)
                    MO.Log(" After collision, displacement {0}, won't slide because slideAngle {1} > minSlideAngle {2}",
                           displacement.ToString(), slideAngle, CollisionAPI.MinSlideAngle);
                displacement = Vector3.Zero;
                return false;
            }
            // Then we find the angle with the y axis, and reject the
            // displacement if it's too steep
            float verticalAngle = NormalizeAngle((float)Math.Acos((double)normDisplacement[1]));
            if (Math.Abs(verticalAngle) > CollisionAPI.MaxVerticalAngle) {
                if (MO.DoLog)
                    MO.Log(" After collision, displacement {0}, won't slide because verticalAngle {1} <= maxVerticalAngle {2}",
                           displacement.ToString(), verticalAngle, CollisionAPI.MaxVerticalAngle);
                displacement = Vector3.Zero;
                return false;
            }
            // Else, we can slide, so return a displacement that
            // points in the direction we're sliding, and has length
            // equal to a constant times the displacement length

            // Rotate displacement so that it's 90 degress from the
            // obstacle normal
            Vector3 cross = normObstacle.Cross(normDisplacement);
            Quaternion q = Quaternion.FromAngleAxis(.5f * (float)Math.PI, cross);
            Matrix4 transform = q.ToRotationMatrix();
            Vector3 transformedNorm = transform * normObstacle.ToNormalized();
            float len = displacement.Length;
            displacement = transformedNorm * len;
            // 			Vector3 alignedPart = normObstacle * (normObstacle.Dot(displacement));
            // 			displacement -= alignedPart;

            Vector3 p = mobNodePosition + displacement;
            float h = worldManager.GetHeightAt(p);
            // If sliding would put us below ground, limit the displacement
            if (h > p.y) {
                if (MO.DoLog)
                    MO.Log(" Sliding up because terrain height is {0} is higher than projected mobNode height {1}",
                           h, p.y);
             				displacement.y += h - p.y;
            }
            if (MO.DoLog) {
                MO.Log(" Exiting DecideToSlide, sliding displacement {0}, slideAngle {1},  verticalAngle {2}",
                       displacement.ToString(), slideAngle, verticalAngle);
                MO.Log(" Exiting DecideToSlide, cross product {0}, quaternion {1}, transformedNorm {2}",
                       cross, q, transformedNorm);
            // 				MO.Log(" Exiting DecideToSlide, alignedPart {0}", alignedPart);
            }
            return true;
        }
Exemplo n.º 3
0
        /// <summary>
        /// This method transforms a Node by a weighted amount from its
        ///	initial state. If weighted transforms have already been applied, 
        ///	the previous transforms and this one are blended together based
        /// on their relative weight. This method should not be used in
        ///	combination with the unweighted rotate, translate etc methods.
        /// </summary>
        /// <param name="weight"></param>
        /// <param name="translate"></param>
        /// <param name="rotate"></param>
        /// <param name="scale"></param>
        internal virtual void WeightedTransform(float weight, ref Vector3 translate, ref Quaternion rotate, ref Vector3 scale, bool lookInMovementDirection)
        {
            // If no previous transforms, we can just apply
            if (accumAnimWeight == 0.0f) {
                rotationFromInitial = rotate;
                translationFromInitial = translate;
                scaleFromInitial = scale;
                accumAnimWeight = weight;
            }
            else {
                // Blend with existing
                float factor = weight / (accumAnimWeight + weight);

                // translationFromInitial += (translate - translationFromInitial) * factor;
                Vector3 tmp = Vector3.Zero;
                translationFromInitial.x += (translate.x - translationFromInitial.x) * factor;
                translationFromInitial.y += (translate.y - translationFromInitial.y) * factor;
                translationFromInitial.z += (translate.z - translationFromInitial.z) * factor;

                Quaternion result = Quaternion.Zero;
                Quaternion.SlerpRef(ref result, factor, ref rotationFromInitial, ref rotate, false);
                rotationFromInitial = result;

                // For scale, find delta from 1.0, factor then add back before applying
                scaleFromInitial.x *= 1.0f + (scale.x - 1.0f) * factor;
                scaleFromInitial.y *= 1.0f + (scale.y - 1.0f) * factor;
                scaleFromInitial.z *= 1.0f + (scale.z - 1.0f) * factor;
                accumAnimWeight += weight;
            }

            // Update final based on bind position + offsets
            // orientation = initialOrientation * rotationFromInitial;
            Quaternion.MultiplyRef(ref orientation, ref initialOrientation, ref rotationFromInitial);
            // position = initialPosition + translationFromInitial;
            position.x = initialPosition.x + translationFromInitial.x;
            position.y = initialPosition.y + translationFromInitial.y;
            position.z = initialPosition.z + translationFromInitial.z;
            // scale = initialScale * scaleFromInitial;
            scale.x = initialScale.x * scaleFromInitial.x;
            scale.y = initialScale.y * scaleFromInitial.y;
            scale.z = initialScale.z * scaleFromInitial.z;
            if(lookInMovementDirection)
                orientation = -Vector3.UnitX.GetRotationTo(translate.ToNormalized());

            NeedUpdate();
        }