Texturing an Imported Triangle Mesh Javafx - java

I created a design in blender exported to STL and used the StlModelImporterJFX to import it into my JavaFX program and run it. Everything runs fine, the application works, there is just one thing missing...texture, so basically, I want to take my imported mesh and create an image as seen below for a smaller design.
Is there any program or algorithm that I can use to create an image such as that below that I can later edit manually and use as a texture for the entire Triangle Mesh? Also on a side note is it possible to edit this image live in the program and swap out colours while running? Sorry if this is poorly worded, if you want any clarification, I can provide it.

When you import a 3D model with a third-party 3D importer you have less control of the resulting TriangleMesh. If you want to provide texture features to your model you'll have to edit the exported file and add the texture coordinates, which is not the best approach.
But if you could generate the mesh from scratch, you could easily apply textures over it.
This question shows how you can define the texture coordinates and uses the same net image you have to provide the texture of an icosahedron.
Based on the answer on that question, the texture can be defined without an actual image, just with a palette of colors.
And you can easily change those on runtime, i.e. when you click on one face you can change the color on that face.
The Fxyz library makes use of a TexturedMesh, designed to easily apply textures to 3D shapes.
You can find many primitives there, like the icosahedron.
This question shows the result of different texture modes over an icosahedron.
This short snippet shows how you can apply a texture over faces, and change it on runtime:
private int numColors = 10;
#Override
public void start(Stage primaryStage) {
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-5);
IcosahedronMesh icoFaces = new IcosahedronMesh(100, 0);
icoFaces.setTextureModeFaces(numColors);
icoFaces.getTransforms().addAll(new Rotate(20, Rotate.X_AXIS), new Rotate(-10, Rotate.Y_AXIS));
final Group group = new Group(icoFaces);
Scene scene = new Scene(group, 600, 400, true, SceneAntialiasing.BALANCED);
scene.setCamera(camera);
primaryStage.setScene(scene);
primaryStage.setTitle(("Icosahedron - FXyz3D"));
primaryStage.show();
icoFaces.setOnMouseClicked(e -> {
ObservableFaceArray faces = ((TriangleMesh) icoFaces.getMesh()).getFaces();
int selectedFace = e.getPickResult().getIntersectedFace();
int colorId = faces.get(6 * selectedFace + 1);
int newColorId = colorId + 1 >= numColors ? 0 : colorId + 1;
faces.set(6 * selectedFace + 1, newColorId);
faces.set(6 * selectedFace + 3, newColorId);
faces.set(6 * selectedFace + 5, newColorId);
});
}
Running the application:
And after clicking in the frontal green face:

Related

Integrating both canvas and pane with Line objects in JavaFX

Disclaimer: I am using Java and Javafx 11. Just putting it out there :)
I am in the process of trying to create an Interpreter for Logo, but have run into a roadblock. You see, I defaulted to using a canvas to display all the things I needed as that is fitting for what I am doing. However, I did not account for the fact that my Turtle needed to move.
private void drawTurtle()
{
vertices[0] = new Vector2(position.x, position.y + 15); // The three points that make the triangle that is the turtle
vertices[1] = new Vector2(position.x - 15, position.y);
vertices[2] = new Vector2(position.x + 15, position.y);
vertices[1] = Renderer.rotatePoint(vertices[1], position, rotation); // applying rotation to vertices
vertices[2] = Renderer.rotatePoint(vertices[2], position, rotation);
vertices[0] = Renderer.rotatePoint(vertices[0], position, rotation);
Renderer.drawLine(vertices[2], vertices[1], currentPen); // drawing the vertices
Renderer.drawLine(vertices[2], vertices[0], currentPen);
Renderer.drawLine(vertices[1], vertices[0], currentPen);
}
Trails left due to rotating the turtle in realtime.
In order to achieve this without leaving "trails", I tried to erase the existing turtle by drawing with a white pen over it. That gave me... weird results.
This is after rotating the turtle 360 degrees.
Then I came across a post here on SO talking about how I should use a Line object on a Pane if I wanted to move stuff. And well, I tried combining it with a canvas to make a CanvasPane:
public class CanvasPane extends Pane
{
public final Canvas canvas;
public CanvasPane(double width, double height)
{
setWidth(width);
setHeight(height);
canvas = new Canvas(width, height);
getChildren().add(canvas);
canvas.widthProperty().bind(this.widthProperty()); // Change this so this canvas does not scale with the pane, and its size is constant.
canvas.heightProperty().bind(this.heightProperty());
}
}
And added line objects to this so I can then edit their start and end values to make the turtle move, but I got nothing out of it, no line to show, and I am quite confused and don't know what to do. Nothing on the great internet helped my either, so I am now asking this question to see if anyone has ideas on how I can move my turtle flawlessly. And no, I can't use clearRect()
TLDR: My turtle leaves trails when moving on a canvas, and using Line and Pane doesn't work, and I can't use clearRect() on my canvas. Help!
Use one Pane to hold both the Canvas Node and your "turtle" Node.
Canvas canvas = new Canvas(640, 480);
Shape turtle = new Polygon(); // fill in the points
Pane p = new Pane(canvas, turtle);
Now you can control the position of the turtle node by either setting the layout coordinates or applying a translation. As it was added last, it will be drawn over the Canvas. (You could also use a StackPane to make that layering more explicit.)

