2009-11-16 23 views
1

Im essayant d'appliquer un matériau à mon GeometryModel3D lors de l'exécution comme ceci:WPF matériel 3d ImageBrush aide

 var model3D = ShardModelVisual.Content as GeometryModel3D; 
     var materialGroup = model3D.Material as MaterialGroup; 

     BitmapImage image; 
     ResourceLoader.TryLoadImage("pack://application:,,,/AnzSurface;component/path file/img.png", out image, ".png"); 
     var iceBrush = new ImageBrush(image); 
     var grp = new TransformGroup(); 
     grp.Children.Add(new ScaleTransform(0.25, 0.65, 0.5, 0.5)); 
     grp.Children.Add(new TranslateTransform(0.0, 0.0)); 
     iceBrush.Transform = grp; 
     var iceMat = new DiffuseMaterial(iceBrush); 
     materialGroup.Children.Add(iceMat); 

qui tout fonctionne très bien, et le matériel est ajouté. Ce que je ne comprends pas, c'est comment je peux cartographier les utilisateurs qui cliquent sur l'écran pour les décalages qui doivent être appliqués à TranslateTransform.

I.e. au moment x: -0.25 déplace le matériau vers l'arrière le long de l'axe X, mais je ne sais pas comment obtenir ce type d'une coordonnée à partir du clic de la souris utilisateurs ...

quand je fais:

e.MouseDevice.GetPosition (ShardsViewPort3D);

qui me donne la normale X/Y corrds du clic de la souris ...

Merci pour toute aide que vous pouvez donner!

+0

Il ya probablement une meilleure façon de le faire, mais l'approche évidente est de mettre en œuvre http://en.wikipedia.org/wiki/Ray_casting –

+0

Hmm, pas trop sûr de ce que vous entendez par là par rapport à ma question .. Pouvez-vous m'expliquer comment cela pourrait aider ma situation? – Mark

Répondre

3

Il semble que vous souhaitiez faire glisser le matériau autour de votre géométrie lorsque vous cliquez dessus. Voici comment:

Utilisez le test d'impact pour traduire vos coordonnées X/Y à partir du clic de la souris dans un RayMeshGeometry3DHitTestResult comme décrit dans earlier answer. Cela vous donnera le MeshGeometry3D qui a été touché, les sommets du triangle qui a été touché, et la position relative sur ce triangle.

rechercher chaque index de sommet (VertexIndex1, VertexIndex2, VertexIndex2) dans le MeshGeometry3D.TextureCoordinates pour obtenir les coordonnées de texture. Cela vous donnera trois paires (u, v) en tant qu'objets ponctuels. Multiplier chaque le (u, v) paires par le poids correspondant du résultat de test de recherche (VertexWeight1, VertexWeight2, VertexWeight3) et ajoutez les paires ensemble, à savoir:

uMouse = u1 * VertexWeight1 + u2 * VertexWeight2 + u3 * VertexWeight3 
vMouse = v1 * VertexWeight1 + v2 * VertexWeight2 + v3 * VertexWeight3 

Maintenant, vous avez un point (uMouse, VMOUSE) cela indique où sur votre matériel votre souris a été cliquée. Si vous voulez qu'un point particulier de votre texture se déplace exactement à l'endroit où la souris a été cliquée, il suffit de soustraire le (uMouse, vMouse) où la souris a été cliquée de la coordonnée (u, v) de l'emplacement dans le matériau vous voulez apparaître sous la souris, et définissez ceci comme TranslateTransform. Si vous voulez gérer glisser, stocker le calculée (uMouse, VMOUSE) où la traînée a commencé et la transformation à partir du début de la traînée, puis comme traînantes progrès calculer la nouvelle transform comme:

translate = (uMouse,vMouse) - (uMouseDragStart, vMouseDragStart) + origTranslate 

Dans le code, vous aurez écrivez ceci comme ajouts de points. Je l'ai orthographié comme (u, v) dans cette explication parce que je pensais que c'était plus facile à comprendre si je le faisais. En réalité le code à calculer (uMouse, VMOUSE) regardera plus comme ceci:

var uv1 = hit.MeshHit.TextureCoordinates[hit.VertexIndex1]; 
var uv2 = hit.MeshHit.TextureCoordinates[hit.VertexIndex2]; 
var uv3 = hit.MeshHit.TextureCoordinates[hit.VertexIndex3]; 

var uvMouse = new Vector(
    uv1.X * hit.VertexWeight1 + uv2.X * hit.VertexWeight2 + uv3.X * hit.VertexWeight3) 
    uv1.Y * hit.VertexWeight1 + uv2.Y * hit.VertexWeight2 + uv3.Y * hit.VertexWeight3); 

et le code pour mettre à jour la transformation au cours d'une traînée ressemblera à quelque chose comme ceci:

... 
var translate = translateAtDragStart + uvMouse - uvMouseAtDragStart; 
... = new TranslateTransform(translate.X, translate.Y); 

Vous aurez doit adapter cela à la situation exacte.

Notez que votre rappel HitTest peut être appelé plusieurs fois, en commençant par le maillage le plus proche et en reculant. Il peut même être appelé avec des hits 2D, par exemple si un objet 2D est en face de votre Viewport3D. Donc, vous voudrez vérifier chaque hit pour voir si c'est vraiment ce que vous voulez, par exemple, pendant le glisser, vous voulez continuer à vérifier la position sur le mesh en train d'être déplacé même si ce n'est plus le cas. Renvoyez HitTestResultBehavior.Stop de votre rappel une fois que vous avez agi sur le maillage en train d'être déplacé.

+0

Merci beaucoup! C'est une bonne réponse, j'apprécie vraiment le détail – Mark

+0

J'ai effectivement trouvé un autre moyen, mais je vous donne des points sur celui-ci – Mark