Eigener Graphics-Context

Steev

Bekanntes Mitglied
Guten Abend liebe Forengemeinde,

ich habe da mal eine Frage, bei der ihr mir hoffentlich weiterhelfen könnt.
Ich habe vor einiger Zeit eine kleine Game-Engine programmiert. Für die Renderung verwende ich ganz normal ein Graphics2D-Objekt, den ich über eine Rendermethode alle Zeichenobjekte erben lasse. Nun wollte ich gerne das Backend meiner Engine so umstellen, dass man einfach die Renderung auf OpenGL oder DirectX umschalten kann.
Also habe ich eine eigene Graphics-Interface und Klasse erstellt, die ich nun anstatt wie bisher Graphics2D an die Rendermethoden übergebe. Das funktioniert soweit auch. Nur bekomme ich leider seltsamme Seiteneffekte.
- auf meinem Rechner (Windows 7 AMD Phenom II X4, NVidia GeForce GTX 280, 8 GB RAM, DirectX 11, Java 6 u 18 (JDK)) werden Bilder sowie Rectangles gerendert, oval, arc, roundrect usw. werden nicht gerendert (!)
- auf meinem Virtuellen PC (Windows XP SP3) werden keine Bilder gerendert, dafür aber rect, oval, roundrect, arc usw.
- auf meinem Notebook (Windows XP SP3) wird alles gerendert

Aufgrund der verschiedenen Laufzeitverhalten verstehe ich nicht so ganz, was ich falsch gemacht habe.

Meine Graphics-Klasse mappt die (für mich) wichtigsten Graphics2D-Methoden (vorerst habe ich nur Swing implementiert). Zu diesem Zweck wird über eine setSource-Methode die "Kernel"-Instanz pro Rendervorgang (vor der Renderung) an die Graphics-Instanz übergeben und als Attribut gespeichert (Ich weis, sollte man nicht machen, geht aber nicht anders...). Während der Renderung wird dann über das gespeicherte Attribut gearbeitet.

Hier mal der Quellcode meiner Graphics-Klasse.
[Java]public class DefaultEGEGraphics implements EGEGraphics {

// public constant class attributes
/**
* A neutral affine transformation for reseting the transformation of the
* source-graphics.
*/
public static final AffineTransform EMPTY_TRANSFORM = new AffineTransform();

// private object attributes
private Graphics2D source;
private EGETransformation transformation;
private EGEVector i_vector;
private EGEFont font;
private EGEColor color;
private EGEComposite composite;
private Composite oldComposite;

// constructors
/**
* This constructor creates a new graphics-object that will be used for the
* internal rendering of ege. This constructor should only be used by the
* internal ege-rendering-classes.
*
* @param graphics
* the native java-swing graphics context that should be mapped.
*/
public DefaultEGEGraphics(Graphics2D graphics) {
setSource(graphics);
}

// implemented methods
public void clearRect(double x, double y, double width, double height) {
source.clearRect((int) x, (int) y, (int) width, (int) height);
}

public void clipRect(double x, double y, double width, double height) {
source.clipRect((int) x, (int) y, (int) width, (int) height);
}

public EGEGraphics create() {
return new DefaultEGEGraphics((Graphics2D) source.create());
}

public void drawArc(double x, double y, double width, double height, double startAngle, double arcAngle) {
source.drawArc((int) x, (int) y, (int) width, (int) height, (int) startAngle, (int) arcAngle);
}

public void drawImage(ImageResource img, double x, double y) {
source.drawImage(img.getResource(), (int) x, (int) y, null);
}

public void drawImage(ImageResource img, double x, double y, EGEColor bgcolor) {
source.drawImage(img.getResource(), (int) x, (int) y, (Color) bgcolor.getSource(), null);
}

public void drawImage(ImageResource img, double x, double y, double width, double height) {
source.drawImage(img.getResource(), (int) x, (int) y, (int) width, (int) height, null);
}

public void drawImage(ImageResource img, double x, double y, double width, double height, EGEColor bgcolor) {
source.drawImage(img.getResource(), (int) x, (int) y, (int) width, (int) height, (Color) bgcolor.getSource(), null);
}

public void drawLine(double x1, double y1, double x2, double y2) {
source.drawLine((int) x1, (int) y1, (int) x2, (int) y2);
}

public void drawOval(double x, double y, double width, double height) {
source.drawOval((int) x, (int) y, (int) width, (int) height);
}

public void drawRect(double x, double y, double width, double height) {
source.drawRect((int) x, (int) y, (int) width, (int) height);
}

public void drawRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight) {
source.drawRoundRect((int) x, (int) y, (int) width, (int) height, (int) arcWidth, (int) arcHeight);
}