LibGDX: What's the fastest way to render scalable-vector-based shapes?

In my game (created using LibGDX) I have a gameworld filled with a lot of circles changing their size continiously. Because there are so many circles I want to maximize their rendering-performance: I've heard of the ShapeRenderer, but it seems like that it is not the best in case of performance. The PixMap is also no solution because my circles should be vector-based.
Is their another faster solution too? And is the ShapeRenderer really that slow?
PS: I'm already using chunks to reduce the render time.
For the ShapeRenderer (circle in particular), if we look at the method, radius does not effect performance, segments is where the work is. And this is most likely what is hurting you, as you scale up in size, you increase the segments for detail.
I am not sure about there being opengl native vector graphics either... I think ultimately to reach the graphics card, you need to eventually become vertices and polygons (if you are filling). So actually, I think the Pixmap solution is the one you might be looking for. You compute the segments and the polygons to draw once (at the highest resolution you need).
With the Pixmap you should be able to do this in a way which is as performant as any other rendering of a Texture which you change sizes using the scaling variables (which should be as performant as not changing the scale). As you can see from the circle draw method that the ShapeRenderer uses, the circle is still really just describing a polygon (you are just computing its geometry every time).
If you want to give the Pixmap option a go, here is some code to get you bootstrapped.
Here is a kotlin function for building a PolygonSprite. You will have to do the maths for plotting the vertices of your circle, but you can probably use the circle draw method to get an idea for that. If you compute your geometry for a radius of 1, then you can just use your x/y scale to set the radius at whatever size you want.
fun polygonSprite(points: Array<Vector2>): PolygonSprite {
val pix = Pixmap(1, 1, Pixmap.Format.RGBA8888)
pix.setColor(0xFFFFFFFF.toInt())
pix.fill()
val textureSolid = Texture(pix)
val vertices = FloatArray(points.size * 2)
val triangleIndices = triangulator.computeTriangles(vertices)
for (i in 0..points.size - 1) {
val point = points.get(i)
val offset = i * 2
vertices[offset] = point.x
vertices[offset + 1] = point.y
}
val polyReg = PolygonRegion(TextureRegion(textureSolid),
vertices, triangleIndices.toArray())
val poly = PolygonSprite(polyReg)
return poly
}
And here is some rendering code. It takes into account relative positioning of the shape from the parent Body and some other stuff:
fun render(camera: OrthographicCamera) {
val parentRotation = (me().physicsRoot.rotationR() * MathUtils.radDeg)
val parentTransform = me().physicsRoot.transform
val myPosition = vec2(offsetX, offsetY)
parentTransform.mul(myPosition)
poly.color = color.get()
poly.setOrigin(0f, 0f)
poly.setPosition(myPosition.x, myPosition.y)
poly.rotation = parentRotation + rotationD
poly.setScale(scaleX, scaleY)
poly.draw(JJ.B.renderWorld.polyBatch)
recycle(myPosition)
}
Also, don't make a new one of these for every one, try and reuse them.
PS: Another option is to make a circle shader :D

Libgdx: text inside the game screen / render - fix size and position

I want to add text on the top of the enemies body.
Downscale issue starts here:
https://gamedev.stackexchange.com/questions/73688/why-is-my-text-is-too-large-even-when-scaled-to-05f-in-libgdx
The issue is that the text is very very big and i can't scale it smaller.
There is a solution for this, to add another camera / viewport.
This is OK - for HUD screen.
But i need the text on the enemy head.
From font class:
viewport = new FitViewport(Application.V_WIDTH * 4 , Application.V_HEIGHT * 4, new OrthographicCamera());
stage = new Stage(viewport, SpriteBatch);
stage.addActor(tableText);
Game main class:
viewport = new FitViewport(Application.V_WIDTH / Application.PPM, Application.V_HEIGHT / Application.PPM, orthographicCamera);
AND THE GAME. . .
What should i do? Do i need to find the right ratio betwin the game and the font class?
Danke
There is another way that works for me now:
bitmapFont.getData().setScale(0.008f);
bitmapFont.setUseIntegerPositions(false);
From libgdx API:
/** Specifies whether to use integer positions. Default is to use them so filtering doesn't kick in as badly. */
public void setUseIntegerPositions (boolean integer) {
this.integer = integer;
cache.setUseIntegerPositions(integer);
}

