I'm working now with javafx to build a maze and I want the walls to be textured with some seamless texture (that can be repeated). The maze is randomly generated so I don't know the size of any walls. I started by using a PhongMaterial with the desired texture, but it expand the image to fill the whole wall (a Box), so my texture is totally stretched. Is there any way to force the Material to replicate the texture as needed ?
The code is like:
Image img = new Image(new FileInputStream("img.jpg"), 400, 400, true, false);
Material mat = new PhongMaterial(Color.WHITE, img, null, null, null);
Box w = new Box(100,10,10);
w.setMaterial(mat);
Something like an ImagePattern seems a good idea, but there is no Material that accept it.
Thanks in advance for any help
As #fabian mentioned, Box is not suitable for customizing the texture. By default the image you set as diffuse map will be applied for each of its six faces, and, as you already discovered, this means that it will stretch the image to accommodate the different sides.
Using the FXyz library, we can easily try the Carbon-Kevlar pattern. But obviously we have to select a size for it. Like 100 x 30.
#Override
public void start(Stage primaryStage) {
Box box = new Box(100, 30, 50);
PhongMaterial material = new PhongMaterial();
Patterns pattern = new Patterns(100, 30);
material.setDiffuseMap(pattern.createPattern(Patterns.CarbonPatterns.CARBON_KEVLAR, false));
box.setMaterial(material);
Scene scene = new Scene(new Group(box), 500, 400, true, SceneAntialiasing.BALANCED);
primaryStage.setScene(scene);
primaryStage.show();
}
While the texture fits perfectly fine the front face with dimensions 100x30, this image is distorted to fit in the same way the other faces 50x50 and 100x50.
Solution 1
We can try to generate our own Box, so we can decide how to apply the diffuse map.
Creating a TriangleMesh for a cuboid is easy in terms of vertices and faces or normals.
The tricky part is setting the texture coordinates. In the following snippet I set them based on one of the different possible 2D net images of the 3D cuboid:
public MeshView createCuboid(float w, float h, float d) {
float hw = w / 2f;
float hh = h / 2f;
float hd = d / 2f;
float points[] = {
hw, hh, hd,
hw, hh, -hd,
hw, -hh, hd,
hw, -hh, -hd,
-hw, hh, hd,
-hw, hh, -hd,
-hw, -hh, hd,
-hw, -hh, -hd};
float L = 2 * w + 2 * d;
float H = h + 2 * d;
float tex[] = {
d / L, 0f,
(d + w) / L, 0f,
0f, d / H,
d / L, d / H,
(d + w) / L, d / H,
(2 * d + w) / L, d / H,
1f, d / H,
0f, (d + h) / H,
d / L, (d + h) / H,
(d + w) / L, (d + h) / H,
(2 *d + w) / L, (d + h) / H,
1f, (d + h) / H,
d / L, 1f,
(d + w) / L, 1f};
float normals[] = {
1f, 0f, 0f,
-1f, 0f, 0f,
0f, 1f, 0f,
0f, -1f, 0f,
0f, 0f, 1f,
0f, 0f, -1f,
};
int faces[] = {
0, 0, 10, 2, 0, 5, 1, 0, 9,
2, 0, 5, 3, 0, 4, 1, 0, 9,
4, 1, 7, 5, 1, 8, 6, 1, 2,
6, 1, 2, 5, 1, 8, 7, 1, 3,
0, 2, 13, 1, 2, 9, 4, 2, 12,
4, 2, 12, 1, 2, 9, 5, 2, 8,
2, 3, 1, 6, 3, 0, 3, 3, 4,
3, 3, 4, 6, 3, 0, 7, 3, 3,
0, 4, 10, 4, 4, 11, 2, 4, 5,
2, 4, 5, 4, 4, 11, 6, 4, 6,
1, 5, 9, 3, 5, 4, 5, 5, 8,
5, 5, 8, 3, 5, 4, 7, 5, 3};
TriangleMesh mesh = new TriangleMesh();
mesh.setVertexFormat(VertexFormat.POINT_NORMAL_TEXCOORD);
mesh.getPoints().addAll(points);
mesh.getTexCoords().addAll(tex);
mesh.getNormals().addAll(normals);
mesh.getFaces().addAll(faces);
return new MeshView(mesh);
}
Now we can generate the image, but using the net dimensions:
#Override
public void start(Stage primaryStage) {
MeshView box = createCuboid(100, 30, 50);
PhongMaterial material = new PhongMaterial();
Patterns pattern = new Patterns(300, 160);
material.setDiffuseMap(pattern.createPattern(Patterns.CarbonPatterns.CARBON_KEVLAR, false));
box.setMaterial(material);
box.getTransforms().addAll(rotateX, rotateY);
Scene scene = new Scene(new Group(box), 500, 400, true, SceneAntialiasing.BALANCED);
primaryStage.setScene(scene);
primaryStage.show();
}
Note that the image is not distorted anymore.
You can play with its size to get a more fine or dense pattern (with a bigger image pattern).
Note that you can find this Cuboid primitive in the FXyz library, among many other 3D primitives.
Also you can find different texture modes (density maps, images, patterns...)
Related
I have a HashSet filled with custom rectangle object("name",center_X,center_Y, width, height). i wrote a method to find if two rectangles are connected(touch/intersect). But i want to get all the rectangles that are a group. For example: if rectA is connected with rectB, RectC is connected with rectB but not rectA directly they all are connected because rectB is common.
I can find the shapes that have direct connection. But I want to get the group where shapes with secondary connection is also included. I'd assume recursion is useful in this case but can't solve it yet. Any solution/suggestion?
public static void canItbeGroup(HashSet<RECTANGLE> ipRectangles)
{
Deque<RECTANGLE> ipDeque = new ArrayDeque<>(ipRectangles);
for (RECTANGLE currRectangle : ipDeque)
{
Set<String> tempGrpMbrShapeID = new HashSet<>();
RECTANGLE tempRect = ipDeque.pop();
for (RECTANGLE r : ipDeque)
{
if (tempRect.areShapesFriend(r))
{
tempGrpMbrShapeID.add(r.shapeID);
tempGrpMbrShapeID.add(tempRect.shapeID);
}
}
if (tempGrpMbrShapeID.size() > 1)
{
System.out.println(tempGrpMbrShapeID);
}
}
}
public static void main(String[] args)
{
HashSet<RECTANGLE> rectHS = new HashSet<>();
RECTANGLE aRect = new RECTANGLE("a", 3, 2, 2, 2);
RECTANGLE aInnerRect = new RECTANGLE("aIn", 3, 2, 1, 1);
RECTANGLE bRect = new RECTANGLE("b", 5, 3, 2, 2);
RECTANGLE cRect = new RECTANGLE("c", 7, 3, 2, 2);
RECTANGLE dRect = new RECTANGLE("d", 4, 5, 4, 2);
RECTANGLE eRect = new RECTANGLE("e", 11, 3, 2, 2);
RECTANGLE fRect = new RECTANGLE("f", 11, 6, 2, 2);
RECTANGLE gRect = new RECTANGLE("g", 13, 3, 2, 2);
RECTANGLE hRect = new RECTANGLE("h", 4, 8, 2, 2);
RECTANGLE iRect = new RECTANGLE("i", 14, 1, 2, 2);
RECTANGLE jRect = new RECTANGLE("j", 16, 7, 2, 2);
RECTANGLE kRect = new RECTANGLE("k", 15, 6, 2, 2);
RECTANGLE lRect = new RECTANGLE("l", 8, 8, 2, 2);
RECTANGLE mRect = new RECTANGLE("m", 5, 10, 2, 2);
rectHS.add(aRect);
rectHS.add(bRect);
rectHS.add(cRect);
rectHS.add(eRect);
rectHS.add(dRect);
rectHS.add(fRect);
rectHS.add(gRect);
rectHS.add(aInnerRect);
rectHS.add(hRect);
rectHS.add(iRect);
rectHS.add(jRect);
rectHS.add(kRect);
rectHS.add(lRect);
rectDQ.add(aRect);
rectDQ.add(bRect);
rectDQ.add(cRect);
rectDQ.add(dRect);
rectDQ.add(eRect);
canItbeGroup(rectHS);
}
output i get:
[a, b, aIn],[b, c, d],[g, i],[e, g],[j, k],[c, d]
I'll need the group as
[a,b,aIn,c,d], [e,g,i], [j,k]
I won't solve the problem for you, but I will give you a general approach.
Generate an initial Collection<Set<String>>. This is effectively what you've already done, but you'll need to store them so that you can merge the sets, rather than printing the group as soon as your find them
Iterate over all groups (i), and compare each group to every other group (j)
If the i contains any item of j then merge the sets (put all items of j into i, and remove all items from j)
Go back to 2 and repeat until you perform 1 full iteration where no merges occur.
Iterate again and remove any empty sets.
On the topic of creating custom 3D models, I found this answer. It remains incomprehensible to me how the coordinates of the texture and points mix.
Here's question.
If this is some kind of global concept, and not a feature of building 3D in Java, then I will be glad to mention any literature where these things are well covered. For convenience, I give an example of a code where getting the coordinates of the faces is covered with darkness for me. Thank!
float[] points =
{
50, 0, 0, // v0 (iv0 = 0)
45, 10, 0, // v1 (iv1 = 1)
55, 10, 0 // v2 (iv2 = 2)
};
float[] texCoords =
{
0.5f, 0.5f, // t0 (it0 = 0)
0.0f, 1.0f, // t1 (it1 = 1)
1.0f, 1.0f // t2 (it2 = 2)
};
int[] faces =
{
0, 0, 2, 2, 1, 1, // iv0, it0, iv2, it2, iv1, it1 (front face)
0, 0, 1, 1, 2, 2 // iv0, it0, iv1, it1, iv2, it2 back face
};
Found the literature with the answers. If anyone is interested, here is the link.a link
I am learning about 2d images. We were given a template to use and told do various things. Everything seems to be working fine, except the image is already being drawn rotated. I do not understand why. This is the image.
public static int[][] letterN = {
{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0},
{0, 1, 1, 0, 0, 0, 0, 1, 1, 0}};
This is the code from the program: I dont understand why the image is popping up rotated. All of the other letters are being rotated as well.
package cmsc325animate;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class CMSC325Animate extends JPanel {
// A counter that increases by one in each frame.
private int frameNumber;
// The time, in milliseconds, since the animation started.
private long elapsedTimeMillis;
// This is the measure of a pixel in the coordinate system
// set up by calling the applyLimits method. It can be used
// for setting line widths, for example.
private float pixelSize;
static int translateX = 0;
static int translateY = 0;
static double rotation = 0.0;
static double scaleX = 1.0;
static double scaleY = 1.0;
ImageTemplate myImages = new ImageTemplate();
BufferedImage tImage = myImages.getImage(ImageTemplate.letterT);
BufferedImage nImage = myImages.getImageN(ImageTemplate.letterN);
BufferedImage oImage = myImages.getImageO(ImageTemplate.letterO);
BufferedImage aImage = myImages.getImageA(ImageTemplate.letterA);
BufferedImage hImage = myImages.getImageH(ImageTemplate.letterH);
BufferedImage heartImage = myImages.getImageHeart(ImageTemplate.heart);
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
JFrame window;
window = new JFrame("Java Animation"); // The parameter shows in the window title bar.
final CMSC325Animate panel = new CMSC325Animate(); // The drawing area.
window.setContentPane(panel); // Show the panel in the window.
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // End program when window closes.
window.pack(); // Set window size based on the preferred sizes of its contents.
window.setResizable(false); // Don't let user resize window.
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
window.setLocation( // Center window on screen.
(screen.width - window.getWidth()) / 2,
(screen.height - window.getHeight()) / 2);
Timer animationTimer; // A Timer that will emit events to drive the animation.
final long startTime = System.currentTimeMillis();
// Taken from AnimationStarter
// Modified to change timing and allow for recycling
animationTimer = new Timer(1600, new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (panel.frameNumber > 4) {
panel.frameNumber = 0;
} else {
panel.frameNumber++;
}
panel.elapsedTimeMillis = System.currentTimeMillis() - startTime;
panel.repaint();
}
});
window.setVisible(true); // Open the window, making it visible on the screen.
animationTimer.start(); // Start the animation running.
}
public CMSC325Animate() {
// Size of Frame
setPreferredSize(new Dimension(800, 600));
}
// This is where all of the action takes place
// Code taken from AnimationStarter.java but modified to add the specific Images
// Also added looping structure for Different transformations
protected void paintComponent(Graphics g) {
/* First, create a Graphics2D drawing context for drawing on the panel.
* (g.create() makes a copy of g, which will draw to the same place as g,
* but changes to the returned copy will not affect the original.)
*/
Graphics2D g2 = (Graphics2D) g.create();
/* Turn on antialiasing in this graphics context, for better drawing.
*/
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
/* Fill in the entire drawing area with white.
*/
g2.setPaint(Color.WHITE);
g2.fillRect(0, 0, getWidth(), getHeight()); // From the old graphics API!
/* Here, I set up a new coordinate system on the drawing area, by calling
* the applyLimits() method that is defined below. Without this call, I
* would be using regular pixel coordinates. This function sets the value
* of the global variable pixelSize, which I need for stroke widths in the
* transformed coordinate system.
*/
// Controls your zoom and area you are looking at
applyWindowToViewportTransformation(g2, -75, 75, -75, 75, true);
AffineTransform savedTransform = g2.getTransform();
System.out.println("Frame is " + frameNumber);
switch (frameNumber) {
case 1: // First frame is unmodified.
translateX = 0;
translateY = 0;
scaleX = 1.0;
scaleY = 1.0;
rotation = 0;
break;
case 2: // Second frame translates each image by (-10, 12).
translateX = -10;
translateY = 12;
break;
case 3: // Third frame rotates each image by 55 degrees Counter
translateX = -10;
translateY = 12;
rotation = 55 * Math.PI / 180.0;
break;
// Can add more cases as needed
case 4: // 4th frame rotates each image by 75 degress Clockwise
translateX = -10;
translateY = 12;
rotation = 55 * Math.PI / 180.0;
rotation = 75 * Math.PI * 180;
break;
case 5: // Scales image 3.5 for x and 1.5 for y
translateX = -10;
translateY = 12;
rotation = 55 * Math.PI / 180.0;
rotation = 75 * Math.PI * 180;
scaleX = scaleX * 3.5;
scaleY = scaleY * 1.5;
break;
default:
break;
} // End switch
g2.translate(translateX, translateY); // Move image.
// To offset translate again
g2.translate(-10,10);
g2.rotate(rotation); // Rotate image.
g2.scale(scaleX, scaleY); // Scale image.
g2.drawImage(tImage, 100, 0, this); // Draw image.
g2.setTransform(savedTransform);
// draw nImage
g2.translate(translateX, translateY); // Move image.
// To offset translate again
// This allows you to place your images across your graphic
g2.translate(-30, 30);
g2.rotate(rotation); // Rotate image.
g2.scale(scaleX, scaleY); // Scale image.
g2.drawImage(nImage, 0, 0, this); // Draw image.
g2.setTransform(savedTransform);
// You can add more shapes/images as needed
// draw o Image
g2.translate(translateX, translateY); //move image
g2.translate(-10, 10);
g2.rotate(rotation);
g2.scale(scaleX, scaleY);
g2.drawImage(oImage, 0, 0, this);
g2.setTransform(savedTransform);
g2.translate(translateX, translateY); //move image
g2.translate(10, -10);
g2.rotate(rotation);
g2.scale(scaleX, scaleY);
g2.drawImage(aImage, 0, 0, this);
g2.setTransform(savedTransform);
g2.translate(translateX, translateY); //move image
g2.translate(30, -30);
g2.rotate(rotation);
g2.scale(scaleX, scaleY);
g2.drawImage(hImage, 0, 0, this);
g2.setTransform(savedTransform);
g2.translate(translateX, translateY); //move image
g2.translate(50, -50);
g2.rotate(rotation);
g2.scale(scaleX, scaleY);
g2.drawImage(heartImage, 0, 0, this);
g2.setTransform(savedTransform);
}
// Method taken directly from AnimationStarter.java Code
private void applyWindowToViewportTransformation(Graphics2D g2,
double left, double right, double bottom, double top,
boolean preserveAspect) {
int width = getWidth(); // The width of this drawing area, in pixels.
int height = getHeight(); // The height of this drawing area, in pixels.
if (preserveAspect) {
// Adjust the limits to match the aspect ratio of the drawing area.
double displayAspect = Math.abs((double) height / width);
double requestedAspect = Math.abs((bottom - top) / (right - left));
if (displayAspect > requestedAspect) {
// Expand the viewport vertically.
double excess = (bottom - top) * (displayAspect / requestedAspect - 1);
bottom += excess / 2;
top -= excess / 2;
} else if (displayAspect < requestedAspect) {
// Expand the viewport vertically.
double excess = (right - left) * (requestedAspect / displayAspect - 1);
right += excess / 2;
left -= excess / 2;
}
}
g2.scale(width / (right - left), height / (bottom - top));
g2.translate(-left, -top);
double pixelWidth = Math.abs((right - left) / width);
double pixelHeight = Math.abs((bottom - top) / height);
pixelSize = (float) Math.max(pixelWidth, pixelHeight);
}
}
Ok, first of all I totally agree that "TheNewBoston" tutorials are very... wrong at times. However that is what I was following to try to make a cube in OpenGL on android.
Anyways, I can't say that I have found great material on OpenGL to be honest. I have read through OpenGL Superbible... it was ok.
So here is the code that I have.
GLRenderer.java
package android.gem.opengltest;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import android.opengl.GLSurfaceView.Renderer;
import android.os.SystemClock;
public class GLRenderer implements Renderer {
private GLCube cube;
public GLRenderer() {
cube = new GLCube();
}
#Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
gl.glDisable(GL10.GL_DITHER);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT | GL10.GL_STENCIL_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 2, 0);
long time = SystemClock.uptimeMillis() % 4000L;
float angle = .09f * ((int) time);
gl.glRotatef(angle, 1, 1.5f, 2);
cube.draw(gl);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
float ratio = (float) width / height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 25);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
// TODO Auto-generated method stub
// START OF PERFORMANCE //
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
// END OF PERFORMANCE //
gl.glClearColor(.8f, 0, .2f, 1f); // Red, Green, Blue, Alpha (0 - 1)
gl.glClearDepthf(1f);
}
}
GLCube.java
package android.gem.opengltest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class GLCube {
private float verticies[] = {
1, 1, -1, // point 0 - topFrontRight
1, -1, -1, // point 1 - bottomFrontRight
-1, -1, -1, // point 2 - bottomFrontLeft
-1, 1, -1, // point 3 - frontTopLeft
1, 1, 1, // point 4 - topBackRight
1, -1, 1, // point 5 - bottomBackRight
-1, -1, 1, // point 6 - bottomBackLeft
-1, 1, 1 // point 7 - frontBackLeft
};
private float rgbaValues[] = {
1, 1, 0, 1,
.25f, 0, .85f, 1,
0, 1, 1, 1,
1, 1, 0, 1,
.25f, 0, .85f, 1,
0, 1, 1, 1,
.5f, .5f, .2f, 1,
.3f, .3f, .3f, 1
};
private FloatBuffer vertBuff, colorBuff;
private short[] pIndex = { // Indicies
3, 4, 0, 0, 4, 1, 3, 0, 1,
3, 7, 4, 7, 6, 4, 7, 3, 6,
3, 1, 2, 1, 6, 2, 6, 3, 2,
1, 4, 5, 5, 6, 1, 6, 5, 4
};
private ShortBuffer pBuffer;
public GLCube() {
ByteBuffer bBuff = ByteBuffer.allocateDirect(this.verticies.length * 4);
bBuff.order(ByteOrder.nativeOrder());
vertBuff = bBuff.asFloatBuffer();
vertBuff.put(this.verticies);
vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(this.pIndex.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
pBuffer = pbBuff.asShortBuffer();
pBuffer.put(pIndex);
pBuffer.position(0);
ByteBuffer cBuff = ByteBuffer.allocateDirect(this.rgbaValues.length * 4);
cBuff.order(ByteOrder.nativeOrder());
colorBuff = cBuff.asFloatBuffer();
colorBuff.put(rgbaValues);
colorBuff.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CW); // Clock Wise
gl.glEnable(GL10.GL_CULL_FACE); // Removes back end of cube
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, this.vertBuff);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, this.colorBuff);
gl.glDrawElements(GL10.GL_TRIANGLES, this.pIndex.length, GL10.GL_UNSIGNED_SHORT, this.pBuffer);
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
I get a cube that looks like this...
What am I doing wrong? What should I do to make it look like an actual cube?
Also, if it helps all my code is at the following address: https://github.com/gemurdock/OpenGlTest/tree/alpha.0.1.0
First of all, this is a (horribly deformed) cube, not a square. Unless you look at it face-on it is never going to look like a "good square" :)
Your polygon face culling appears to be culling the wrong side of your cube faces. It still looks like a cube, just an inside out cube.
This is likely because you have overridden OpenGL's default front face winding direction (GL_CCW).
When I just draw texture on SpriteBatch and set TextureWrap.Repeat everything is OK. But now I have 3D scene and I want have ground and texture must be repeated on model/mesh and this just don' t work.
public static StillModel createPlainMesh(float xs, float zs, Texture texture) {
final Mesh mesh = new Mesh(true, 4, 6, new VertexAttribute(
Usage.Position, 3, "a_position"), new VertexAttribute(
Usage.TextureCoordinates, 2, "a_texCoords"));
mesh.setVertices(new float[]
{ xs, 0f, zs, 0, 0,
xs, 0f, -zs, 0, 1,
-xs, 0f, zs, 1, 0,
-xs, 0f, -zs , 1,1
});
mesh.setIndices(new short[] { 0, 1, 2, 1, 2, 3 });
final StillModel model = new StillModel(new StillSubMesh(
"ground", mesh, GL10.GL_TRIANGLES, new Material()));
texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);
model.setMaterial(new Material("material", new TextureAttribute(texture, 0, "s_tex")));
return model;
}
I have this code. I use setWrap(TextureWrap.Repeat, TextureWrap.Repeat), but textures are still streched. I don't know why, but it looks terrible.
I solved it. If you want repeat texture on model, You must modify this:
mesh.setVertices(new float[]
{ xs, 0f, zs, 0, 0,
xs, 0f, -zs, 0, 1,
-xs, 0f, zs, 1, 0,
-xs, 0f, -zs , 1,1
});
Modify Texture Coords - change to for example 20 if You want repeat it 20times
Example:
mesh.setVertices(new float[]
{ xs, 0f, zs, 0, 0,
xs, 0f, -zs, 0, 20,
-xs, 0f, zs, 20, 0,
-xs, 0f, -zs , 20,20
});