public void drawShape(EGEShape shape) {
int v1_p1_x, v1_p1_y, v1_p2_x, v1_p2_y;
for (int i = 1; i < shape.size(); i++) {
v1_p1_x = (int) shape.get(i - 1).getX();
v1_p1_y = (int) shape.get(i - 1).getY();
v1_p2_x = (int) shape.get(i).getX();
v1_p2_y = (int) shape.get(i).getY();

source.drawLine(v1_p1_x, v1_p1_y, v1_p2_x, v1_p2_y);
}
}

public void drawShape(EGEShape shape, Transformable transform) {
if (i_vector == null)
i_vector = new EGEVector(0., 0.);
int v1_p1_x, v1_p1_y, v1_p2_x, v1_p2_y;
for (int i = 1; i < shape.size(); i++) {
shape.get(i_vector, transform, i - 1);
v1_p1_x = (int) i_vector.getX();
v1_p1_y = (int) i_vector.getY();
shape.get(i_vector, transform, i);
v1_p2_x = (int) i_vector.getX();
v1_p2_y = (int) i_vector.getY();

source.drawLine(v1_p1_x, v1_p1_y, v1_p2_x, v1_p2_y);
}
}

public void fillArc(double x, double y, double width, double height, double startAngle, double arcAngle) {
source.fillArc((int) x, (int) y, (int) width, (int) height, (int) startAngle, (int) arcAngle);
}

public void fillOval(double x, double y, double width, double height) {
source.fillOval((int) x, (int) y, (int) width, (int) height);
}

public void fillRect(double x, double y, double width, double height) {
source.fillRect((int) x, (int) y, (int) width, (int) height);

}

public void fillRoundRect(double x, double y, double width, double height, double arcWidth, double arcHeight) {
source.fillRoundRect((int) x, (int) y, (int) width, (int) height, (int) arcWidth, (int) arcHeight);
}

public EGEColor getColor() {
return color;
}

public EGEFont getFont() {
return font;
}

public Transformable getTransformation() {
return transformation;
}

public void setClip(double x, double y, double width, double height) {
source.setClip((int) x, (int) y, (int) width, (int) height);
}

public void setColor(EGEColor c) {
this.color = c;
source.setColor((Color) color.getSource());
}

public void setFont(EGEFont font) {
if (font == null)
return;
this.font = font;
}

public void setTransformation(Transformable transformation) {
this.transformation.setRotation(transformation.getRotation());
this.transformation.setX(transformation.getX());
this.transformation.setXScale(transformation.getXScale());
this.transformation.setXShear(transformation.getXShear());
this.transformation.setY(transformation.getY());
this.transformation.setYScale(transformation.getYScale());
this.transformation.setYShear(transformation.getYShear());
source.setTransform(EMPTY_TRANSFORM);
source.translate(this.transformation.getX(), this.transformation.getY());
source.rotate(this.transformation.getRotation());
source.scale(this.transformation.getXScale(), this.transformation.getYScale());
source.shear(this.transformation.getXShear(), this.transformation.getYShear());
}

