# Eigenes 3D Objekt



## Highchiller (27. Jun 2011)

Hallöchen liebe Java-Freunde.

Ich hab ja schon durchblicken lassen, dass ich mich mal öfter melden werden.

Folgendes. Ich wollte ein eigenes Object erstellen, ein Hexagon in 3D.
Nun hab ich mir eine Shape3D-Klasse geschrieben, die mir im Konstruktor ein Shape3D Object erstellt mit den gewünschten Werten.
In einer anderen Klasse will ich nun dieses Object aufrufen und anzeigen lassen.

Das Problem ist aber, das einzelne Flächen nicht angezeigt werden und das Hexagon in 3D nun viele 3-Eckige Löcher hat. Wie kann das sein?

Hier erst mal mein Code

```
public class Tile {
	private Shape3D S3D;
	
	public Tile(){
		S3D = new Shape3D();
		
		Point3f[] CoordArr = new Point3f[12];
		int[] Vind = new int[60];
		
		GeometryInfo GInfo;
		NormalGenerator NormGen = new NormalGenerator();
		Stripifier GStrip = new Stripifier();
		
		/*** Coordinates ***/
		//first lvl plane
		CoordArr[0] = new Point3f(0.5f,0f,0f);
		CoordArr[1] = new Point3f(1.5f,0f,0f);
		CoordArr[2] = new Point3f(2f,0f,0.5f);
		CoordArr[3] = new Point3f(1.5f,0f,1f);
		CoordArr[4] = new Point3f(0.5f,0f,1f);
		CoordArr[5] = new Point3f(0f,0f,0.5f);
		//second lvl plane
		CoordArr[6] = new Point3f(0.5f,0.25f,0f);
		CoordArr[7] = new Point3f(1.5f,0.25f,0f);
		CoordArr[8] = new Point3f(2f,0.25f,0.5f);
		CoordArr[9] = new Point3f(1.5f,0.25f,1f);
		CoordArr[10] = new Point3f(0.5f,0.25f,1f);
		CoordArr[11] = new Point3f(0f,0.25f,0.5f);
		
		/*** Planes ***/
		//ground lvl
		Vind[0] = 0; Vind[1] = 1; Vind[2] = 4;
		Vind[3] = 1; Vind[4] = 3; Vind[5] = 4;
		Vind[6] = 0; Vind[7] = 4; Vind[8] = 5;
		Vind[9] = 1; Vind[10] = 2; Vind[11] = 3;
		
		//top lvl
		Vind[12] = 6; Vind[13] = 7; Vind[14] = 10;
		Vind[15] = 7; Vind[16] = 9; Vind[17] = 10;
		Vind[18] = 6; Vind[19] = 10; Vind[20] = 11;
		Vind[21] = 7; Vind[22] = 8; Vind[23] = 9;
		
		//planes
		Vind[24] = 0; Vind[25] = 5; Vind[26] = 11;
		Vind[27] = 0; Vind[28] = 11; Vind[29] = 6;
		
		Vind[30] = 1; Vind[31] = 0; Vind[32] = 6;
		Vind[33] = 1; Vind[34] = 7; Vind[35] = 6;
		
		Vind[36] = 2; Vind[37] = 1; Vind[38] = 7;
		Vind[39] = 2; Vind[40] = 8; Vind[41] = 7;
		
		Vind[42] = 3; Vind[43] = 2; Vind[44] = 8;
		Vind[45] = 3; Vind[46] = 9; Vind[47] = 8;
		
		Vind[48] = 4; Vind[49] = 3; Vind[50] = 9;
		Vind[51] = 4; Vind[52] = 10; Vind[53] = 9;
		
		Vind[54] = 5; Vind[55] = 4; Vind[56] = 10;
		Vind[57] = 5; Vind[58] = 11; Vind[59] = 10;
		
		GInfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
		GInfo.setCoordinates( CoordArr );
		GInfo.setCoordinateIndices( Vind );
		GInfo.compact();
		
		NormGen.generateNormals( GInfo );
		GStrip.stripify( GInfo );
		
		S3D.addGeometry( GInfo.getGeometryArray() );
	}
	
	public Shape3D getTile(){
		return S3D;
	}
}
```

