How to recreate XNA's SkinnedModelProcessor - c#

I have a model that is rigged and skinned and I would like to be able to move the bones programmatically (as opposed to a preset animation stored int he fbx file)
I can load the model fine, and see that the bones have been loaded, but changing the bone transforms doesnt seem to affect the rendered model.
I am looking at the sample project here:
http://create.msdn.com/en-US/education/catalog/sample/skinned_model
It looks like it uses an extended ModelProcessor (aka SkinnedModelProcessor) to over the DefaultEffect and return a MaterialProcessorDefaultEffect.SkinnedEffect. I am guessing that somewhere along the lines this makes the renderer transform the mesh vertices using the model bones (with a vertex shader???)
I am having problems getting this SkinnedModelProcessor working in my own project. The sample uses the Microsoft.Xna.Framework.Content.Pipeline assembly. In my project I dont see the item in the regular list of .net references. So I added it manually from the filesystem.
The problem there is that as soon as I compile, visual studio says that it cant find that namespace, even though right up until I compile it shows everything working fine
How can I recreate the SkinnedModelProcessor from the sample in my own project
or
How can I get changes to bones reflect in my rendered model?

I've had the same issue and I'm in the works on creating my own simple Skinned Model Manipulator. For the time being the easiest way is to just create a new method in the AnimationPlayer class that will allow you to alter the boneTransforms.
I made something like this for your help:
public void SetPose(Matrix rootTransform, Matrix[] boneAlteration)
{
skinningDataValue.BindPose.CopyTo(boneTransforms, 0);
for (int i = 0; i < boneTransforms.Length; i++)
{
boneTransforms[i] = boneAlteration[i] * boneTransforms[i];
}
UpdateWorldTransforms(rootTransform);
UpdateSkinTransforms();
}
For this method the Matrix Array boneAlteration is simply an array of Identity Matrices for maintaining the original bindPose. Change any of the matrices before passing it into this method to rotate the bone for that corresponding index.

It appears the reason getting the reference to the pipeline assembly was such a problem is that you have to segregate that code into a separate special project using the XNA Content Pipeline Extension Library project template

Related