public void translate(double x, double y) {
transformation.addX(x);
transformation.addY(y);
source.translate(x, y);
}

public Graphics2D getSource() {
return source;
}

public void setSource(Object source) {
if (source instanceof Graphics2D) {
this.source = (Graphics2D) source;
if (transformation == null)
transformation = new EGETransformation();
if (font == null)
font = EGETemplates.FONT01;
oldComposite = ((Graphics2D) source).getComposite();
}
}

public EGEComposite getComposite() {
return composite;
}

public void setComposite(EGEComposite composite) {
this.composite = composite;
if (composite != null) {
source.setComposite((Composite) composite.getSource());
} else if (oldComposite != null) {
source.setComposite(oldComposite);
}
}

public void drawString(String str, double x, double y) {
font.drawString(this, str, x, y);
}

public void reset() {
transformation.setRotation(0);
transformation.setX(0);
transformation.setXScale(1);
transformation.setXShear(0);
transformation.setY(0);
transformation.setYScale(1);
transformation.setYShear(0);
source.setTransform(EMPTY_TRANSFORM);
source.translate(transformation.getX(), transformation.getY());
source.rotate(transformation.getRotation());
source.scale(transformation.getXScale(), transformation.getYScale());
source.shear(transformation.getXShear(), transformation.getYShear());
source.setClip(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
}

public void resetComposite() {
source.setComposite(oldComposite);
}

public void rotate(double rotation) {
transformation.setRotation(transformation.getRotation() + rotation);
source.rotate(PI / 180. * rotation);
}

public void scale(double xs, double ys) {
transformation.setXScale(transformation.getXScale() / xs);
transformation.setYScale(transformation.getXScale() / ys);
source.scale(xs, ys);
}

public void shear(double xs, double ys) {
transformation.setXShear(transformation.getXShear() + xs);
transformation.setYShear(transformation.getXShear() + ys);
source.shear(xs, ys);
}
}[/Java]

Ich hoffe ich habe mich einigermaßen verständlich ausgedrückt...
Währe nett, wenn mir jemand weiterhelfen könnte. Für (sinnvolle) Vorschläge bin ich dankbar.

Danke und Gruß
Steev
 

Steev

Bekanntes Mitglied
Weis keiner woran der Fehler liegen könnte? Was vieleicht noch wichtig ist: Die Graphics2D-Instanz kommt von einem VolatileImage. Aber vorher hat das ja auch funktioniert...
 

Steev

Bekanntes Mitglied
ich implementiere doch überhaupt keine Standard-Klasse, die Interface heist EGEGraphics, und liefert alle implementierten Methoden. Graphics und Graphics2D sind doch sowieso abstracte Klassen die in SunGraphics2D implementiert werden.
 

Ebenius

Top Contributor
Sorry. Ich hatte Deine Problembeschreibung nicht korrekt aufgenommen. :)

Ich würde testweise in den einzelnen Methoden die Farbe auf dem Graphics2D setzen. Vielleicht auch einen Stroke. Oder die Transformation.

Du hast nicht zufällig ein Test-Programm dazu als kleinen Quelltext…

Ebenius
 
Zuletzt bearbeitet:

Steev

Bekanntes Mitglied
Nein, ich habe leider kein Testprogamm, das sind einige hundert Klassen...

Habe ich vieleicht irgendwas grundsätzlich total falsch gemacht? Wie würdest du das machen?

Was ich gerade rausgefunden habe: ein Testprogramm, wo ich mir den Kontext selbst nochmal zu Fuß erstellt habe funktioniert einwandfrei.
Also nehme ich an, dass irgendwo in der Engine noch was anderes nicht ganz stimmt... Und da kann mir warscheinlich keiner Helfen.
 

Ebenius

Top Contributor
Kannst Du Threading-Issues ausschließen? Mach doch mal alle Methoden synchronized. Oder lass Dir die Thread-Names ausgeben. Ohne weiter Code kann ich da erstmal kein Problem sehen… Ansonsten helfen sicher Log-Ausgaben… *schulterzuck*

