When you use the model processor build into the XNA Framework Content Pipeline you will notice that each ModelMeshPart on a Model has an Effect already loaded. By default this is an instance of BasicEffect with the models textures and other material properties already set. This is great when you want to get a model loaded and rendering quick but sometimes you want to set a custom effect that you have previously created.
To help show users how to load a custom effect file on a model we created a sample called Custom Model Effect found here. The sample sets the new effect file in a custom content processor before saving the model out into an .xnb file. In this post I hope to show how to can extend this idea to allow you to create a custom processor that will accept a processor parameter for the effect file. This will allow you to reuse the same processor for many of your models even if they use separate effect files.
The first step is to create a new Content Pipeline Extension Library project if you do not already have one setup for your project. You will also need to setup a reference to the new project in your content project. The XNA Docs have some great resources that show you how to do this.
Next you will need to overwrite the standard model processor.
[ContentProcessor]
public class CustomEffectModelProcessor : ModelProcessor
Your new class needs a processor parameter that will take in your new effect file name.
[DisplayName("Custom Effect")]
[DefaultValue("")]
[Description("The custom effect applied to the model.")]
public string CustomEffect
{
get { return customEffect; }
set { customEffect = value; }
}
private string customEffect;
You will need to add a using statement for System.ComponentModel for the new parameter.
Next you will need to override the ConvertMaterial method of the standard model processor so we can call our new material processor. Also notice that we pass along the processor parameter we defined above.
protected override MaterialContent ConvertMaterial(MaterialContent material, ContentProcessorContext context)
{
OpaqueDataDictionary processorParameters = new OpaqueDataDictionar();
processorParameters.Add("CustomEffect", customEffect);
return context.Convert<MaterialContent, MaterialContent>(material, "CustomEffectMaterialProcessor", processorParameters);
}
Now our new model processor will be looking for a material processor called "CustomEffectMaterialProcessor". The next step is to create this new material processor.
[ContentProcessor]
class CustomEffectMaterialProcessor : MaterialProcessor
Our material processor needs two parts. The first is the same processor parameter as we created above for the model processor to accept the filename of the custom effect file. The other is an override of the Process method.
public override MaterialContent Process(MaterialContent input, ContentProcessorContext context)
In the process method we need to create the new EffectMaterialContent and load the custom effect from the file.
// Create a new effect material.
EffectMaterialContent customMaterial = new EffectMaterialContent();
// Point the new material at the custom effect file.
string effectFile = Path.GetFullPath(customEffect);
customMaterial.Effect = new ExternalReference<EffectContent>(effectFile);
// Loop over the textures in the current material adding them to the new material.
foreach (KeyValuePair<string, ExternalReference<TextureContent>> textureContent in input.Textures)
{
customMaterial.Textures.Add(textureContent.Key, textureContent.Value);
}
// Loop over the opaque data in the current material adding them to the new material.
foreach (KeyValuePair<string, Object> opaqueData in input.OpaqueData)
{
customMaterial.OpaqueData.Add(opaqueData.Key, opaqueData.Value);
}
// Call the base material processor to continue the rest of the processing.
return base.Process(customMaterial, context);
Now all you will need to do is set the Content Processor of your model to your new CustomEffectModelProcessor and set the Custom Effect to the effect file that you wish to use.

It has been over a year since my last blog post. As one colleague put it I was starting to get “Blogger Guilt”. The last post was all about the new Creators Club Online website. Well it turns out this post is about the same topic but much better. The original site did a great job at delivering information and educational content to our users.
The new site does that all a lot more. It is still home to the XNA forums and a bunch of great XNA educational content but it is also now home to the Community Games on Xbox LIVE Beta. Creators now have the ability to submit, peer review, and play community games. Go check out the new site at http://creators.xna.com for more information.