How to draw square pixel with different colors using SWT application

I am working on a fluid simulation application using SWT and want to draw the final calculated density of fluid back to UI. Now I am thinking about using SWT canvas and GC, but GC seems only for drawing shapes and lines, without the ability to draw colored pixels
There are many simulation app in the website but none is implemented by SWT. Below is the expected result for this application:
Use GC.drawPoint to draw a single pixel, the colour will be that set with GC.setForeground.
Jonah's answer is the way to do it if you want to draw everything yourself.
I'm just posting this as an alternative:
There's a library called "JHC (Java Heat Map Control)" that you could use to draw your data.
It would look something like this:
The data is provided in the form of an int[][].
// Define scales
JHCScale<String> xScale = new JHCScale.String(new String[] { "X1", "X2", "X3" });
JHCScale<String> yScale = new JHCScale.String(new String[] { "Y1", "Y2", "Y3" });
// Configure
JHCLayout layout = new JHCLayout(false, 20, true, 20);
JHCConfiguration config = new JHCConfiguration("x-label", "y-label",
JHCGradient.GRADIENT_HEAT, layout);
// Create array
int[][] array = {{0,1,0}, {1,2,1}, {0,1,0}};
// Create data object
JHCData data = JHCData.create(array, Orientation.ROW, xScale, yScale);
// Create JHC widget
JHC jhc = new JHC(shell, SWT.NONE);
jhc.setData(data, config);

How to fill a JavaFX Sphere with two Colors

How can I fill in JavaFX a 3D Sphere with a linear gradient like a 2d Circle?
I work with the JavaFX Scene Builder.
As #mohsenmadi has pointed out, the diffuse color doesn't allow you using other than one single color.
But you can have different colors on the sphere by using an image as a diffuse map.
Based on your first image, I've created this texture image (called diffuse.jpg, and placed under the same folder as the JavaFX class):
You can create now your bicolored sphere:
#Override
public void start(Stage primaryStage) throws Exception {
// 3D
Sphere sphere = new Sphere(5);
PhongMaterial phongMaterial = new PhongMaterial();
phongMaterial.setDiffuseMap(new Image(getClass().getResource("diffuse.jpg").toExternalForm()));
sphere.setMaterial(phongMaterial);
...
}
So you will see this:
Note that you may have some side effects on the poles.
You can also have a look at the FXyz project, a library with aditional JavaFX 3D complex shapes, and also complex texture options.
For instance, you can use a density map to create the same effect you want, but without providing the texture image.
Under org/fxyz/shapes/primitives you can find several primitives like SegmentedSphereMesh.
Like an sphere you can create one giving the number of divisions, the crop divisions (0 in this case for x and y), the radiuos, and the center:
SegmentedSphereMesh sphere = new SegmentedSphereMesh(200,0,0,100,new Point3D(0f,0f,0f));
Now you can define the function:
Function<Point3D, Number> dens = p->p.y>0?1:0;
and apply it, with the number of colors (2 in this case):
sphere.setTextureModeVertices3D(2,dens);
Now you will have this:
Now you won't have side effects on the poles, and you could modify this function easily to other cases.
Note that you can add create your own palette of colors or play with the HSB function under org/fxyz/utils/Palette.
The way to achieve gradient-like effects on 3D shapes is by applying lighting material and lighting position. You can't simply apply two colours that gradually transform into each other. I cooked for you a small app that shows just how to achieve this.
public class ShadedSphere extends Application {
public void start(Stage stage) {
StackPane layout = new StackPane();
layout.setPrefSize(300, 300);
Scene scene = new Scene(layout);
createScene(scene);
stage.setScene(scene);
stage.show();
}
private void createScene(Scene scene) {
PhongMaterial material = new PhongMaterial();
material.setDiffuseColor(Color.ORANGE);
material.setSpecularColor(Color.BLACK);
Sphere sphere = new Sphere(100);
sphere.setMaterial(material);
Pane root = (Pane) scene.getRoot();
root.getChildren().add(sphere);
}
public static void main(String[] args) {
launch(args);
}
}
Which will give you this:
If you change the location of the sphere (e.g., using setTranslateX() and same for Y and Z), you should notice different effects of lighting on it; so the next thing for you to grasp is how to control location of lighting fixtures. Also, lights can have colour! Which means you can achieve even Northern Lights effects if you want to see cool stuff.
To learn a bit more about lighting, camera and effects, see this link.

Categories