GetComponent in Unity (C#)

So i try to access the script component in another GameObject, but to do it faster i have a Component variable.
Component map = GameObject.FindWithTag("Map").GetComponent<Map>();
Now when i want to reference a variable inside a map component
map.selected = true;
it gives me an error that
UnityEngine.Component does not contain a definition for selected".
Selected is a public bool in Map script, attached to the Map GameObject.
When i go with the long way
GameObject.FindWithTag("Map").GetComponent<Map>().selected = true;
everything works, but i'm looking for a way to shorten my code (this script uses variables from Map in many instances, so i want to write it the shorter way).
This happens because you are instanciating your variable map as a Component, so the compiler will be looking for the selected attribute in the Component class.
Try something like this:
MapScript map = GameObject.FindWithTag("Map").GetComponent<MapScript>();
(Replace MapScript with the actual name of that script.)
I'm not entirely sure if this exact syntax will work, and I have no way of testing this at the moment, so please try and see if it works. If it doesn't, I will look into that as soon as I'm home.

Getting Scene Names at Runtime/Creating Scenes at runtime

I want to build a RTS Game in Unity version 5.3.xxx.
I want to have a dropdown menu to select the level i want to play.
I dont want to hardcode it in so how do i get the scene names at runtime?
This is neccessary to add new Levels ingame.
Thats the next question then. How do i create new scenes and add them to build path at runtime to use them ingame? for example in an map editor?
I cant use the UnityEditor to go through all scenes with foreeach, because its a editor class and these dont get into the final build..
Thanks
As of Unity 5.x, there are much more robust options for managing scenes at runtime.
Getting the current scene name:
SceneManager.GetActiveScene().name
Getting a list of all scene names added to the SceneManager:
var numScenes = SceneManager.sceneCount;
List<string> sceneNames = new List<string>(numScenes);
for (int i=0; i < numScenes; ++i)
{
sceneNames.Add(StageManager.GetSceneAt(i).name);
}
Creating new scene at runtime:
var newScene = SceneManager.CreateScene(string sceneName);
Adding new scenes to the build path at runtime:
I'm fairly certain this is not possible nor recommended.
If you want the functionality of a level editor in your game, consider writing your own method of serializing a scene so that it can be deserialized into an empty scene at runtime.
See also:
SceneManagement.Scene
SceneManagement.SceneManager
As explained here on the Unity forums, SceneManager.GetSceneAt only works with currently active scenes.
For now, you need to use work-arounds to get all scenes in your build during run-time, using EditorBuildSettings.scenes. You are right, this is only available during editing, but you can simply make sure to cache them to a run-time asset or component before building.
Also note that the documentation example for EditorBuildSettings.scenes actually gives you a pretty powerful script to grab all scenes, including those that have not been added to the build settings (and even adds them to the build settings, using a single button click)! You can just use that to save all scene paths to a component or ScriptableObject which will then be available during run-time.
Old I know, but it matched my search, so I'm posting my solution. This seems to be possible at runtime now using SceneUtility.GetScenePathByBuildIndex
What I did:
var sceneNames = new List<string>();
var regex = new Regex(#"([^/]*/)*([\w\d\-]*)\.unity");
for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++)
{
var path = SceneUtility.GetScenePathByBuildIndex(i);
var name = regex.Replace(path, "$2");
sceneNames.Add(name);
}
Regex Credit

Loading level data from xml file in XNA

I am creating a tile-based game in XNA and will be loading the level information from xml files. I have no problem with loading xml data but I would like feedback on the approach I'm thinking of using for reading the xml file.
The code has a class hierarchy such that:
A Level class contains:
- a collection of TileLayers
- a collection of Tilesets
A TileLayer class contains
- a collection of Tiles
A Tileset class contains:
- a collection of TilsetTiles
A TilesetTile class contains:
- a TileId
- a collection of TileProperties
- a TileRectangle
Each of the above classes requires some information from the xml level file.
When I load a level I would like to simply call Level.Load();
My intention is that each class will have a Load() method that will:
1. Load any specific info it needs from the xml file.
2. Call Load() on its children.
The problem I see is that the code for processing the xml will be scattered around in different files making changes difficult to implement (for instance if I decide to encrypt the xml file), and no doubt breaks several aspects of the SOLID principles.
I have this idea that I could create an xmlLevelReader class whose sole purpose is to read an xml level file.
This class could then expose methods that can be called from the Load() method in each of the classes described above.
For example the TileLayer class Load() method could call xmlLevelReader.GetTiles() which would return an IEnumerable<Tile>
Do you think this approach will work?
Can you foresee any difficulties?
Is this approach too simplistic/complicated?
Any constructive criticism welcomed!
Thanks
Based on your comment, I see that you are using Tiled Map Editor. This lead me to suggest that you use TiledLib. Here is a brief explanation of how you can get up and running with importing your .tmx files for use in game.
Content Pipeline Overview
File -> Content Import -> Content Process -> Content Write -> .xnb -> ContentRead -> Game Object
TiledLib
TiledLib only handles the ContentImporter part of the above diagram. It will essentially handle reading the .tmx XML and allow you to process the data into whatever objects you need at run time. Fortunately, the TiledLib author has provided a Demos section in the download as well.
Basic Tiled Map Processor Demo
BasicDemo main game project which contains the ContentManager.Load call.
BasicDemoContent project which has the .tmx file from Tiled
BasicDemoContentPipeline project which has the ContentProcessor
TiledLib which has the ContentImporter
You really only need to worry about how the ContentProcessor works because TiledLib handles all the importing for you. Although I do suggest looking through the different classes to understand how it is deserializing the XML (for educational purposes).
The example ContentProcessor in the Basic Demo project takes in a MapContent object from the ContentImporter (TiledLib) and outputs a DemoMapContent object which is serialized to .xnb at build time and deserialized to a Map object at run time. Here are the classes that represent the map after being processed completely:
[ContentSerializerRuntimeType("BasicDemo.Map, BasicDemo")]
public class DemoMapContent
{
public int TileWidth;
public int TileHeight;
public List<DemoMapLayerContent> Layers = new List<DemoMapLayerContent>();
}
[ContentSerializerRuntimeType("BasicDemo.Layer, BasicDemo")]
public class DemoMapLayerContent
{
public int Width;
public int Height;
public DemoMapTileContent[] Tiles;
}
[ContentSerializerRuntimeType("BasicDemo.Tile, BasicDemo")]
public class DemoMapTileContent
{
public ExternalReference<Texture2DContent> Texture;
public Rectangle SourceRectangle;
public SpriteEffects SpriteEffects;
}
A Map contains a tile width, tile height, and a list of MapLayers.
A MapLayer contains a width, a height, and a list of Tiles.
A MapTile contains a texture, a source rectangle (proper rectangle in the tileset), and optional sprite effects (I've never used any).
How It's Made
I suggest reading the comments of the ContentProcessor to understand what is happening, but in brief, this is the basics:
Load texture data for tile set
Get source rectangles for each tile from within the texture
Iterate over all layers of the map
For each layer, iterate over all tiles
For each tile, get the proper texture and source rectangle
Assign all data from the input to the output properly
Caveats
As long as you stick to basic types (vague, I know), you also do not need to worry about ContentWriter and ContentReader parts of the content pipeline. It will automatically serialize and deserialize the .xnb files at build and run time, respectively. See a question I asked about this: here.
Also, you'll notice that if you're using object layers from within Tiled, the demo does not show you how to process those. TiledLib does properly import them, you just need to pull the data out and stick it in your proper classes. I'll try to edit this answer later with an example of how to do that.
If you are just wanting to load in XML without manipulating the data at all, you can just use the built in XNA Content Serializer.
Essentially you define a class which maps to your xml format, and then read the XML into an instance of that class.
For example. Here I define the class I want to load into:
SpriteRenderDefinition.cs
I chose this one because it has nested classes like the case you describe. Note that it goes into the ContentDefinitions project of you XNA solution.
Now here is the xml file that fills in the content of a SpriteRenderDefinition:
Sprite.xml
The format of that XML maps directly to the member names of SpriteRenderDefinition.
And finally, the code to actually load that XML data into an actual Object at runtime is very straight forward:
SpriteRenderDefinition def = GameObjectManager.pInstance.pContentManager.Load<SpriteRenderDefinition>(fileName);
After calling that line, you have a SpriteRenderDefintion object populated with all the content of the XML file! That is all the code I wrote. Everything else is built into XNA. It's really quite slick and useful if you take an hour or so to figure it out!

TiledLib for XNA throws ArgumentException on loading

Essentially, what I'm trying to do is to load/draw a map from a Tiled map using Nick Gravelyn's TiledLib. The map is saved in Tiled's XML format. However, when I try loading the map with the line
TiledLib.Map map = Content.Load<TiledLib.Map>("Maps/Map1");
it throws an ArgumentException. The whole thing renders like this in Tiled itself:
The map's XML source looks like this (not posted directly onto StackOverflow for obvious size reasons).
It worked at first (with a pretty simple map using only one tileset) but when I edited it to include a bit more stuff then it suddenly started doing this. Could it be related to my usage of tile objects?
EDIT: I have been able to work out that using tile objects was not the culprit; this map structure still creates the same error.
you get an exception because you didn't name the objects in the map, this will cause ArgumentException in TiledLib. So, to solve this issue you need to go back to Tiled program, (re)edit this map, and select every object in the map and give it a name (not property but name) then export the map again and (re)import it into the game content. This should fix the problem.
BTW: I recommend using regular layer for collide check not object layer.
Like this: Make small png file with a transparent red rectangle tile in it in the same map tile dimensions, add new layer to the map, name it CollideLayer, and in this CollideLayer put that red rectangle tile where you want to be a collide, and then in the game code you can check to see if the CollideLayer cell is empty or not. I find this is simpler.
I',m guessing, but looking at your XML structure in the section, there are a lot of repeats of
<tile gid="0"/>
in the data element. There is no documentation or schema definition on the structure of this file on the official site, and the content pipeline source is not available. Also, the demo of TileLib comes with that section as
<data encoding="base64" compression="gzip">
H4sIAAAAAAAAC2NmYGBgpjKmFkA2jxCNrg+bHD7z0PWSYx428wmZjW4+qf7Fxyc3PnDFJS3jdzCbx4QFg8QZScTUzmcgDACR4mfdwAMAAA==
I'm not sure if you have an option to include encryption or not. But, the "gid" (global id ??) attribute cannot be the same for every tile defined if that is what it is. If I was writing this engine, I would have some way to readily identify each basic defined tile. Like a primary key on a data table. Which has to be unique. That would be the "gid" attribute for me.
Since the exception does not give any information (which is stupid - who deploys public libraries like that??), the argument exception is either that your "gid" attribute value is already defined, or that you're missing the encryption attributes which it expects in the pipeline importer or processor.

Programatic way to do linear referencing in ArcGIS

I am working on a custom ArcGIS Desktop tool project and I would like to implement an automated linear referencing feature in it. To make a long story short, I would like to display problematic segments along a route and show the severity by using a color code (say green, yellow, red, etc.). I know this is a pretty common scenario and have come to understand that the "right way" of accomplishing this task is to create a linear event table which will allow me to assign different codes to certain route segments. Some of my colleagues know how to do it manually but I can't seem to find any way to replicate this programaticaly.
The current tool is written in C# and already performs all the needed calculations to determine the problematic areas. The problem mainly is that I don't know where to start since I don't know a lot about ArcObjects. Any code sample or suggestion is welcome (C# is preferred but C++, VB and others will surely help me anyway).
EDIT :
I'm trying to use the MakeRouteEventLayer tool but can't seem to get the different pre-conditions met. The routes are hosted on an SDE server. So far, I am establishing a connection this way :
ESRI.ArcGIS.esriSystem.IPropertySet pConnectionProperties = new ESRI.ArcGIS.esriSystem.PropertySet();
ESRI.ArcGIS.Geodatabase.IWorkspaceFactory pWorkspaceFactory;
ESRI.ArcGIS.Geodatabase.IWorkspace pWorkspace;
ESRI.ArcGIS.Location.ILocatorManager pLocatorManager;
ESRI.ArcGIS.Location.IDatabaseLocatorWorkspace pDatabaseLocatorWorkspace;
pConnectionProperties.SetProperty("server", "xxxx");
pConnectionProperties.SetProperty("instance", "yyyy");
pConnectionProperties.SetProperty("database", "zzzz");
pConnectionProperties.SetProperty("AUTHENTICATION_MODE", "OSA");
pConnectionProperties.SetProperty("version", "dbo.DEFAULT");
pWorkspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.SdeWorkspaceFactory();
pWorkspace = pWorkspaceFactory.Open(pConnectionProperties, 0);
pLocatorManager = new ESRI.ArcGIS.Location.LocatorManager();
pDatabaseLocatorWorkspace = (ESRI.ArcGIS.Location.IDatabaseLocatorWorkspace)pLocatorManager.GetLocatorWorkspace(pWorkspace);
Now I am stuck trying to prepare everything for MakeRouteEventLayer's constructor. I can't seem to find how i'm supposed to get the Feature Layer to pass as the Input Route Features. Also, I don't understand how to create an event table properly. I can't seem to find any exemple relating to what I am trying to accomplish aside from this one which I don't understand since it isn't documented/commented and the datatypes are not mentionned.
I'm not entirely certain what it is you want to do. If you want to get Linear Referencing values or manipulate them directly in a feature class that already has linear referencing defined, that's pretty straight forward.
IFeatureClass fc = ....;
IFeature feature = fc.GetFeature(...);
IMSegmentation3 seg = (IMSegmentation3)feature;
... blah ...
If you need to create a Feature class with linear referencing, you should start witht he "Geoprocessing" tools in the ArcToolbox. If the out-of-the-box tools can do most of what you need, this will minimize your coding.
I would strongly recommend trying to figure what you need to do with ArcMap if at all possible... then backing out the ArcObjects.
Linear Referencing API
Linear Referencing Toolbox
Understanding Linear Referencing

Categories

Resources