ClassCastException bei IndexedGeometryArray

Stefan1971HH

Mitglied
Hi,
ich habe eine Klasse "Triangle" (an derer statt ich wohl auch "IndexedTriangleArray" hätte verwenden können:
Java:
import javax.media.j3d.IndexedGeometryArray;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;

/**
 *
 * 
 */
public class Triangle extends IndexedGeometryArray{
    public Triangle(Point3f[]vertices, int vInd1, int vInd2, int vInd3, int vInd4,Color3f c){
    super(vertices.length, COORDINATES| NORMALS| COLOR_3,4);
            
            
            }
    
}

In einer anderen Klasse versuche ich mit folgendem Teil-Code, ein Objekt von "Triangle" zu erzeugen
und in meinen Szenengraphen einzufügen:
Java:
        Point3f[] vertices = new Point3f[3];
        vertices[0] = new Point3f(0, 0, 0);
        vertices[1] = new Point3f(2, 0, 0);
        vertices[2] = new Point3f(1, 2, 0);
        int[] indices = {0, 1, 2, 0};
TransformGroup TriTG = new TransformGroup();
        Triangle triangle;
        Color3f color = new Color3f();
        triangle = new Triangle(vertices, 0, 1, 2,3, color);
        triangle.setCoordinateIndices(0,indices);
        Shape3D shapeTri = new Shape3D(triangle);
        TriTG.addChild(shapeTri);
        contents.addChild(TriTG);

Dabei erhalte ich immer folgenden Fehler:
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.media.j3d.NodeComponentRetained cannot be cast to javax.media.j3d.GeometryArrayRetained
at javax.media.j3d.GeometryArray.<init>(GeometryArray.java:873)
at javax.media.j3d.GeometryArray.<init>(GeometryArray.java:611)
at javax.media.j3d.GeometryArray.<init>(GeometryArray.java:466)
at javax.media.j3d.IndexedGeometryArray.<init>(IndexedGeometryArray.java:168)
at Fachwerte.Triangle.<init>(Triangle.java:17)
at GUI.MyCanvasPanel.<init>(MyCanvasPanel.java:90)
at GUI.MainDisplayUI.initComponents(MainDisplayUI.java:54)

Die ersten beiden im Fehler genannten Zeilen sind der Super-Aufruf in Triangle
und der Triangle-Konstruktor-Aufruf in der anderen Klasse.
Eine ClassCastException bedeutet ja, dass man ein "nicht typkompatibles" Casting versucht hat, aber ich weiss nicht,
wo ich das hier getan haben soll. Ich weiss auch nicht recht, was es mit den beiden in der Meldung genannten
"...Retained" -Klassen auf sich hat. Kann das mit dem Rendering-Modus in Java3D zusammenhängen?
Wäre für Hilfe dankbar..

Gruß,
Stefan
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Hui, vor etlichen Jahren hatte ich mich da mal durch den Java3D-Quellcode gewühlt ... die dunkle Erinnerung ("dunkel" hier nur im Sinn von "verschwommen", nicht primär (aber teilweise auch :D ) im Sinn von "schlimm" :D) reicht nur noch für ein vages: "Die ganzen Retained-Sachen sind sozusagen 'interne' Datenstrukturen, die für die einzelnen Klassen vorgehalten werden - und sind so versteckt, dass man eigentlich nichts damit zu tun hat".

In diesem Fall... falls du vorhast, ein einzelnes Dreieck in einem IndexedGeometryArray zu speichern (und davon dann ggf. viele) wirst du damit in bezug auf die Performance keine Freude haben. Beschreib' vielleicht mal genauer, was du eigentlich vorhast. Als unmittelbare Problemlösung könnte man vorschlagen, mal zu versuchen, direkt von IndexedTriangleArray zu erben - das könnte zwar funktionieren, aber ... klingt immernoch sehr suspekt...
 

Stefan1971HH

Mitglied
Ich möchte verschiedenartige 3D Shapes erstellen können und wollte mir zunächst mal "handlichere"
Klassen bzw. Konstruktoren für die begrenzenden Flächen basteln,( z.B. für gleichmäßige Polygone, denen man dann nur noch die Seitenlänge und Eckenanzahl als Parameter übergeben muss), aus denen
man dann auch Körper bilden kann, die aus veschiedenartigen Polygonen zusammengesetzt sind.
Vielleicht versuche ich es tatsächlich erstmal so, das ich für Dreiecke von IndexedTriangleArray erbe
(bzw. für Vierecke von IndexedQuadarray) und Polygone mit mehr als vier Ecken als IndexedTriangleFanArray modelliere.-
Gruß
 

Marco13

Top Contributor
Ich finde, es klingt immernoch suspekt, aber das ist nur ein Bauchgefühl. Eigentlich sind GeometryArrays Strukturen, die sehr nah am Rendering in Java3D sind. Wenn du z.B. allgemeine platonische Körper modellieren willst, könnte es sich anbieten, dafür Interfaces zu defninieren, die "möglichst spät" ("nur" zum Rendern) in die jeweiligen *GeometryArrays gepackt werden. Aber vielleicht habe ich das Ziel falsch erfasst.
 

Stefan1971HH

Mitglied
Tatsächlich ist die Exception durch Erben von IndexedTriangleArray verschwunden.
Ich konnte jetzt eine Pyramide erstellen, habe aber Problme mit dem Färben der Seiten.
Gibt es eine Möglichkeit, den Seiten der Pyramide jweils "direkt" eine Farbe zuzuweisen,
oder wird diese immer anhand der Farben der beteiligten Vertices interpoliert?
Eigenartig finde ich auch, das die SetColor(s)-Methoden von IndexedTriangleArray
scheinbar alle nur direkt den Vertex-Array ansprechen können(und nicht den Vertex-Index-Array,
was doch eigentlich gerade der Sinn dieser Klasse ist).
(Hoffe, es ok, wenn ich nicht für jedes Folgeproblem einen neuen Thread aufmache).
 

Marco13

Top Contributor
Was du mit "direkt" meinst ist mir nicht ganz klar. Man muss üblicherweise schon den einzelnen Vertices die Farben zuweisen (und unter Umständen (das weiß ich nicht genau) müssen die Vertices dazu "doppelt" vorhanden sein, um das Interpolieren zu vermeiden, aber vielleicht kann man da auch mit der Appearance/Material was dengeln...)

Allgemein: Die aktive Community zu Java3D ist nicht sooo groß, und bei mir ist es auch schon lange her, dass ich aktiv was damit gemacht habe. Meine Antworten hier zehren von dem wenigen, was ich vor ein paar Jahren gemacht habe :D und Links auf "java2s": Dort findet man recht schnell zu vielen Themen Compilierbare Beispiele, wenn man nach sowas wie
java2s java3d vertex colors
(und vielleicht noch "IndexedTriangleArray" dazu) oder anderen Stichworten sucht. Sowas wie Geometry By Reference : Object Model3DJava verwendet die By-Reference-Methoden, die AFAIR depracated sind, aber vielleicht kann man die passenden (nicht-deprecateden) Teile da rausklauen. Wenn's nicht klappt, sag nochmal bescheid
 

Stefan1971HH

Mitglied
Mit "direkt" meinte ich, dass man eine (Dreieck)seite referenzieren kann, indem man die an
ihr beteiligten Vertices bzw. deren Indices der Methode SetColor(s) übergibt und damit
dann die Farbe zuweist, die die Seite erhalten soll. Auf diese Möglichkeit hatte ich gehofft,
aber sowasdann nicht gefunden. Ich seh mir jetzt mal deine Beispiele an, danke.
 

Marco13

Top Contributor
Ich hätte da jetzt auf GeometryArray (Java 3D 1.3.2) getippt, aber vielleicht habe ich die Frage immernoch falsch verstanden...

EDIT: Oder ging es um sowas wie
setTriangleColor(triangleIndex, color);
? Sowas gibt's AFAIK nicht, aber ggf. kannst du ja so eine praktische Methode in deiner Klasse anbieten, die sie dann passend aufgeteilt an die Vertices des ITA weiterreicht..
 

Stefan1971HH

Mitglied
Ich meine z.B. folgendes:
Ein Dreieck sei durch die Vertices vert[0],vert[1],vert[2] festgelegt (und es verweisen vertInd[0] usw. wiederum auf diese Vertices). Nun möchte ich, dass dieses Dreieck rot wird. Gibt es eine Methode, die die dreiVertices bzw.Indices sowie die Farbe als Parameter nimmt und meinen Wunsch erfüllt?
Anscheinend kann ich nur jedem Vertex eine Farbe zuweisen. Bezogen auf dieses eine Dreieck könnte man
nun zwar diese drei Vertices alle rot machen, aber diese sind ja auch an anderen Dreiecken beteiligt, für die sie andere Farben haben sollten.
 

Marco13

Top Contributor
Das meinte ich oben mit
und unter Umständen (das weiß ich nicht genau) müssen die Vertices dazu "doppelt" vorhanden sein

Ich kenne (und kannte selbst als ich es noch "aktiv(er)" benutzt habe) nicht jedes Detail der API auswendig ;) Und gerade GeometryArray und seine Sub- und Superklassen sind ja ... nun, Monster mit hunderten Methoden..., und wenn man nicht wirklich low-level Geometrie nach ganz bestimmten Kriterien zusammenbauen will, kommt man selbst damit kaum in Berührung...

