j3d mehr als ein Objekt rotieren

bob_sheknowdas

Aktives Mitglied
Hi,
ich habe schon wieder ein Problem mit der Rotation in j3d. In einem anderen Threat wurde mir bereits dabei geholfen ein Objekt vernünftig zu rotieren. Jetzt habe ich ein 2. Objekte erzeugt und wollte es auf die selbe Weise drehen lassen. Das funktioniert aber nicht, die beiden Rotationen überschreiben sich und es kommt zu mysteriösen Ereignissen :D

Hier mal fix die Klasse, die sich um die Bewegung kümmert (auf das Wichtigste reduziert)

Java:
class Steuerung implements KeyListener
{
    private final TransformGroup myTransformGroup;
    private final Flugzeug myFlugzeug;
    private final Enemy theEnemy;
    private Transform3D trans = new Transform3D();
    private Transform3D transE = new Transform3D();
    private final Spiel parent;
    private int enemyTurn=0;
    
    float xE = 0f;
    float yE = 0f;
    
    private final int upKey = KeyEvent.VK_W;
    private final int downKey = KeyEvent.VK_S;
    private final int leftKey = KeyEvent.VK_A;
    private final int rightKey = KeyEvent.VK_D;
    private final int speedUp = KeyEvent.VK_UP;
    private final int slowDown = KeyEvent.VK_DOWN;
    private final Thread thread;
 
    private float speed = 0f;
    
    private final Set<Integer> pressedKeys = new HashSet<Integer>();
    private Matrix4f currentRotation = new Matrix4f();
    private Matrix4f currentRotationE = new Matrix4f();
    
    public Steuerung(TransformGroup rotatedTransformGroup, Flugzeug flugzeug, Spiel spiel, Enemy enemy)
    {
        this.myTransformGroup = rotatedTransformGroup;
        this.myFlugzeug = flugzeug;
        this.parent = spiel;
        this.theEnemy = enemy;
        currentRotation.setIdentity();
        currentRotationE.setIdentity();
 
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    updateMovement();
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }   
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
    
    private void updateMovement() {
        if (pressedKeys.contains(upKey)&& !pressedKeys.contains(downKey)){
            rotate(-0.1f, 0);
        }
        if (pressedKeys.contains(downKey)&& !pressedKeys.contains(upKey)){
            rotate(0.1f, 0);
        }
        if (pressedKeys.contains(leftKey)&& !pressedKeys.contains(rightKey)){
            rotate(0, 0.1f);
        }
        if (pressedKeys.contains(rightKey) && !pressedKeys.contains(leftKey)) {
            rotate(0, -0.1f);
        }
        if (pressedKeys.contains(slowDown) && !pressedKeys.contains(speedUp) && speed>=-0.05f) {
            speed-=0.001f;
        }
        if (pressedKeys.contains(speedUp) && !pressedKeys.contains(slowDown)&& speed<=0.15f) {
        	speed+=0.001f;
        }
        move();
        moveEnemy();
    }

	private void moveEnemy() {
		if(enemyTurn==50){
			xE = (float)Math.random()*(0.3f+0.3f)-0.3f;
			yE = (float)Math.random()*(0.3f+0.3f)-0.3f;
			rotateE(xE, yE);
		}
		else if (enemyTurn <90 && enemyTurn>50){
			rotateE(xE, yE);
		}
		else if (enemyTurn==90) enemyTurn=0;
		else enemyTurn++;
		
		Transform3D tempTransform1 = new Transform3D();
		Vector3f tempVector1 = new Vector3f();
		theEnemy.getSphere().getLocalToVworld(tempTransform1);
		tempTransform1.get(tempVector1);

		Transform3D tempTransform2 = new Transform3D();
		Vector3f tempVector2 = new Vector3f();
		theEnemy.getSphere2().getLocalToVworld(tempTransform2);
		tempTransform2.get(tempVector2);
		
		tempVector1.x += (tempVector1.x-tempVector2.x) * 0.13f;
		tempVector1.y += (tempVector1.y-tempVector2.y) * 0.13f;
		tempVector1.z += (tempVector1.z-tempVector2.z) * 0.13f;
		
		transE.setTranslation(tempVector1);
		transE.setAutoNormalize(true); 
		theEnemy.setTransform(transE );
		
	}

	private void rotateE(float angleX, float angleY) {
        Matrix4f m0 = new Matrix4f();
        m0.setIdentity();
        m0.rotX(angleX/4);
        Matrix4f m1 = new Matrix4f();
        m1.setIdentity();
        m1.rotY(angleY/4);
        Matrix4f result = new Matrix4f();
        result.mul(m0, m1);
        currentRotationE.mul(currentRotationE, result);
        transE = new Transform3D(currentRotationE);
		
	}

