S
s_m_w
Gast
Hallo,
Ich habe eine Bezierkurve mit Breite b, die ich gerne mit einer Textur füllen würde. Das Problem ist jedoch, dass die Textur mit der Linie mitgehen soll (ansonsten wäre es ein recht trivialies Problem mit TexturePaint).
Die Bezierkurve wird als zwei Arrays, die jeweils Koordinaten zweier Bezierkurven enthalten, die jeweils den Linken und Rechten Rand der Bezierkurve definieren, übergeben. Als ersten Ansatz habe ich aus diesen Punkten Polygone erzeugt, meine Textur rotiert und dann damit die Polygone gefüllt, doch das Ergebnis ist nicht ganz erfreulich:
Im folgenden der Code:
("Vec" ist ein Point2D mit einigen Vektoroperatrionen, die selbsterklärend sein sollten)
Die Bezierkurve wird wie folgt erzeugt (keine Probleme hier; nur als Zeitersparnis für die Helfer):
Bestimmt gibt es genau das, was ich suche schon, habe aber per Google nichts hilfreiches gefunden
Ich habe eine Bezierkurve mit Breite b, die ich gerne mit einer Textur füllen würde. Das Problem ist jedoch, dass die Textur mit der Linie mitgehen soll (ansonsten wäre es ein recht trivialies Problem mit TexturePaint).
Die Bezierkurve wird als zwei Arrays, die jeweils Koordinaten zweier Bezierkurven enthalten, die jeweils den Linken und Rechten Rand der Bezierkurve definieren, übergeben. Als ersten Ansatz habe ich aus diesen Punkten Polygone erzeugt, meine Textur rotiert und dann damit die Polygone gefüllt, doch das Ergebnis ist nicht ganz erfreulich:

Im folgenden der Code:
("Vec" ist ein Point2D mit einigen Vektoroperatrionen, die selbsterklärend sein sollten)
Java:
void drawTexturedLineFromVecArray(Graphics2D g, ArrayList<Vec> Pt1, ArrayList<Vec> Pt2, BufferedImage Texture) {
ArrayList<Polygon> Polys = new ArrayList();
ArrayList<Double> Angles = new ArrayList();
// Transform the coordinates into polygons
Iterator<Vec> it1 = Pt1.iterator();
Iterator<Vec> it2 = Pt2.iterator();
Vec Left = it1.next();
Vec Right = it2.next();
Polygon newP;
while (it1.hasNext()) {
Vec UpperLeft = it1.next();
Vec UpperRight = it2.next();
newP = new Polygon();
newP.addPoint((int) UpperLeft.x, (int) UpperLeft.y);
newP.addPoint((int) UpperRight.x, (int) UpperRight.y);
newP.addPoint((int) Right.x, (int) Right.y);
newP.addPoint((int) Left.x, (int) Left.y);
Vec AngleVec;
Vec v1, v2;
v1 = UpperLeft.add(UpperRight);
v1 = v1.multiply(0.5);
v2 = Left.add(Right);
v2 = v2.multiply(0.5);
AngleVec = v1.subtract(v2);
Angles.add(Math.atan2(AngleVec.y, AngleVec.x) + Math.PI / 2);
Polys.add(newP);
Left = UpperLeft;
Right = UpperRight;
}
// Here is where it gets interesting
int newTextureWidth = 50;
int newTextureHeight = 50;
Iterator<Polygon> it3 = Polys.iterator();
Iterator<Double> angleit = Angles.iterator();
// Go through all Polygons and their respective angles
while (it3.hasNext()) {
Polygon P = it3.next();
// generate a new image
BufferedImage RotatedTexture = new BufferedImage(newTextureWidth, newTextureHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D TextureGraphics = (Graphics2D) RotatedTexture.getGraphics();
// Use our original texture as paint material
TextureGraphics.setPaint(new TexturePaint(Texture,
new Rectangle2D.Float(0, 0, Texture.getWidth(), Texture.getHeight())));
AffineTransform xform = new AffineTransform();
xform.setToIdentity();
// rotate around the center
xform.rotate(angleit.next(), RotatedTexture.getWidth() / 2, RotatedTexture.getHeight() / 2);
TextureGraphics.transform(xform);
TextureGraphics.fillRect(0, 0, RotatedTexture.getWidth(), RotatedTexture.getHeight());
xform.setToIdentity();
g.setPaint(new TexturePaint(RotatedTexture,
new Rectangle2D.Float(0, 0, RotatedTexture.getWidth(), RotatedTexture.getHeight())));
g.fillPolygon(P);
}
}
Die Bezierkurve wird wie folgt erzeugt (keine Probleme hier; nur als Zeitersparnis für die Helfer):
Java:
TargetX = (int) Target.getCenterX();
TargetY = (int) Target.getCenterY();
OriginX = (int) Origin.Position.x;
OriginY = (int) Origin.Position.y;
// Start and end
int startX = (int) (OriginX + OriginOffset.x);
int startY = (int) (OriginY + OriginOffset.y);
Vec start = new Vec(startX, startY);
int endX = TargetX;
int endY = TargetY;
Vec end = new Vec(endX, endY);
// Two points that define the look of the laser curve
Vec P2 = new Vec(startX*0.8+endX*0.2, startY*0.5+endY*0.25-50);
Vec P3 = new Vec(startX*0.5+endX*0.5, (startY-100)*0.2+endY*0.8);
//P(t) = (1-t)^3P0 + 3(1-t)^2tP1 + 3(1-t)t^2P2 + t^3P3 with t running from 0 to 1.
double precision = 0.1;
double laser_width = 33;
Vec A, B = new Vec();
Vec DiffVec;
double angle = 0;
double partX, partY;
// Save all generated points so we have X different arrays of points of a line
ArrayList<Vec>[] Points = new ArrayList[5];
for (int j=0;j<2;j++) {
Points[j] = new ArrayList();
}
G.setColor(new Color(255, 255, 255, 255));
for (double t = 0; t < 1;) {
A = new Vec((int) ((1 - t) * (1 - t) * (1 - t) * start.x + 3 * (1 - t) * (1 - t) * t * P2.x + 3 * (1 - t) * t * t * P3.x + t * t * t * end.x),
(int) ((1 - t) * (1 - t) * (1 - t) * start.y + 3 * (1 - t) * (1 - t) * t * P2.y + 3 * (1 - t) * t * t * P3.y + t * t * t * end.y));
t += precision;
B = new Vec(
(int) ((1 - t) * (1 - t) * (1 - t) * start.x + 3 * (1 - t) * (1 - t) * t * P2.x + 3 * (1 - t) * t * t * P3.x + t * t * t * end.x),
(int) ((1 - t) * (1 - t) * (1 - t) * start.y + 3 * (1 - t) * (1 - t) * t * P2.y + 3 * (1 - t) * t * t * P3.y + t * t * t * end.y));
DiffVec = B.subtract(A);
angle = DiffVec.getAngle() + Math.PI/2;
for (int j=0;j<=1;j++) {
partX = A.x + Math.cos(angle)*(((j*2)-1)*laser_width/5);
partY = A.y + Math.sin(angle)*(((j*2)-1)*laser_width/5);
Points[j].add(new Vec(partX,partY));
//G.fillRect((int)partX-3,(int)partY-3,5,5);
}
if (t>1) break;
//G.drawLine((int)A.x, (int)A.y, (int)B.x, (int)B.y);
}
Game.getArt().drawTexturedLineFromVecArray(G,Points[0],Points[1],Game.getArt().getContinuousLaserPart());
Bestimmt gibt es genau das, was ich suche schon, habe aber per Google nichts hilfreiches gefunden