Wenn ich das Object drehbar mache, fällt auch auf, dass die Flächen zwar angezeigt werden, aber eben nicht deren Rückseiten. 
Im Übrigen, wird das Object komplett in weiß angezeigt, trotz anderer Lichtobjekte. Eigentlich dachte ich mit Hilfe der GeometryInfo hätte ich das Problem gelöst, aber irgendwie... wohl nicht.

Weiß jemand Rat?
Vielen Dank schon mal, Euer Chiller


----------



## muckelzwerg (27. Jun 2011)

Ist für gewöhnnlich ein Problem mit falsch gesetzten Normalen. Du kannst beidseitige Zeichnung von Polygonen aktivieren, aber die Normalen solltest Du dennoch reparieren. (falls es daran liegt)


----------



## Highchiller (27. Jun 2011)

Also ich denke auch dass es an den Normalen liegt. Aber wie "reparier" ich die denn?
Würde denn die Reihenfolge was ändern?


----------



## Marco13 (27. Jun 2011)

Vermutlich ja. Bin aus Java3D ein bißchen raus, aber wenn man die Reihenfolge der indizes der "falschen" Dreiecke umkehrt, kann es gut sein, dass es funktioniert, also z.B.
Vind[3] = 1; Vind[4] = 3; Vind[5] = 4;
ändern in
Vind[3] = 4; Vind[4] = 3; Vind[5] = 1;
(falls das eins von den "falschen" war).


----------



## muckelzwerg (27. Jun 2011)

Für gewöhnlich wird die Normale nach dem Umlaufsinn gesetzt. In einem Rechtssystem musst Du rechtsherum, also gegen den Uhrzeigersinn, die Punkte angeben, um die Vorderseite festzulegen.

Die Normale ist das Ergebis des Kreuzproduktes, das aus den Seiten des Polygons gebildet wird. Nimm Dir einen Punkt des Dreiecks, bilde die Vektoren zu den anderen beiden Punkte in der Reihenfolge, wie Du sie angegeben hast und berechne das Kreuzprodukt. Die Seite auf die das Kreuzprodukt zeigt, ist die Seite von der aus man das Polygon von "Vorne" sieht.


----------



## Highchiller (27. Jun 2011)

Tatsächlich... es hat funktioniert.

Vielen vielen Dank.

Jetzt gleich noch eine Frage bzgl. dieses Objekts. Ich will das ausschließlich auf der oberseite eine Grafik angezeigt wird. Im moment hab ich das so gelöst:

```
ObjApp.setTexture( new TextureLoader("C:/Users/Andre/eclipse/3DWorkshop/images/Queen.png",
				TextureLoader.GENERATE_MIPMAP, null).getTexture());
		ObjApp.setTexCoordGeneration( new TexCoordGeneration(
				TexCoordGeneration.OBJECT_LINEAR, TexCoordGeneration.TEXTURE_COORDINATE_3));
```

Und dann halt zu der Shape3D S3D mit hilfe von setAppearance(ObjApp) hinzugefügt.
Wie kann ich jetzt sagen, dass diese Grafik aber nur ganz bestimmten flächen zusehen sein soll?
Nämlich eben auf den obersten 4 Dreiecken.
Quasi auf der Ebene:

```
Vind[12] = 6; Vind[13] = 7; Vind[14] = 10;
		Vind[15] = 7; Vind[16] = 9; Vind[17] = 10;
		Vind[18] = 6; Vind[19] = 10; Vind[20] = 11;
		Vind[21] = 7; Vind[22] = 8; Vind[23] = 9;
```

Versteht ihr was ich meine? 

PS: Also im Moment wird das PNG halt über das ganze Objekt gespannt. Dadurch ist es aber total verzerrt und von oben halt gar nicht mehr zu erkennen. 

Danke wieder im Voraus. Ihr habt mir schon jetzt enorm geholfen.


----------



## Marco13 (27. Jun 2011)