	private void rotate(float angleX, float angleY) {
        Matrix4f m0 = new Matrix4f();
        m0.setIdentity();
        m0.rotX(angleX/4);
        Matrix4f m1 = new Matrix4f();
        m1.setIdentity();
        m1.rotY(angleY/4);
        Matrix4f result = new Matrix4f();
        result.mul(m0, m1);
        currentRotation.mul(currentRotation, result);
        trans = new Transform3D(currentRotation);
    }
 
    @Override
    public void keyTyped(KeyEvent e){
    }
 
    @Override
    public void keyPressed(KeyEvent e){
        pressedKeys.add(e.getKeyCode());
    }
 
    @Override
    public void keyReleased(KeyEvent e){
        pressedKeys.remove(e.getKeyCode());
    }
	
	private void move(){
		
		Transform3D tempTransform1 = new Transform3D();
		Vector3f tempVector1 = new Vector3f();
		myFlugzeug.getSphere().getLocalToVworld(tempTransform1);
		tempTransform1.get(tempVector1);

		Transform3D tempTransform2 = new Transform3D();
		Vector3f tempVector2 = new Vector3f();
		myFlugzeug.getSphere2().getLocalToVworld(tempTransform2);
		tempTransform2.get(tempVector2);
		
		tempVector1.x += (tempVector1.x-tempVector2.x) * speed;
		tempVector1.y += (tempVector1.y-tempVector2.y) * speed;
		tempVector1.z += (tempVector1.z-tempVector2.z) * speed;
		
		trans.setTranslation(tempVector1);
		trans.setAutoNormalize(true); 
		myTransformGroup.setTransform(trans);
	}

}


Die beiden zu bewegenden Objekte sind Flugzeug und Enemy. Eigentlich müssten beide Ihre eigenen Bewegungen ausführen können, ohne sich zu beeinflussen (es gibt ja trans und transE, sowie currentRotation und currentRotationE). Solange siche Enemy nicht dreht klappt das auch, aber sobald rotateE() aufgerufen wird lässt sich Flugzeug nicht mehr vernünftig steuern.

Ich hoffe jemand von euch sieht warum das so ist.
Wie immer vielen Dank im Vorraus...
 
S

Spacerat