Ebenius
 

Steev

Bekanntes Mitglied
Ich kann nicht alle Methoden synchronized machen, da ich sonst deathlocks bekomme. Ich werde mal mit VirtualVM gucken, was da intern passiert. Eine wirkliche Vorstellung, was da nicht läuft habe ich nicht. Wenn ich vor drawImage ein drawRect, mit den Maßen des Images schreibe, dann wird der Rect angezeigt, das Image aber nicht. Also wirklich ganz komisch... Keine Ahnung was da falsch ist... Zur Not stelle ich eine VM hoch, wo man das Problem nachstellen kann, wenn ich nicht mehr weiterkomme.
Danke für deine Hilfe.
 

Ebenius

Top Contributor
Deadlocks? Auf den Grafikkontext kann man doch nicht aus verschiedenen Threads zugreifen? Das kann doch gar nicht hinhauen… Oder hab ich da nen Denkfehler?

Ebenius
 

Steev

Bekanntes Mitglied
Ach, du meintest nur die Graphic-Context methoden? :p Ich hatte das jetzt irgendwie allumfassender verstanden.
Ich kann mir nicht vorstellen, dass das an Threads liegt, da das ja nur auf einem Rechner nicht (mehr) funktioniert.
Ich werde nochmal tief im Code rumwühlen und suchen, ob da irgendwas nicht richtig zusammenarbeitet.
 

Steev

Bekanntes Mitglied
Ich habe den Fehler gefunden :)
Das war ein ganz dummer Fehler und direkt in obiger Graphics-Implementiertung enthalten:

In der Methode reset stand bisher folgendes:
[Java]source.setClip(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);[/Java]

Das ist falsch, weil der Min- und der Maxwert vorzeichenlos gleich ist. Der Clip ist aber ein rectangle, sodass die Breite und Höhe immer doppelt so hoch sein muss wie die X- und Y-Position um zentriert zu der Zeichenfläche zu sein.

Gruß
Steev
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
K Hashmap mit 2D Graphics Spiele- und Multimedia-Programmierung 7
FunnyO Graphics fillOval weiche Kanten Spiele- und Multimedia-Programmierung 8
kaoZ Graphics Objekt liefert null Spiele- und Multimedia-Programmierung 14
S Graphics Objekt weiterreichen? Spiele- und Multimedia-Programmierung 4
S Graphics.drawString (Graphics2D.drawString) Y-Problem Spiele- und Multimedia-Programmierung 4
G Wie bekomme ich einen Punkt (Graphics) Spiele- und Multimedia-Programmierung 2
K stringWidth bei Graphics von JPanel und Printer unterschiedl Spiele- und Multimedia-Programmierung 4
P Graphics Klasse Spiele- und Multimedia-Programmierung 3
N Performance Problem bei mit Graphics Spiele- und Multimedia-Programmierung 6
V Graphics oder Graphics2D Zeichenfunktion gesucht? Spiele- und Multimedia-Programmierung 4
G Einen gif oder jpg Datei aus einem Graphics Objekt o. JFrame Spiele- und Multimedia-Programmierung 2
O transparente farbe in Image mit Graphics Spiele- und Multimedia-Programmierung 8
G Graphics bei Java aufteilen Spiele- und Multimedia-Programmierung 3
C Graphics 2D Zeichnen Spiele- und Multimedia-Programmierung 4
F einzelne Polygone(Graphics) schneller als and. Fig. zeichnen Spiele- und Multimedia-Programmierung 3
RalleYTN OpenGL Context im JFrame? Spiele- und Multimedia-Programmierung 0
K LibGdx, Loadingscreen & Opengl context Spiele- und Multimedia-Programmierung 3

Ähnliche Java Themen

Neue Themen


Oben