Hmmm... das kann frickelig werden... Spätestens wenn sich das dann noch während des Spiels ändern soll (also diese Textur dann auf einem anderen Hexagon liegen soll) wird's kompliziert (aber vorher u.U. auch schon...). Es wäre vermutlich deutlich einfacher, wenn man, falls das passt, für jede Spielfigur ein eigenes Hexagon anlegen würde (ggf. könnte man dann gleich eine Klasse "Spielfigur" machen, um das ganze auch ein bißchen aufzuräumen und zu kapseln). Wenn nicht, solltest du nochmal genauer beschreiben, was da am Ende so alles gemacht werden soll....


----------



## Highchiller (27. Jun 2011)

Ja ganz genau so hab ich mir das schon gedacht. Daher hab ich mir gleich eine eigene Klasse für ein Steinchen angelegt. Mein Plan umfasste schon jeden Stein extra "herzustellen".

Also um das mal etwas zu verdeutlichen. Das Spiel nennt sich Hive und sieht in 2D typischerweise ungefähr so aus:




Da liegen also Spielsteine aneinander.
Das heißt auch, wenn so ein Stein erst mal liegt, wird der nicht verändert. Bestenfalls seine Position wird verändert. Aber weil ich mir das noch etwas zu komplex denke, dürfte es erst mal reichen, für jeden Zug das neu zu erstellen. (Optimieren kann ich später ja immer noch)
Daher reicht es einen Stein einmal zu erstellen. Verändert wird daran nix mehr, der ist und bleibt dann so 

Problem ist halt, wie krieg ich son Bild auf das Steinchen? Also nicht total verzerrt sondern halt einfach als Grafik oben drauf.


----------



## Marco13 (27. Jun 2011)

Ist jetzt jeder Spielstein ein eigenes Shape3D oder nicht.. ???:L


----------



## Highchiller (27. Jun 2011)

Ähm, ja. So hätte ich das jetzt gelöst. Meinst nich?


----------



## Marco13 (28. Jun 2011)

Ja, war nur nicht ganz klar. Die Position verändern ist ja unkritisch. Eigentlich sollte er ja mit diesem "TexCoordGeneration" Ding die Texturkoordinaten automatisch generieren. Ich hab' das noch nicht verwendet, vielleicht mal mit den Parametern rumspielen...? (Viel mehr als sowas wie TexCoordGeneration class to automatically define the texture coordinates : Texture3DJava kopieren könnte ich da spontan auch nicht). Im Zweifelsfall muss man die Texturkoordinaten per Hand angeben - aber zum Glück wären die ja für alle Figuren gleich.


----------



## Highchiller (28. Jun 2011)

Was mich an dem "selber setzen" irritiert.
Wenn wir das verwenden, zerstören wir dann nicht das komplette Reflexionsverhalten des Steines? Ich meine klar, wir hätten dann ein tolles Bild oben drauf, weil der Stein ja gar nicht mehr Anhaltspunkte hätte, aber damit hätte er ja auch keine Reflexionspunkte mehr. Oder täusch ich mich da jetzt?

Ansonsten Danke erst mal 
Ich schau mir das Morgen mal in Ruhe an :rtfm:


----------



## Highchiller (28. Jun 2011)

Hmm nun ja, vllt noch eine andere Frage.

Im moment hab ich ja einen schönen "weißen" Stein mit folgenden Appearance eigenschaften:

```
SphereAppearance.setMaterial(
				new Material( new Color3f(0.5f,0.5f,0.5f), new Color3f(0f,0f,0f),
						new Color3f(0.8f,0.8f,0.8f), new Color3f(0.6f,0.6f,0.6f), 
						100f) );
```

Hat jemand eine Idee wie ich einen schwarzen Stein immitieren könnte?
Also der soll auch schön glänzen im Licht, klar. Aber er soll halt schwarz sein.
Jemand ne Idee wie ich das hinbekomme ohne dass man ihn gar nicht mehr sieht, weil er einfach kaum etwas reflektiert?
Gibts da vllt noch andere tollen Sachen als setMaterial()?


----------



## Marco13 (28. Jun 2011)