Gast
Öhm... er 'nu wieder... XD
Hatte ich schon erwähnt, dass du dein Konzept von Grund auf ändern solltest? Normalerweise ist's in 3D-Welten so, dass jedes Objekt eine eigene 4*4-Element-Matrix (Transform3D) hat. Mit jedem Renderdurchlauf iteriert man nun über "lebende" Objekte und multipliziert die View-Matrix mit der jeweiligen Objekt-Matrix und erhält so eine Matrix, an welcher das Objekt gezeichnet werden soll.
Matritzen bestehen aus den Komponenten Translation, Scale und Rotation. Das bedeutet, dass eine solche Matrix Grösse, Lage und Position beinhaltet. Also: Egal, was so ein Objekt sonst noch für Methoden hat, wichtig sind auf jeden Fall [c]setPosition(x, y,z)[/c], [c]setRotation(angle, x, y, z)[/c] und [c]getTransform()[/c] welche schliesslich die Objekt-Matrix liefert. Es gibt zwar noch [c]setScale(x, y, z)[/c], aber das ist erstmal nicht wichtig. Ganz banal für Java3D also
Java:
public abstract class J3DObject
extends TransformGroup
{
  private final Tramsform3D transform;

  protected Java3DObject()
  {
    this(new Transform3D());
  }

  private Java3DObject(Transform3D transform)
  {
    super(transform);
    this.transform = transform;
    setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  }

  public void seRotation(float angle, float x, float y, float z)
  {
    transform.setRotation(new AxisAngle4f(x, y, z, angle));
  }

  public void setPosition(float x, float y, float z)
  {
    transform.setPosition(new Vector3f(x, y, z));
  }

  public void getTransform()
  {
    return new Transform3D(transform);
  }
}
Wie du siehst, ist die Objekt-Matrix völlig von äusseren Zugriffen isoliert, so dass man halt gezwungen ist, zum Positionieren usw. die dafür vorgesehenen Methoden zu verwenden. Was ich in Java3D im übrigen vermisse sind Methoden zum echten Bewegen, sprich entsprechende additive [c]rotate()[/c]-, [c]scale()[/c]- und [c]translate()[/c]-Methoden, damit Position, Rotation und Scale nicht auch noch wo anders gespeichert werden müssen. Aber das ist halt Java3D... komplizierter geht's nicht.
[EDIT]Das Beispiel ist im übrigen auch keineswegs das Mass der Dinge. Im Zweifelsfalle würde das nämlich viel zu oft "new SonstWas()" bedeuten, womit man höchstens höchstens (das steht aus gutem Grund zweimal hier ;)) den GC beschäftigt. Normalerweise entwickelt man hier per Object-Reuse.[/EDIT][EDIT]Ach dus Sch... Was ist das denn? Ich experimentiere hier grad' ein bissl' und da fällt mir auf, das sich die transform der TransformGroup ja nicht mal mit aktualisiert... aaaahhhhh[/EDIT][EDIT]Ok... update... soweit so gut... vorerst[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Normalerweise ist's in 3D-Welten so, dass jedes Objekt eine eigene 4*4-Element-Matrix (Transform3D) hat. Mit jedem Renderdurchlauf iteriert man nun über "lebende" Objekte und multipliziert die View-Matrix mit der jeweiligen Objekt-Matrix und erhält so eine Matrix, an welcher das Objekt gezeichnet werden soll.

Sowohl den Hinweis als auch den Code würde ich mit Skepsis betrachten. Java3D ist eben Szenegraph-basiert, und mit einer "View-Matrix" hat man da i.a. nicht mehr viel zu tun. BTW: "Viele kleine" Objekte erzeugen ist spätestens bei Java7 dank escape analysis gar nicht mehr so kritisch... aber... zugegeben, ich bin auch noch teilweise beim "alten Muster" :oops:
 
S

Spacerat

Gast
Sowohl den Hinweis als auch den Code würde ich mit Skepsis betrachten.
Also den Code kann man auch nur skeptisch betrachten, vor allem die Zeilen 28 bis 31 - verdammtes copy paste :oops:
BTW: "Viele kleine" Objekte erzeugen ist spätestens bei Java7 dank escape analysis gar nicht mehr so kritisch... aber... zugegeben, ich bin auch noch teilweise beim "alten Muster" :oops:
[OT]Was bitte hat Escapeanalyse mit Object-Reuse zu tun? Sie zeigt der JVM doch nur, ob Objekte ausserhalb anderer Objekte erreichbar sein können, nicht aber ob sie noch erreichbar sind. Ich erinner mich in dieser Beziehung da gerade an unser Thema mit BufferedImages - Weisst du wie das SunWritableRaster feststellt, ob sein Datenpuffer "stolen" ist, bzw. sein könnte? Bislang hatte dieser Mechanismus für mich allerdings noch keinen Namen, dank dir, jetzt schon (Obwohl, das SWR hat diese "Analyse" schon lange bevor Java 1.6_14 durchgeführt). Objekte, die ausserhalb eines Anweisungsblocks weiterverwendet werden können belasten den GC immer noch. Das bedeutet, du darfst dir in einem solchen Block, soviele Objekte erstellen, wie du willst, unescaped Objects sind beim Verlassen eines solchen sofort Geschichte, da braucht's nicht mal einen GC (mit dem Rücksetzen eines Stapelzeigers in Assembler vergleichbar). Escaped Objects aber liegen in ganz anderen, meist viel globaleren Adressbereichen, im Zweifelsfalle vllt. irgend was mit "A4-Relativ" (Amiga-Assembler) vergleichbarem (dem Java-Heap), jedenfalls weis ich, woher mir diese Techniken bekannt vor kommen, ich aber keinen Namen dazu habe. So neu sind die also gar nicht.[/OT]
 

Marco13

Top Contributor
Da der Thread erledigt ist, sind ein, zwei OT-Nachträge hofentlich OK...:

Was bitte hat Escapeanalyse mit Object-Reuse zu tun?

Ich erinnere mich an meine ersten Programme mit Java3D (und allgemein zeitkritische Berechnungen, z.B. mit der Vecmath), wo man sowas wie
Java:
float compute(Vector3f v0, Vector3f v1)
{
     Vector3f t0 = new Vector3f();
     Vector3f t1 = new Vector3f();
     t0.set(v0); 
     t0.normalize();
     t1.set(v1); 
     t1.normalize();
     return t0.dot(t1);
}
für die maximale Performance (und JA, es ging da wirklich um das zweitkritischste, was es gibt!) tunlichst als
Java:
private static final Vector3f t0 = new Vector3f();
private static final Vector3f t1 = new Vector3f();
float compute(Vector3f v0, Vector3f v1)
{
     //Vector3f t0 = new Vector3f(); // Rausgezogen
     //Vector3f t1 = new Vector3f(); // Rausgezogen
     t0.set(v0); 
     t0.normalize();
     t1.set(v1); 
     t1.normalize();
     return t0.dot(t1);
}
schreiben sollte. Aber wie du schon geschrieben hast: Mit der Escape Analysis wird erkannt, dass diese Vektoren nur lokal gebraucht werden. D.h. sie werden auf dem Stack erzeugt, und belasten den GC nicht (Genaugenommen können in diesem Fall sogar sämtliche Berechung ge'inline't werden, aber das ist nochmal ein anderer Punkt).

Die Kurve zum BufferedImage krieg' ich jetzt so spontan nicht (und das DirectBufferedImage liegt immernoch in der Queue ... sorry.... :oops: obwohl ich schon überlegt habe, ob man das nicht im Zusammenhang mit jcuda.org - JNpp irgendwie verwursten könnte... Ich muss mir erst nochmal deine Erkenntnisse aus dem DirectBufferedImage-Thread und (vor allem!) den dazugehörigen Code durchlesen...). Aber für das "managed" oder "stolen" wird keine Escape Analysis verwendet. Zumindest gibt es in "SunWritableRaster" eine ganz lapidare Methode "setStolen" (die ich in diesem Beitrag unten schonmal erwähnt hatte). Es könnte zwar theoretisch sein, dass sich da mit Java7 was ändert, aber ... das Raster ist ja NIE nur in einer Methode vorhanden (also nicht lokal, und kann nicht auf dem Stack erstellt werden), deswegen sehe ich zumindest keine Verwandtschaft zur Escape Analysis. :bahnhof:
 
S

Spacerat

Gast
Dieses lapidare "setStolen()" macht nur häufig keinen Sinn, weil die JVM trotzdem merkt, ob der Buffer noch zu erreichen ist, allerdings macht sie das an existierenden Klassen fest. BufferedImages, die keine bekannte ColorModel-SampleModel-Raster-Struktur haben sind manchmal sogar auch dann lahm, wenn "stolen" false ist, erst recht dann, wenn ein DirectBuffer verwendet wird. Das mag jetzt zwar wenig mit der sogenannten Escape-Analyse zu tun haben aber diese ist halt auch nur ein Verfahren zur Unterscheidung zwischen Daten bekannter (offensichtlicher) und unbekannter Herkunft, um herauszufinden, ob man die Daten entweder schnell abarbeiten kann oder aber ständig validieren muss.

Dein "was man tunlichst machen sollte" oben ist hoffentlich nur auf die schnelle zusammen gefrickelt, denn so wäre der Preis für maximale Performance nämlich unter Umständen Dateninkonsistenz. "t0" und "t1" müssten nämlich Threadsicher gemacht werden und das auf statische Objekte? ???:L
Ich löse das immer so:
Java:
float compute(Vector3f v0, Vector3f v1, Vector3f t0, Vector3f t1)
{
     t0.set(v0); 
     t0.normalize();
     t1.set(v1); 
     t1.normalize();
     return t0.dot(t1);
}
In diesem Fall geht's zwar nicht, aber mein Hammer für (automatisches) Object-Reuse ist folgendes:
Java:
Object getData(Object outData)
{
  if(outData == null) {
    outData = new int[1]; // Standardtyp z.B. int[1]
  }
  if(outData instanceof int[]) {
    int[] tmp = (int[]) outData;
    int[0] = this.color // Klasse ist vllt. eine Art Farbmodell
  } else if(outData instanceof SomeKindOfOtherSupportedType) {
    // fill outData in other ways...
  } else {
    throw new IllegalArgumentException("type of outData not supported");
  }
  return outData;
}

// Verwendung wie folgt:

Object data = null;
for(int n = 0; n < width; n++) {
  data = getData(data); // diese Zuweisung ist lebenswichtig!
  // do something with data
}
Das kommt davon, wenn man sich eindringlich mit z.B. BufferedImages beschäftigt, da wird's im Prinzip überall so gemacht. :D Allerdings muss man in all den Klassen, wo man es so macht abrufbar machen, wie sich Object zusammensetzt. Natürlich klappt das auch mit anderen Klassen, z.B. so, wie oben mit Transform3D.
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Zu "setStolen": Ich hatte diese Methode nur auf meiner Odyssee durch die Sun-BufferedImage-Klassen entdeckt, und es schien, als wäre das der einzige Unterschied zu dem, was man auch mit der öffentlichen API erreichen kann, aber das müßte ich auch erst nochmal auffrischen.


Dein "was man tunlichst machen sollte" oben ist hoffentlich nur auf die schnelle zusammen gefrickelt, denn so wäre der Preis für maximale Performance nämlich unter Umständen Dateninkonsistenz.

Nein... die Methode ist eben private und als "nicht threadsicher" gekennzeichnet. (Wenn sowas im Anwendungsfall 2% Geschwindigkeitsvorteil gebracht hat, war es das wert...).


Ich löse das immer so:

Das ist eine Option - verschiebt die Frage aber ggf. nur einen Methodenaufruf weiter nach oben ;)


