/// <summary> /// Adds all of the geometry used by a model component to the static geometry. /// This is used by the ModelComponent. /// </summary> public void Add(ModelComponent mc, ThingBlock template, ModelBlock block, ThingDefinition def) { // if the model detail option is low and this model wants imposters, don't even make any static geometry of it if (Options.ModelDetail == ModelDetailOption.Low) { if (def.GetBoolProperty("Imposters", false)) return; } var sceneMgr = LKernel.GetG<SceneManager>(); string meshName = block.GetStringProperty("mesh", null); // map region goes first string sgeomName = template.GetStringProperty("MapRegion", "(Default)"); // static group can override map region sgeomName = block.GetStringProperty("StaticGroup", sgeomName); Entity ent; // get our entity if it already exists if (!ents.TryGetValue(meshName, out ent)) { // getting the entity was not successful, so we have to create it ent = sceneMgr.CreateEntity(meshName + mc.ID, meshName); string material; if (block.StringTokens.TryGetValue("material", out material)) ent.SetMaterialName(material); ents.Add(meshName, ent); } Vector3 pos; // two ways to get the position // inherit it from the lthing, the default (if we were using nodes, this would be the default too) if (block.GetBoolProperty("InheritOrientation", true)) { pos = (mc.Owner.SpawnOrientation * block.GetVectorProperty("position", Vector3.ZERO)) + template.VectorTokens["position"]; } // or we can choose not to inherit it for whatever reason else { pos = block.GetVectorProperty("position", Vector3.ZERO) + template.VectorTokens["position"]; } Quaternion orient = block.GetQuatProperty("orientation", Quaternion.IDENTITY) * template.GetQuatProperty("orientation", Quaternion.IDENTITY); Vector3 sca = block.GetVectorProperty("scale", Vector3.UNIT_SCALE); StaticGeometry sg; if (!sgeoms.TryGetValue(sgeomName, out sg)) { sg = LKernel.GetG<SceneManager>().CreateStaticGeometry(sgeomName); sg.RegionDimensions = regionDimensions; sg.RenderingDistance = 300 / 5f; sgeoms.Add(sgeomName, sg); } sg.AddEntity(ent, pos, orient, sca); }
public void Add(ModelComponent mc, ThingBlock template, ModelBlock block, ThingDefinition def) { // if the model detail option is low and this model wants imposters, don't even make any instanced geometry of it if (Options.ModelDetail == ModelDetailOption.Low) { if (def.GetBoolProperty("Imposters", false)) return; } var sceneMgr = LKernel.GetG<SceneManager>(); string meshName = block.GetStringProperty("mesh", null); string mapRegion = template.GetStringProperty("MapRegion", string.Empty); string key = mapRegion + meshName; // create our entity if it doesn't exist if (!ents.ContainsKey(key)) { Entity ent = sceneMgr.CreateEntity(mc.Name + mc.ID, meshName); ent.SetMaterialName(block.GetStringProperty("Material", string.Empty)); // then add it to our dictionary ents.Add(key, ent); } // get our transforms Vector3 pos; // two ways to get the position // inherit it from the lthing, the default (if we were using nodes, this would be the default too) if (block.GetBoolProperty("InheritOrientation", true)) { pos = (mc.Owner.SpawnOrientation * block.GetVectorProperty("position", Vector3.ZERO)) + template.VectorTokens["position"]; } // or we can choose not to inherit it for whatever reason else { pos = block.GetVectorProperty("position", Vector3.ZERO) + template.VectorTokens["position"]; } Quaternion orient = block.GetQuatProperty("orientation", Quaternion.IDENTITY) * template.GetQuatProperty("orientation", Quaternion.IDENTITY); Vector3 sca = block.GetVectorProperty("scale", Vector3.UNIT_SCALE); // put them in one class Transform trans = new Transform { Position = pos, Orientation = orient, Scale = sca, }; // if the transforms dictionary doesn't contain the mesh yet, add a new one if (!transforms.ContainsKey(key)) { transforms.Add(key, new List<Transform>()); } // then put our transform into the dictionary transforms[key].Add(trans); }
/// <summary> /// Creates a CollisionShape from the ShapeComponents of the given thing. If the shape already exists, we'll just return that instead. /// </summary> public CollisionShape CreateAndRegisterShape(LThing thing, ThingDefinition def) { CollisionShape shape; if (!Shapes.TryGetValue(thing.Name, out shape)) { // create the shape bool forceCompound = def.GetBoolProperty("forcecompound", false); // if we only have one shape we don't have to do as much if (thing.ShapeComponents.Count == 1) { // force us to use a compound shape? if (forceCompound) { CompoundShape comp = new CompoundShape(); comp.AddChildShape(thing.ShapeComponents[0].Transform, CreateShapeForComponent(thing.ShapeComponents[0])); shape = comp; } // one component, no compound is the easiest else { shape = CreateShapeForComponent(thing.ShapeComponents[0]); } } // otherwise, make all of our shapes and stick them in a compound shape else { CompoundShape comp = new CompoundShape(); foreach (ShapeComponent component in thing.ShapeComponents) { comp.AddChildShape(component.Transform, CreateShapeForComponent(component)); } shape = comp; } // then put the shape in our dictionary Shapes.Add(thing.Name, shape); } return shape; }
/// <summary> /// Creates a model component for a Thing. /// </summary> /// <param name="lthing">The Thing this component is attached to</param> /// <param name="template">The template from the Thing</param> /// <param name="block">The block we're creating this component from</param> public ModelComponent(LThing lthing, ThingBlock template, ModelBlock block, ThingDefinition def) { ID = IDs.Incremental; Owner = lthing; var sceneMgr = LKernel.GetG<SceneManager>(); Name = block.GetStringProperty("name", template.ThingName); // set these up here because static/instanced geometry might need them // position SpawnPosition = block.GetVectorProperty("position", Vector3.ZERO); // orientation SpawnOrientation = block.GetQuatProperty("orientation", Quaternion.IDENTITY); // if orientation was not found, we fall back to rotation if (SpawnOrientation == Quaternion.IDENTITY) { Vector3 rot = block.GetVectorProperty("rotation", Vector3.ZERO); if (rot != Vector3.ZERO) SpawnOrientation = rot.DegreeVectorToGlobalQuaternion(); } // scale SpawnScale = block.GetVectorProperty("scale", Vector3.UNIT_SCALE); ThingEnum shad = block.GetEnumProperty("CastsShadows", ThingEnum.Some); // if we're static, set up the static geometry // don't set up static geometry if we want to cast shadows though, since static geometry doesn't work with shadows if ((block.GetBoolProperty("static", false) || def.GetBoolProperty("static", false)) // make static if we never want shadows && (shad == ThingEnum.None // or if the mesh has "some" shadows but we don't want any || (shad == ThingEnum.Some && Options.ShadowDetail == ShadowDetailOption.None) // or if the mesh has "many" shadows but we only want those with "some" || (shad == ThingEnum.Many && Options.ShadowDetail != ShadowDetailOption.Many))) { LKernel.GetG<StaticGeometryManager>().Add(this, template, block, def); Entity = null; } else if (block.GetBoolProperty("instanced", false) || def.GetBoolProperty("instanced", false)) { LKernel.GetG<InstancedGeometryManager>().Add(this, template, block, def); Entity = null; } // for attachments else if (block.GetBoolProperty("Attached", false)) { SetupEntity(sceneMgr, block); SetupAnimation(block); string boneName = block.GetStringProperty("AttachBone", null); int modelComponentID = (int) block.GetFloatProperty("AttachComponentID", null); Quaternion offsetQuat = block.GetQuatProperty("AttachOffsetOrientation", Quaternion.IDENTITY); Vector3 offsetVec = block.GetVectorProperty("AttachOffsetPosition", Vector3.ZERO); lthing.ModelComponents[modelComponentID].Entity.AttachObjectToBone(boneName, Entity, offsetQuat, offsetVec); } // otherwise continue as normal else { Node = lthing.RootNode.CreateChildSceneNode(Name + "Node" + ID); Node.Position = SpawnPosition; Node.Orientation = SpawnOrientation; Node.Scale(SpawnScale); Node.InheritScale = block.GetBoolProperty("InheritScale", true); Node.InheritOrientation = block.GetBoolProperty("InheritOrientation", true); Node.SetInitialState(); // make our entity SetupEntity(sceneMgr, block); SetupAnimation(block); // then attach it to the node! Node.AttachObject(Entity); } }
/// <summary> /// Set up all of the stuff needed before we create our body /// </summary> private void SetUpBodyInfo(ThingDefinition def) { // set up our collision shapes CollisionShape shape = LKernel.GetG<CollisionShapeManager>().CreateAndRegisterShape(this, def); // get the physics type and set up the mass of the body ThingEnum physicsType = def.GetEnumProperty("physics", null); float mass = physicsType.HasFlag(ThingEnum.Static) ? 0 : def.GetFloatProperty("mass", 1); // create our construction info thingy Vector3 inertia; shape.CalculateLocalInertia(mass, out inertia); // if it's static and doesn't have a sound, we don't need a mogre motion state because we'll be disposing of the root node afterwards if (def.GetBoolProperty("Static", false) && SoundComponents == null) MotionState = new DefaultMotionState(); else MotionState = InitializationMotionState; Info = new RigidBodyConstructionInfo(mass, MotionState, shape, inertia); // physics material stuff from a .physmat file string physmat = def.GetStringProperty("PhysicsMaterial", "Default"); LKernel.GetG<PhysicsMaterialFactory>().ApplyMaterial(Info, physmat); // we can override some of them in the .thing file if (def.FloatTokens.ContainsKey("bounciness")) Info.Restitution = def.GetFloatProperty("bounciness", PhysicsMaterial.DEFAULT_BOUNCINESS); if (def.FloatTokens.ContainsKey("friction")) Info.Friction = def.GetFloatProperty("friction", PhysicsMaterial.DEFAULT_FRICTION); if (def.FloatTokens.ContainsKey("angulardamping")) Info.AngularDamping = def.GetFloatProperty("angulardamping", PhysicsMaterial.DEFAULT_ANGULAR_DAMPING); if (def.FloatTokens.ContainsKey("lineardamping")) Info.LinearDamping = def.GetFloatProperty("lineardamping", PhysicsMaterial.DEFAULT_LINEAR_DAMPING); // choose which group to use for a default ThingEnum defaultGroup; if (physicsType.HasFlag(ThingEnum.Dynamic)) defaultGroup = ThingEnum.Default; else if (physicsType.HasFlag(ThingEnum.Static)) defaultGroup = ThingEnum.Environment; else // kinematic defaultGroup = ThingEnum.Default; // collision group ThingEnum collisionGroup = def.GetEnumProperty("CollisionGroup", defaultGroup); PonykartCollisionGroups pcg; if (!Enum.TryParse<PonykartCollisionGroups>(collisionGroup + String.Empty, true, out pcg)) throw new FormatException("Invalid collision group!"); CollisionGroup = pcg; // collides-with group ThingEnum collidesWith = def.GetEnumProperty("CollidesWith", defaultGroup); PonykartCollidesWithGroups pcwg; if (!Enum.TryParse<PonykartCollidesWithGroups>(collidesWith + String.Empty, true, out pcwg)) throw new FormatException("Invalid collides-with group!"); CollidesWith = pcwg; // update the transforms Matrix4 transform = new Matrix4(); transform.MakeTransform(SpawnPosition, SpawnScale, SpawnOrientation); Info.StartWorldTransform = transform; MotionState.WorldTransform = transform; }
/// <summary> /// If this is a static/instanced thing with no ribbons, billboards, or sounds, we can clean up a whole bunch of stuff /// to make it faster for ogre. /// </summary> private void DisposeIfStaticOrInstanced(ThingDefinition def) { if (def.GetBoolProperty("Static", false) || def.GetBoolProperty("Instanced", false)) { if (IsDisposed) return; var sceneMgr = LKernel.GetG<SceneManager>(); // this bool is to check we only fully dispose lthings if ALL of their model components are static/instanced bool removedAllModelComponents = true; // dispose of all of the model components if (ModelComponents != null) { foreach (ModelComponent mc in ModelComponents) { if (mc.Entity == null) { mc.Dispose(); } else { removedAllModelComponents = false; } } } // if we have no ribbons, billboards, or sounds, we can get rid of the root node if (removedAllModelComponents && RibbonComponents == null && BillboardSetComponents == null && SoundComponents == null) { // if we have no shapes, we can get rid of everything if (ShapeComponents == null/*.Count == 0*/) { Dispose(true); } // but otherwise we can still get rid of the root scene node else { sceneMgr.DestroySceneNode(RootNode); RootNode.Dispose(); RootNode = null; } } } }
/// <summary> /// Creates the body and makes it static/kinematic if specified. /// </summary> private void CreateBody(ThingDefinition def) { Body = new RigidBody(Info); // stick on our flags ThingEnum te = def.GetEnumProperty("physics", null); if (te.HasFlag(ThingEnum.Static)) Body.CollisionFlags |= CollisionFlags.StaticObject; else if (te.HasFlag(ThingEnum.Kinematic)) Body.CollisionFlags |= CollisionFlags.KinematicObject; if (def.GetBoolProperty("CollisionEvents", false)) Body.CollisionFlags |= CollisionFlags.CustomMaterialCallback; if (def.GetBoolProperty("DisableVisualization", false)) Body.CollisionFlags |= CollisionFlags.DisableVisualizeObject; Body.WorldTransform = Info.StartWorldTransform; LKernel.GetG<PhysicsMain>().World.AddRigidBody(Body, CollisionGroup, CollidesWith); if (def.GetBoolProperty("Deactivated", false)) Body.ForceActivationState(ActivationState.WantsDeactivation); }