Often when working with 3D objects like characters and space ships you will need to point one object at the other. In this post we will cover two ways you can point objects at each other. The first way creates a matrix to turn your object towards the other. The second covers a way to determine the direction your object needs to turn.
Before we start we will cover some vector operations or what they represent. So here are a couple of the operations we will be using.
The vector cross product of X and Y creates a third vector Z that is orthogonal to both of them. Here are two resources for further information.
http://mathworld.wolfram.com/CrossProduct.html
http://en.wikipedia.org/wiki/Cross_product
The vector dot product represents a couple of things. Geometrically it represents the projection of X onto the unit length vector of Y. So you get the length of the X vector in the Y direction. This will be very useful for us later.
http://mathworld.wolfram.com/DotProduct.html
http://en.wikipedia.org/wiki/Dot_product
In order to turn the character towards another object (in this case, a sphere), we first create a vector between the two objects. Because we are in a right handed coordinate system we will be using –Z as our forward direction. To get the new forward vector of our object we need to take our position and subtract the position of the object.
characterLocalMatrix.Forward = characterLocalMatrix.Translation
- spherePosition;
Now we need to normalize the forward vector because we want our local matrix to be orthonormalized. If the object had been scaled this would be a good time to add the scale back to the object by multiplying the forward vector by the objects scale in the Z direction.
characterLocalMatrix.Forward = Vector3.Normalize(
characterLocalMatrix.Forward);
Next we need to create a new right vector for the object. To do this we are going to cross the new forward vector with the world up vector. We do this because we don’t yet know what the up vector is going to be so we will come back later and fix the up vector. Note that if your objects have abnormal orientations this will not work because it assumes that world up is close to your eventual up vector. The new right vector also needs to be normalized.
characterLocalMatrix.Right = Vector3.Cross(characterLocalMatrix.Forward,
Vector3.Up);
characterLocalMatrix.Right = Vector3.Normalize(characterLocalMatrix.Right);
Finally we need to create our up vector by crossing the new right and forward vectors.
characterLocalMatrix.Up = Vector3.Cross(characterLocalMatrix.Right,
characterLocalMatrix.Forward);
characterLocalMatrix.Up = Vector3.Normalize(characterLocalMatrix.Up);
Our characters local matrix is now ready to use. If you are using the BasicEffect your draw code will look something like this.
effect.World = characterLocalMatrix;
effect.View = viewMatrix;
effect.Projection = projectionMatrix;
Now that you know how to turn directly towards another object, what happens when you want to know what direction your AI should turn in order to face you? We need a way to determine if it is better to turn left or right. We will use the dot product to determine if we should turn left or right. Like the last example the first thing we need to do is to create a vector to the target. We also want the vector to be unit length so we also normalize the vector.
Vector3 turnAt = spherePosition - characterLocalMatrix.Translation;
turnAt.Normalize();
Next we calculate the dot product with our right vector. You might wonder why the right vector when we are trying to turn our forward vector. The reason is because of the behavior of the dot product. By using the right vector the result of the dot product with the turnAt vector will result in the projection of the turnAt vector in the right direction. This will get of the length of the turnAt in the right direction. If the result is positive it means we should turn left and if the result is negative we should turn right.
// Determine direction we need to turn using right vector
float dotResult = Vector3.Dot(turnAt, characterLocalMatrix.Right);
// Turn left
if (dotResult > 0.1f)
{
characterLocalMatrix *= Matrix.CreateRotationY(turnSpeed *
gameTime.ElapsedGameTime.Milliseconds);
}
// Turn right
else if (dotResult < -0.1f)
{
characterLocalMatrix *= Matrix.CreateRotationY(-turnSpeed *
gameTime.ElapsedGameTime.Milliseconds);
}
You will notice that we don’t check dotResult with 0. This is because the character will turn past the object and then turn the other direction. This cycle will go back and forth causing the character to shake. So this technique uses a dead zone. Another option if to turn directly at the target when you get in this zone.
Well that’s the end of my first post. While the information here was geared towards people new to 3D graphics I hope it helped everyone.