In diesem Fall geht's zwar nicht, aber mein Hammer für (automatisches) Object-Reuse ist folgendes:

Den konkreten Anwendungsfall konnte ich daran zwar nicht erkennen, aber allgemein gibt es verschiedene "Muster", mit denen man ""Optimierungen"" machen kann (oder konnte) um dem GC das Leben leichter zu machen. Einige davon werden in Zukunft vielleicht obsolet. Bleibt nur zu hoffen, dass sie sich nicht als nachteilhaft herausstellen (was durchaus sein kann...)
 
S

Spacerat

Gast
Den konkreten Anwendungsfall konnte ich daran zwar nicht erkennen...
???:L Schau' dir bei Zeiten ruhig noch mal die BufferedImage-Klasse - insbesondere die Methode [c]setRGB(int x, int x, int w, int h, int[] pixels, int offset, int scansize)[/c] und dann diverse Colormodelle und vllt. auch noch einige Samplemodelle an, da wird das exxessiv verwendet. Oder noch viel besser... probier's aus. Vllt. hasts ja nicht gesehen, aber outData wird nur einmal zugewiesen. Diese so über alle Maße lebenswichtige Zuweisung im äusseren Anweisungsblock dient nur sehr nebensächlich dazu, das Objekt dort verfügbar zu machen (es ist dort längst verfügbar, es wurde ja dort definiert ;)) sondern mehr dazu, es in den folgenden Aufrufen genau so übergeben zu können, wie man es bekommen hat, also zumindest nicht mehr als Nullreferenz wie beim ersten Aufruf. Die Klasse Objekt verwendet man nur, wenn der Rückgabetyp nicht vorhersehbar ist (Images können z.B. mehrere Bänder haben, dann kämen Arrays mit mehr als nur einem Element zurück). Wenn der Datentyp aber feststeht, kann man das Objekt durchaus auch im äusseren Anweisungsblock initialisieren. In Sachen 3D schiebe ich auf diese Art ein float[16], ein double[16] oder gar entsprechende nio.Buffer als Matrix durch komplette Objektbäume oder besser durch die gesamte Szene. Deswegen wundert es mich ja auch, warum es in Java3D nicht so toll funktioniert. Ständig muss man dort die Transform3D einer TransformGroup neu setzen. Was für'n Krampf.
 