Nebenbei: Es ist so, dass einige Grafikbibliotheken und Formate sich festlegen, dass es für die Vertices selbst, die Vertexfarben, die Vertexnormalen etc. nur EINEN Index-Satz gibt - dass also ein Dreieck durch die indizes (0,1,2) beschrieben ist, und dieselben indizes dann für die vertices selbst als auch für die Farben verwendet werden. Das kann eklig sein: Das OBJ-Dateiformat ermöglicht z.B. "gemischte" Index-Sätze, d.h. ein Dreieck kann dabei aus den Vertices 0,1,2 bestehen, aber die Texturkoordinaten (analog zu Farben) mit den Indizes 0,1,99 rerferenzieren. Wenn man das einlesen und mit OpenGL darstellen will, ist das ein Krampf, weil OpenGL erstmal von einheitlichen Index-Sätzen ausgeht (auch wenn man vielleicht irgendwie mehrere angeben kann, aber es ist eben fummelig).

Aber zur eigentlichen Frage: Nach kurzem Scrollen über die langen, langen Klassendokus fiel mir die Methode
http://download.java.net/media/java3d/javadoc/1.3.2/javax/media/j3d/IndexedGeometryArray.html#setColorIndices%28int,%20int[]%29


ins Auge: Es könnte sein, dass man gezielt mehrere Index-Sätze verwenden kann, so dass man (für deinen Fall z.B.) vielleicht sagen kann:
Dreieck 0: Vertices 0,1,2, Farben 0,1,2
Dreieck 1: Vertices 0,3,4, Farben, 9,10,11
(so dass der Vertex 0 einmal Farbe 0 und einmal Farbe 9 hat), aber ... das müßte ich auch erst ausprobieren....
 