Der letzte Parameter (die 100f) ist schon die "shininess", das sollte reichen. Aber was genau du (auch im Beitrag davor) mit "Glanz" meinst, weiß nicht nicht: Die Texturkoordinaten haben da eigentlich keinen Einfluß drauf...


----------



## thewulf00 (28. Jun 2011)

Da bist Du schon richtig im Material.
Du setzt die Farben auf schwarz (oder besser: fast schwarz), die ambient usw. darstellen. Und die Farben, die die Reflexion steuert, setzt Du auf helles grau. Das sieht dann so aus, als würdest Du auf schwarzem Marmor die Küchenlampe teilweise sehen.


----------



## Highchiller (28. Jun 2011)

Na gut ich schraub erst mal ein wenig daran rum. 
Vielen Dank für die Hilfe.


----------



## Highchiller (1. Jul 2011)

So, jetzt hab ich alles zu meiner Zufriedenheit gelöst.
Es gibt nur immer noch ein Problem mit den Texturen.

Also ich setze ja eine Textur auf mein eigenes Objekt. Das Objekt hat als Textureigenschaft auch TexCoordGeneration.OBJECT_LINEAR damit das Bild fest auf dem Stein liegt.

Das Problem ist, dass er das Bild nicht wirklich wie ein Bild drauf packt, sondern eher eine riesige Fläche voll mit diesen Bilder hat, und immer nur den Ausschnitt zeigt, wo das Objekt liegt. Quasi wie ein Fenster durch das man die "Textur" sieht.

Macht eigentlich auch irgendwo Sinn, wenn man sich fragt was Textur überhaupt bedeutet.

Meine Frage nun, krieg ich das Bild irgendwie fest auf Objekt. So richtig als Bild auch, dass die Texturen nicht irgendwie, irgendwo verschieben.


----------



## Marco13 (1. Jul 2011)

Kapier' ich nicht - hat das was mit den "Boundary modes" aus Texture (Java 3D API) zu tun?


----------



## Highchiller (1. Jul 2011)

Hmm. Kenn ich gar nicht :bahnhof:

Also ich erstelle mir ein Objekt. Ein Shape3D und füge dann Appearance hinzu.
Da kann ich ja verschiedene Eigenschaften hinzufügen.
Da setz ich eine Texture, nämlich mit Hilfe des TextureLoader. Der Läd ein Bild und ich klau mir davon die Textur und füge die der Appearance hinzu. Anschließend füge ich die Appearance dann dem Objekt hinzu.

Der Appearance überge ich noch als TexCoordGeneration, dass die Textur Object_Linear sein soll. Heißt halt das die Textur fest auf dem Objekt klebt, wenn ich es bewegen würde.

Aber es das Bild liegt halt nicht richtig auf dem Objekt drauf. Es ist leicht verschoben und liegt schief drauf. Wie kann ich das beheben.

Um es einfach auszudrücken.


----------



## Marco13 (2. Jul 2011)

Ehrlich gesagt weiß ich nicht, was TexCoordGeneration _intern_ genau macht - d.h. WIE dort die Texturkoordinaten (abhängig von OBJECT_LINEAR und Co) berechnet werden. Es geht doch nur um Sechsecke? Vielleicht wäre es da doch am einfachsten, die Texturkoordinaten per Hand zu definieren. Kann gut sein, dass die am Anfang sogar gleich den Vertexpositionen sind (müßte man nochmal genauer schauen). Könnte man den relevanten Teil (das Erstellen des Objektes) in rausschälen und in ein KSKB packen?


----------



## Highchiller (3. Jul 2011)

Das hab ich nicht verstanden. Ein KSKB?
Das mit den Texturkoordinaten per Hand setzen hab ich über Bord geworfen, weil ich dachte, dass dann die Reflexion für Licht ja auch von diesen Texturkoordinaten abhängen, dachte ich zumindest.

Meine Lösung ist jetzt, das ich immer ein Objekt im Nullpunkt erzeuge, mit oberseite Richtung Z-Achse. Damit liegt das Bild einigermaßen gerade drauf 

Danke für die Hilfe


----------

