Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (11 posts)

Modifying Model Textures

Last post 1/8/2013 5:19 AM by 49ers94. 10 replies.
  • 4/28/2011 4:59 PM

    Modifying Model Textures

    I don't know if this is possible through XNA and if not, can I implement something into my DirectX shader? The scenario is we have a class that handles drawing and updating models. What we want to do is detect if a model intersects with another model, the vector3 where they collided can be translated to either model's textures. Specifically this is for our damage system. When a particle collides with the player's geometry, we want to modify the diffuse and bump maps where that particle collided.

    1. How can we detect precise collisions like that?
    2. How can we translate that 3D position in the world to a 2D position along the player geometry?
    3. How can we modify the textures then applied to the model. I assume using Texture2D.SetData() but the 2D position from the above question will need to be translated into the data[] that is applied to the texture.

    Can we get information about the individual polygons or information about the UV mapping? If we can do anything through XNA, through the shader, FBX exporter, or the content processor?

    Any help with any of these is really appreciated.

  • 5/1/2011 3:57 PM In reply to

    Re: Modifying Model Textures

    Answer
    Reply Quote
    Check out the triangle picking sample. This shows you how to detect intersections at individual triangles of a model, by using a modified content processor that stores vertex information in each model's Tag field, which can be read at runtime. The sample uses a ray projected from the screen but could be modified to detect intersections between models instead.

    You could also store a model's UV coordinates in the Tag field, using the vertices of intersection to look up the texcoords at that point. Rather than modifying the model's texture directly you would probably want to generate a decal texture that you layer over the model.

    It strikes me that there is likely a way to do this without generating tons of redundant mesh data, but this is probably the quickest way to get it working.
  • 5/3/2011 2:14 AM In reply to

    Re: Modifying Model Textures

    I am doing something similar now to that where I fire a ray from the bullet and if that ray intersects with the triangle, then it counts as a collision. Now the problem is that the vertex data (vector3) array that was set when the model was proccessed needs to be transformed to where it exists in the scene. The code of the triangle picker would work if the models never moved. So next problem is how do I translate that vertex array set at processing time to represent where it is in the game's world? Then I'll start looking at UVs.
  • 5/3/2011 5:08 AM In reply to

    Re: Modifying Model Textures

    VIAT:
    So next problem is how do I translate that vertex array set at processing time to represent where it is in the game's world? Then I'll start looking at UVs.

    You use the same World matrix that is typically applied when you draw it.

    Vector3 modelVertex; // given: a vertex in your model
    Matrix world; // given: the World matrix for your model

    Vector3 vertexInGameWorld = Vector3.Transform(modelVertex, world);


    If your model is skinned, you'll need to take into account the bone transforms too (i.e. if you are using Model.CopyAbsoluteBoneTransformsTo) - basically whatever the final World matrix you use when drawing.
  • 5/4/2011 1:16 AM In reply to

    Re: Modifying Model Textures

    Looks to be working. Thanks. Next would be translating the vector3 where the collision took place into a vector2 or something on the model's texture maps.
  • 5/4/2011 2:46 AM In reply to

    Re: Modifying Model Textures

    VIAT:
    Looks to be working. Thanks. Next would be translating the vector3 where the collision took place into a vector2 or something on the model's texture maps.
    This should be relatively easy if you change your model processor to store UV coordinates along with the vertices in the Tag data. The triangle intersection test gives you three indices into the vertex array, which you can also use to look up the corresponding texture coordinates.
  • 5/4/2011 6:24 PM In reply to

    Re: Modifying Model Textures

    Can you be a little more specific. Where are the UVs stored in the model? Are they in the opaquedata? Are they a vector2 array or a texture2D? Do you have any specific ideas on how to translate that triangle intersection location (u,v) into the same place in the UV coordinates or translate it to the texture maps?
  • 5/5/2011 3:36 AM In reply to

    Re: Modifying Model Textures

    Answer
    Reply Quote
    Sure. I haven't tested this but hopefully it'll put you on the right track. Assuming you're using the code from the triangle picking sample linked above, you need to modify the custom model processor to store UV coordinates for the model in the Tag data. So first add a member variable to the TrianglePickingProcessor class to accumulate texture coordinates in:
    List<Vector2> texCoords = new List<Vector2>(); 

    In the FindVertices method, inside the foreach loop that iterates through the mesh's GeometryContents (but outside the inner foreach loop that iterates through the Indices), get the texture coordinates for each piece of
    geometry and store them:
    IEnumerable<Vector2> geometryTexCoords = geometry.Vertices.Channels.Get<Vector2>(VertexChannelNames.TextureCoordinate(0));   
    texCoords.AddRange(geometryTexCoords); 


    What you get back from Channels.Get is just a list of all the texture coordinates for that GeometryContent, in the same order as the vertices. (So index 0 of texCoords contains the UV coordinates for index 0 of vertices.) You can access any of the model's non-positional data this way -- colors, normals, etc.

    Then in the Process method where the tagData is generated, add the texture coordinates to the tagData dictionary along with the vertices and bounding sphere that are already being added:
    tagData.Add("TexCoords", texCoords.ToArray()); 

    That's it for the ModelProcessor. Next, modify the RayIntersectsModel method that does the triangle test so it will output the indices of the closest intersecting triangle's vertices -- right now it just outputs the vertex positions. This is in the inner most block of the method, where it stores the information for the closest detected intersection:
    // If so, is it closer than any other previous triangle?  
    if ((closestIntersection == null) || (intersection < closestIntersection))  
    {  
    // .... 
     
    You just need to add an integer output parameter for the method and store the value of the i counter. If RayIntersectsModel returns with a hit, you use i, i+1, and i+2 as the indices into the texcoord list you have stored in the model's tag data.

    Those three pairs of texture coordinates will tell you which part of the model texture covers the triangle that was hit, and proportionally where you should draw the damage onto your damage texture map, so that when you blend the damage texture on the model the bullet holes / explosion marks / whatever show up in the right place. The simplest way to process the texture coordinates just to get something working would probably be to average them and then center your damage graphic on that point. But to make it look good you will need some kind of logic that works out the appropriate scale of the damage graphic based on how large the intersected triangle is. (And what the range of UV values for the triangle is, indicating the scale of the texture on that part of the model.)

    When it comes to creating the damage texture most likely you would have sprites with the different possible damage representations. For each model you'd have a Texture2D with the same proprtions as the model's main texture (not necessarily the same resolution, just same width/height ratio), as well as an array of Colors with (textureWidth*textureHeight) elements. Initially all the elements would probably be transparent black. Then whenever there's a hit you copy one of the damage sprites into the array at the location and scale indicated by the texture coordinates. To index into an array like this that you're creating a texture from, you use
    y * textureWidth + x 
    to get the pixel at coords (x,y). Whenever the array changes because of new hits you call SetData on the Texture2D that stores the damage, passing in the Color array. (Not every frame! Only when it actually changes. SetData is slow.) 

    Does this help?
  • 5/5/2011 4:49 PM In reply to

    Re: Modifying Model Textures

    Seems logical. It'll take me a few days to fully implement it but I think I can work with this. Thanks for all your help.
  • 5/6/2011 1:41 AM In reply to

    Re: Modifying Model Textures

    Sorry, NCLF is actually me. I just changed and forgot to post as this account.
  • 1/8/2013 5:19 AM In reply to

    Re: Modifying Model Textures

    Would you mind giving a visual example of the modification of the RayIntersectsModel method to a newbie.

    (my overall goal is to try to create certain sounds and particle effects based on the texture of the terrain the character is walking on. )Thankyou.
Page 1 of 1 (11 posts) Previous Discussion Next Discussion