Marco13

Top Contributor
Ja, bestimmte Parallelen zum Code aus den BufferedImage-Klassen hatte ich erkannt. Irgendwann hatte ich auch mal etwas verdutzt geschaut, als ich gesehen habe, dass dort in solchen Fällen anscheinend öfter mal ein int[1] erstellt wird, um einzelne Pixel abzuholen :autsch: Aber ich hätte sowohl den geposteten als auch den BufferedImage-Code noch genauer vergleichen müssen. Ich fand es aber auch immer schwierig, herauszufinden, von wo bestimmte Methoden aus Raster & Co aufgerufen werden - solange man nicht den gesamten Code in eine IDE packt...
 
S

Spacerat

Gast
Bleibt nur zu hoffen, dass sie sich nicht als nachteilhaft herausstellen (was durchaus sein kann...)
Auf jeden Fall... hoffen! Denn wenn sich diese (Hmm, hab' mal wieder keinen Namen dafür - nenn' ich's mal...) Shared-Instance-Methode als solches herausstellen sollte, wäre das nicht nur für Java2D Bilder fatal, sondern auch für meine Methode zum Rendern einer OpenGL-Szene...
Java:
void renderObject(Link3D object, DoubleBuffer transform) {
  transform = (DoubleBuffer) object.getTransform(transform);
  glPushMatrix();
  glMultMatrix(transform);
  object.display();
  for (Link3D l : object) {
    renderObject(l, transform);
  }
  glPopMatrix();
}
Link3D ist dabei eine Klasse, welche auf ein echtes Object3D linkt. Echte Object3D können so mehrfach verwendet werden - jedes halt mit eigener Transformation, belegen aber sonst nur einmal Speicher.
 

Marco13

Top Contributor
Hmja - auch da kann ich mir den Anwendungsfall und den größeren Kontext nicht ganz vorstellen. Aber welche "Tricks" man sich auch immer für Optimierungen überlegt hat: Ich glaube, dass allgemein der Fall, dass so ein "Trick" durch eine neue JVM oder einen neuen JIT langsamer wird unwahrscheinlicher ist, als dass ein anderer Trick danach schneller sein könnte, als der alte.

Im Zweifelsfall gilt in den meisten Fällen ja immernoch die Regel Write Dumb Code (durch die Oracle-Übernahme leider nur noch im Google cache...)
 
S

Spacerat

Gast
Der Anwendungsfall ist Klar. Halbautomatisches Object-Reuse mit bekannten oder unbekannten Transferobjekten (Buffer oder Arrays). Du weisst nicht, was für Daten zurückkommen? Frag' die Datenklasse nach dem Transfertypen. Du weisst nicht, wieviele Elemente pro transfer zurückkommen? Frag' die Datenklasse nach der Länge. Du weisst nicht, ob Buffer erlaubt sind? Erstelle einen mit den von der Datenklasse geforderten Daten (Transfertyp und Länge) und lass ihn von der Datenklasse befüllen. Wird das Transferobjekt nicht unterstützt fliegt meistens 'ne Exception. Z.B. braucht man es bei DataBuffern, Color- und SampleModellen (kurz gesagt bei Sun-Standard-Rastern für Bilder) mit Buffern gar nicht erst versuchen, wie gesagt, ich finde, das ist nicht mehr zeitgemäss. Deswegen kann man es bei meinen überarbeiteten Klassen des ständig besser werdenden 3D-APIs meiner schon oft erwähnten Dateitypenerkennung auch getrost verwenden, die Implementation war auch schwierig genug.
Schau dir doch mal die ganzen VecMath-Klassen an, was da dran faul sein könnte. Schön, man kann z.B. jedes einzelne Element einzeln ändern und Objekt-Reuse wird sogar auch unterstützt. Aber diese ganzen dafür erforderlichen Methoden... (z.B. 17 * set bei Matrix4f) ist das "Good will hunting"?
 

Marco13

Top Contributor
... das ist nicht mehr zeitgemäss. Deswegen kann man es .... auch getrost verwenden, die Implementation war auch schwierig genug.
Irgendwie kann ich dir hier nicht mehr ganz folgen, bzw. es klingt widersrpüchlich, aber ich bin im Moment auch nicht ganz fit...

Die Vecmath... das "faulste" daran finde ich eigentlich die publich fields ... (Vector3f x,y,z & Co). Was wäre die Alternative zu den settern? Immutable Objekte? Hätte theoretische Vorteile, aber wäre aus Effizienzgründen (speziell zu der Zeit, als die entwickelt wurden - aber ggf. auch heute noch) kaum praktikabel....
 
S

Spacerat

Gast
Hier mal ein minimalistisches KSKB, mit einer Matrix. Die mult-Methode ist vllt. nicht ganz korrekt, aber darum geht's ja auch nicht. Es geht ums Datenschaufeln per set und get mit Object-Reuse, schnell, effizient, komfortabel und vor allem performant, speichersparend und GC entlastend.
Java:
import java.util.ArrayList;
import java.util.List;


public class TransferObjectDemo
{
	public enum TransferType
	{
//		BYTE,
//		SHORT,
//		CHAR,
//		INT,
//		LONG,
//		FLOAT,
		DOUBLE, // zu Demonstrationszwecken reicht DOUBLE
	}

	private static final double[] IDENTITY = {
		1.0, 0.0, 0.0, 0.0,
		0.0, 1.0, 0.0, 0.0,
		0.0, 0.0, 1.0, 0.0,
		0.0, 0.0, 0.0, 1.0,
	};

	private final double[] data = new double[16];

	private TransferObjectDemo(double[] initial)
	{
		setData(initial);
	}

	private TransferObjectDemo()
	{
		loadIdentity();
	}

	public void loadIdentity()
	{
		setData(IDENTITY);
	}

	public int getNumElements()
	{
		return 16;
	}

	public TransferType getTransferType()
	{
		return TransferType.DOUBLE;
	}

	public boolean supportsBuffer()
	{
		return false;
	}

	public void setData(Object inData)
	{
		System.arraycopy(inData, 0, data, 0, 16);
	}

	public Object getData(Object outData)
	{
		if(outData == null) {
			outData = new double[16];
		}
		System.arraycopy(data, 0, outData, 0, 16);
		return outData;
	}

	public void mult(Object inData)
	{
		double[] tmp = (double[]) inData;
		for(int n = 0; n < 16; n++) {
			data[n] *= tmp[n];
		}
	}

	public static void main(String[] args)
	{
		List<TransferObjectDemo> renderTree = new ArrayList<TransferObjectDemo>();
		for(int n = 0; n < 2000; n++) {
			renderTree.add(new TransferObjectDemo(createRandomArray()));
		}
		Object trans = null;
		TransferObjectDemo view = new TransferObjectDemo();
		for(int n = 0; n < 100; n++) {
			view.loadIdentity();
			for(TransferObjectDemo t : renderTree) {
				trans = t.getData(trans);
				view.mult(trans);
			}
		}
	}

	private static double[] createRandomArray()
	{
		double[] rc = new double[16];
		for(int n = 0; n < 15; n++) {
			rc[n] = Math.random();
		}
		rc[15] = 1.0;
		return rc;
	}
}
Kannst in Zeile 91 ja mal spasseshalber einen Haltepunkt setzen, um zu zählen, wie oft trans instanziert wird. Aber vor der ersten Ausführung des Programms raten, wie lange es wohl braucht un 200000 4*4 Matritzen zu Multiplizieren. Kannst auch mit den Zahlen ein wenig experimentieren. Davon bekommt man Experimentierung... ich mein' Experience... oder auch Erfahrung. XD
 

Marco13

Top Contributor
Hmja... um die Performance beurteilen zu können, müßte man das zu einem Microbenchmark aufbohren. An sich spricht ja nichts gegen dieses Muster - z.B. bei Bildern ist das wohl das flexibelste, was man machen kann:
Java:
// Writes the data into the given output image and and returns the 
// outputImage. If outputImage is null, then a new object is created 
// and returned
BufferedImage filter(BufferedImage inputImage, BufferedImage outputImage) { ... }
Jedem steht es frei, dort zu reusen oder sonstwas zu machen.

Aber abgesehen von einigen Innereien der BufferedImage/Raster/ColorModel-Sachen würden mir nicht viele Fälle einfallen, wo man das "Object" nicht durch irgendwas spezifischeres ersetzen könnte (ggf. mit Generics - die gab es damals noch nicht... (Wir hatten ja nichts, damals ... ;)) )