Stefan1971HH

Mitglied
Ja, diese Methode hatte ich auch gesehen, aber dort muss man plötzlich die Farben indizieren, und
ich habe noch nicht recht durchschaut, wie man einer Farbe einen Index zuweisen kann. Ich finde die
Formulierungen in den Klassendokumentationen auch des öfteren etwas unklar, insbesondere ist oft schwammig, ob mit Index der Vertex-Index oder der Vertex-Index-Index gemeint ist. Bei meinen ersten
Versuchen der Farbzuweisung hatte ich immer Array-out-ouf-Bounds Exceptions, weil ich die Farben über
den Vertex -Index-Array zuweisen wollte (der Länge 12 hat), die setColors-Methoden sich aber auf den Vertex-Array mit Länge 4 beziehen.
 

Stefan1971HH

Mitglied
Eine Idee wäre evtl. noch, die Dreiecke, die die Pyramide bilden, als separate Geometry-Objekte anzulegen und nacheinander dem Shape3D Objekt hinzuzufügen. Dann sollte es wohl möglich sein, pro Dreieck demselben Vertex eine andere Farbe zuzuweisen. Wäre aber natürlich arg umständlich...
Da das Anliegen, eine Fläche zu färben, nicht so ausgefallen sein kann, sollte es doch wohl eine praktischere Lösung geben.
Eigentlich fallen Farben, wie du schon angedeutet hast, ohnehin eher in den Zuständigkeitsbereich
von Appearance - aber warum haben dann all diese Geometry-Abkömmlings-Klassen mysteriöse
setColor-Methoden?
Gibt es irgendwo den Source-Code des Standard Color-cubes von Java3D? Da scheint die Färbung
ja ganz gut gelungen.
 

Marco13

Top Contributor
Den Source Code von ColorCube gibts - wer hätte das gedacht - auf Java2s: ColorCube.java : 6.0-JDK-Modulesjava-3dorgjdesktopj3dexamplesmorphingJava Open Source :D (Ist anscheinend ein anderer, als der "normale", der bei Java3D irgendwo rumliegt, aber vielleicht hilft er als Inspiration - er sieht auch SEHR übersichtlich aus).

Es wäre wirklich gut zu wissen, was genau du aufbauen willst. Wenn es um eine handvoll Pyramiden und Dodekaeder geht, ist's kein Problem sich da die "bequemste" Variante rauszusuchen, wo man mehrere einzelne Dreiecke als Shape3Ds zusamenbaut. Wenn man davon dann aber 1000 oder 10000 oder mehr Stück darstellen will, bekommt man vermutlich (!) deutlich (!) schneller ein Performance-Problem, als wenn man alles in einem Geometry-Objekt unterbringt.
Und eine Abstraktionsstufe höher: Wenn man die einzelnen Objekte oder gar Seitenflächen dann z.B. noch anklicken können will, wäre das u.a. wiederum deutlich (!) leichter, wenn es einzelne Objekte wären, und NICHT alles in einer Geometry zusammengewurstet
 

Stefan1971HH