Vielleicht würde es sich doch langsam lohnen, den Teil nach dem "28.04.2012 09:41" Beitrag (rein der Ordnung halber) abzutrennen... (Mit welchem Titel auch immer ;) )
 
S

Spacerat

Gast
Jedem steht es frei, dort zu reusen oder sonstwas zu machen. ... Vielleicht würde es sich doch langsam lohnen, den Teil nach dem "28.04.2012 09:41" Beitrag (rein der Ordnung halber) abzutrennen... (Mit welchem Titel auch immer ;) )
Naja, abtrennen vllt. nicht, eigentlich ist doch alles darüber gesagt. Aber vllt. könnte man ein neues Thema eröffnen, in welchem die Frage nach dem "sonst was" geklärt wird. Ehrlich gesagt, ist meine Art des Object-Reuse nämlich zuweilen unheimlich umständlich zu implementieren, erst recht, wenn man flexibel sein will.
 

Marco13

Top Contributor
Hm... Vielleicht ist es diese Flexibilität, von der ich mir gerade nich vorstellen kann, was damit gemeint ist... Und auch das "übergeordnete" Ziel des KSKBs... Also, im schlimmsten Fall (z.B. wenn die bei 10000 Objekten die TransferTypes abwechselnd Float und Double sind) bringt das ja nichts... und NOCH weiter übergeordnet die Frage, ob die gesparten Objekterzeugung die Mühen wert sind, die sich aus der Verwendung von 'Objects' den damit verbundenen Typ-Checks und der wiederum damit verbundenen "Infrastruktur" ergeben. (Ich hab' bei meiner ""Rendering-Enginge"" einfach überall dumm-dreist die Matrix4f's rumgereicht - wenn DAS wirklich das Bottleneck ist... .... ... muss man eben komplexere Modelle rendern :D )
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Mein Jump and Run charakter bewegt sich nicht mehr rückwärts... Spiele- und Multimedia-Programmierung 0
Blender3D VLCJ Video lässt sich nicht mehr abspielen nach mysql Installation Spiele- und Multimedia-Programmierung 1
Q Mehr objekte darstellen als Pixel vorhanden Spiele- und Multimedia-Programmierung 6
Androbin mehr-dimensionale(n) Array(s) "drehen" Spiele- und Multimedia-Programmierung 8
B Minecraft mehr Ram zuweißen Problem Spiele- und Multimedia-Programmierung 0
B j3d Rotation um mehr als eine Achse Spiele- und Multimedia-Programmierung 9
Haave Mehr Abstraktion bei Spieleinstellungen Spiele- und Multimedia-Programmierung 2
N Schlieren und Ruckeln, weiss nicht mehr weiter.... Spiele- und Multimedia-Programmierung 5
M JOGL - Mehr als nur ein Canvas - Texturpool Spiele- und Multimedia-Programmierung 7
Steev KeyPressed:Tab wird nicht mehr weitergeleitet Spiele- und Multimedia-Programmierung 2
S Hilfe: Ich sehe durch die ganze Api's nicht mehr durch! Spiele- und Multimedia-Programmierung 15
F OrbitBehavior empfängt keine Mouseevents mehr Spiele- und Multimedia-Programmierung 2
S Sudoku Solver funktioniert beim 2. Aufruf nicht mehr Spiele- und Multimedia-Programmierung 11
pcfreak9000 Objekt-Vorlagen Spiele- und Multimedia-Programmierung 0
Arif Maus-Objekt im Player Klasse implementieren !? Spiele- und Multimedia-Programmierung 2
H Objekt der Klasse A in der Klasse B verwenden und manipulieren Spiele- und Multimedia-Programmierung 6
M [JOGL] Maus über einem gezeichnetem Objekt abfragen? Spiele- und Multimedia-Programmierung 5
U Kann nur ein Objekt mit LWJGL rendern Spiele- und Multimedia-Programmierung 2
kaoZ Graphics Objekt liefert null Spiele- und Multimedia-Programmierung 14
E Java3D Objekt skalieren per JSlider/JButton Spiele- und Multimedia-Programmierung 10
D Probleme mit objekt initializirung mit Mouselistener Spiele- und Multimedia-Programmierung 10
S Java3D: Primitives zu einem Objekt kombinieren Spiele- und Multimedia-Programmierung 7
T LWJGL 3D Objekt Collision: Wie? Spiele- und Multimedia-Programmierung 11
S Wie erkennt ein Objekt ein anderes? Spiele- und Multimedia-Programmierung 7
G Hindernis vor Objekt erkennen Spiele- und Multimedia-Programmierung 6
W Java3D: Kanten die hinter einem Objekt liegen werden gezeigt Spiele- und Multimedia-Programmierung 2
S Graphics Objekt weiterreichen? Spiele- und Multimedia-Programmierung 4
H Eigenes 3D Objekt Spiele- und Multimedia-Programmierung 20
D 2D Objekt fragmentieren Spiele- und Multimedia-Programmierung 3
V Jogl: Objekt trotz Rotation immer in gleiche Richtung bewegen Spiele- und Multimedia-Programmierung 5
M [J3D]Dynamische Erzeugung vom Objekt Box Spiele- und Multimedia-Programmierung 5
Kr0e OpenGL .. Pixel Buffer Objekt oder Frame Buffer Object? Spiele- und Multimedia-Programmierung 2
B String zu Objekt einer eigenen Klasse casten Spiele- und Multimedia-Programmierung 13
N Objekt entgegengesetzt bewegen Spiele- und Multimedia-Programmierung 8
M BoundingBox ist nicht bündig am Objekt Spiele- und Multimedia-Programmierung 5
K Kanten anzeigen lassen in einem Shape3D-Objekt Spiele- und Multimedia-Programmierung 4
S geladenes Objekt -> Material Zuweisen. Spiele- und Multimedia-Programmierung 4
J Picking Selection auf ein Objekt begrenzen ! Spiele- und Multimedia-Programmierung 6
C Objekt bei Buttonklick zeichnen Spiele- und Multimedia-Programmierung 16
G JOGL: per Mausbewegung Objekt verschieben Spiele- und Multimedia-Programmierung 2
C Objekt zwischen 2 Geraden? Spiele- und Multimedia-Programmierung 3
D 3D Objekt entlang Geraden Spiele- und Multimedia-Programmierung 4
Quaxli Picking: Vom Shape3D zum eigentlichen Objekt Spiele- und Multimedia-Programmierung 2
G Objekt nicht ins negative oder null skalieren Spiele- und Multimedia-Programmierung 2
G Objekt verschieben Spiele- und Multimedia-Programmierung 6
G Textur laden auf ein eingelesenes 3D Objekt Spiele- und Multimedia-Programmierung 4
I ScaleInterpolator verschiebt Objekt immer in den Ursprung. Spiele- und Multimedia-Programmierung 2
V Objekt per Tastendruck anzeigen/verschwinden lassen? Spiele- und Multimedia-Programmierung 4
R Objekt mit cos/sin verschieben Spiele- und Multimedia-Programmierung 27
G Kein Licht in Box-Objekt Spiele- und Multimedia-Programmierung 2
K Ein 3D-Objekt mit Maus auswählen Spiele- und Multimedia-Programmierung 5
D Alpha Objekt Spiele- und Multimedia-Programmierung 8
H Kompliziertes 3D-Objekt Spiele- und Multimedia-Programmierung 16
G Einen gif oder jpg Datei aus einem Graphics Objekt o. JFrame Spiele- und Multimedia-Programmierung 2
C Wie kann ich ein Objekt auf Tastendruck vor & zurück bew Spiele- und Multimedia-Programmierung 3
M Position der ViewingPlatform als Point3d-Objekt? Spiele- und Multimedia-Programmierung 12
S 3D Objekt erstellen und darstellen Spiele- und Multimedia-Programmierung 4
G RotationInterp. setzt Objekt an Ursprungsposition zurück Spiele- und Multimedia-Programmierung 2
N Shape3D Objekt auf dem Bildschirm zentrieren Spiele- und Multimedia-Programmierung 2
B MarioKart Map rotieren? Spiele- und Multimedia-Programmierung 6
D 2D Pixelbild rotieren Spiele- und Multimedia-Programmierung 3
TulPe Würfel per Mausklick rotieren Spiele- und Multimedia-Programmierung 10
Creylon [LWJGL] 2D Sprite Rotieren/Drehen Spiele- und Multimedia-Programmierung 6
G Rotieren eines Objekts (2D) Spiele- und Multimedia-Programmierung 8
M [Java3D] Rotieren der Scene NICHT des POV Spiele- und Multimedia-Programmierung 4
Developer_X 3D Point rotieren lassen Spiele- und Multimedia-Programmierung 17
J Rotieren eines 2D Images endet in Java heap space Error Spiele- und Multimedia-Programmierung 15
W Affine Transformation, Rotieren eines Objekts Spiele- und Multimedia-Programmierung 2
S Schiff in Richtung der Maus rotieren - Problem :/ Spiele- und Multimedia-Programmierung 5
Tr3kk3r Kamera nur um x und y, nicht um z achse rotieren Spiele- und Multimedia-Programmierung 2
D Dreieck um den Mittelpunkt rotieren lassen Spiele- und Multimedia-Programmierung 9
P Rechteck rotieren und frontal anzeigen Spiele- und Multimedia-Programmierung 2
A Objekte nacheinander zeitgesteuert rotieren lassen Spiele- und Multimedia-Programmierung 4

Ähnliche Java Themen

Neue Themen


Oben