Mitglied
Ich soll ein Programm entwickeln, mit dem interaktiv Punkte, Flächen und Körper erzeugen und manipulieren kann.
Genauer gesagt ein "Lern-Tool", mit dem man die Zusammenhänge zwischen Transformationsanweisungen
(sowie -matrizen) und damit korrespondierenden Änderungen erleben und besser verstehen kann.-
Mit meiner Pyramide hat jetzt analog zum Color-Cube folgenermaßen anscheinend geklappt:
Java:
public class TetrahedronBuilder extends TriangleArray{
    //dieEcken der Pyramide
    final float e = 0.3f;
    Point3f grd1 = new Point3f(0,0,0);
    Point3f grd2 = new Point3f(e,0,0);
    Point3f grd3 = new Point3f(e*0.5f,0f,-(float)Math.sin(60)*e);
    Point3f peak = new Point3f(0.15f, (float)Math.sin(57.7)*0.3f,(float)(e/3)*(float)Math.sqrt(6));
    Color3f red = new Color3f(1.0f, 0.0f, 0.0f);
    Color3f blue = new Color3f(0.0f, 0.0f, 1.0f);
    Color3f green = new Color3f(0.0f, 1.0f, 0.0f);
    Color3f cyan = new Color3f(0.0f, 1.0f, 1.0f);
    Color3f yellow = new Color3f(1.0f, 1.0f, 0.0f);
    Color3f magenta = new Color3f(1.0f, 0.0f, 1.0f);

    
    Point3f[]vertices = {
        
        //green side
        grd1, grd2, grd3,
        //red side
        grd1, grd2, peak,
        //magenta side
        grd2, grd3, peak,
        //yellow side
        grd3, grd1, peak
    };
   
      Color3f[] colors =  {
          green, green, green,
          red, red, red,
          magenta, magenta, magenta,
          yellow, yellow, yellow
        
    };
              
    public TetrahedronBuilder(){
     super(12, TriangleArray.COORDINATES | TriangleArray.COLOR_3);
     setCoordinates(0, vertices);
     setColors(0,colors);
     
    }}

Man kann also tatsächlich demselben Knoten mehrere Farben (jeweils eine andere
für jede an ihn grenzende Fläche) zuweisen, zumindest, wenn man "direkt" mit
dem Knotenarray arbeitet und nicht mit dem Index-Array arbeitet. Muss nochmal sehen, ob es möglich/
sinnvoll ist, dass auch mit einem IndexedArray hinzukriegen. Ich habe mich anhand des Manuals von
Michael Pfeiffer in Java3D eingelesen; dort wird ein IndexedArray als zumindest für die Geometry
praktischer/speichersparsamer empfohlen; ich hatte dort sogar den Eindruck gewonnen, dass derselbe
Knoten gar nicht in derselben Geometry mehrfach "direkt" (nicht über Indices-Array) gespeichert werden
kann.-
Nachdem dies aber erstmal gelöst ist (vielen Dank an dich), tritt wieder ein anderes Problem zurück in
den Vordergrund: Ich arbeite mit NetBeans (insbesondere wegen des GUI-Builders).Für die oben angedeutete
interaktive Steuerung des Javad3D Geschehens muss ein Canvas3D Objekt in eine Swing-GUI eingebettet werden.
Dies konfrontiert mich mit der altbekannten schlechten Verträglichkeit von Light- mit Heavyweightkomponenten.
Ich habe diverse Lösungsvorschläge gefunden, die im wesentlichen alle darauf basieren, von JPanel zu erben
und den Canvas3D in diesem *allein* unterzubringen. Ich habe es zwar geschafft, einen solchen erweiterten JPanel
der Palette des GUI-Builders und von dort meiner Benutzeroberfläche hinzuzufügen - dies führt aber ständig zu
Abstürzen von Netbeans. Wenn es gelingt, diese Komponente vor der Arbeit an den anderen Komponenten zu entfernen,
läuft alles stabil- allerdings führt meistens schon der Versuch dieses Entfernens zum Absturz. Hast du (oder auch ein
anderer freundlicher Leser) eine Idee, wie man dies stabiler lösen könnte? Ich habe schon mehrere Kombinationen von
Java- und Netbeansversionen probiert-ohne Erfolg. (Mein Programm selber läuft allerdings stabil).-danke
 

Marco13

Top Contributor
Spontan nicht, aber das könnte vielleicht einen eigenen Thread wert sein (ich arbeite i.a. nicht mit NetBeans... und ... halte allgemein nicht viel von solchen GUI-Buildern...). Zwar ist der konkrete Zusammenhang auch wieder sehr speziell, aber vielleicht weiß jemand allgemein was zu "heavyweight Canvas im NetBeans GUI-Builder" oder so...
 

Ähnliche Java Themen

Neue Themen


Oben