Hello all,
I try to create a Terrain System with an Editor. This video shows the progress of my project.
http://www.youtube.com/watch?v=GFcp4kS8Js8
But as you can see, the texture wich is applying is not Blender with the terrainTexture and I wish you could help me to know where is my mistake.
[java]
public void paintAt(int x, int y){
int brushSize = listeBrush.get(currentBrush).brushSize;
for(int i = x-brushSize/2; i<x+brushSize/2;i++){
for(int j = y-brushSize/2;j<y+brushSize/2;j++){
if(!( i > textureSize-1 || j > textureSize-1 || j < 0 || i < 0)){
int CA = currentImg.img.getRGB(i, j); //Texture wich is currently used to paint
int CB = terrainTexture.backImg.getRGB(i, j); //The alpha Map
//In the next i get the pixel of the brush wich is give me a float beetween [0-255] and i normalize this value to have a percentage [0-1]
int Alpha = (255-(int) listeBrush.get(currentBrush).brushHeight[(i-x+brushSize/2)*brushSize+(j-y+brushSize/2)])/255;
int CC = (int) (Alpha * CB + (1 - Alpha) * CA);
terrainTexture.backImg.setRGB(i, j, CC);
}
}
}
terrainTexture.refreshTexture();
}[/java]
I used this link http://stackoverflow.com/questions/746899/how-to-calculate-an-rgb-colour-by-specifying-an-alpha-blending-amount
My aim is to create something like that : (with blended transition)
http://thumbs2.modthesims.info/img/2/6/2/7/7/MTS2_pixelhate_911997_Teraint_2.jpg
Maybe you want to look at the source of the jMP Terrain Editor, it has smoothing etc.
I looked at the source, but I do not understand at all how it works. Beside, the person who programmed, used ColorRGBA, while I used java.awt.Color instead.
Just below, I put the sources of the function that lets you manipulate the image pixels. (in Terrain Editor) But I want to know how the image.data of com.jme3.texture.Image works. Because right now, I use AWT BufferedImage class and I am forced to convert each frame and that’s greatly reduces performance.
[java]
protected void doPaintAction(int texIndex, Image image, Vector2f uv, boolean dragged, float radius, boolean erase, float fadeFalloff){
Vector2f texuv = new Vector2f();
ColorRGBA color = ColorRGBA.Black;
float width = image.getWidth();
float height = image.getHeight();
int minx = (int) (uv.xwidth - radiuswidth); // convert percents to pixels to limit how much we iterate
int maxx = (int) (uv.xwidth + radiuswidth);
int miny = (int) (uv.yheight - radiusheight);
int maxy = (int) (uv.yheight + radiusheight);
float radiusSquared = radiusradius;
float radiusFalloff = radiusfadeFalloff;
// go through each pixel, in the radius of the tool, in the image
for (int y = miny; y < maxy; y++){
for (int x = minx; x < maxx; x++){
texuv.set((float)x / width, (float)y / height);// gets the position in percentage so it can compare with the mouse UV coordinate
float dist = texuv.distanceSquared(uv);
if (dist < radiusSquared ) { // if the pixel is within the distance of the radius, set a color (distance times intensity)
manipulatePixel(image, x, y, color, false); // gets the color at that location (false means don’t write to the buffer)
// calculate the fade falloff intensity
float intensity = 0.1f;
if (dist > radiusFalloff) {
float dr = radius - radiusFalloff; // falloff to radius length
float d2 = dist - radiusFalloff; // dist minus falloff
d2 = d2/dr; // dist percentage of falloff length
intensity = 1-d2; // fade out more the farther away it is
}
//if (dragged)
// intensity = intensity*0.1f; // magical divide it by 10 to reduce its intensity when mouse is dragged
if (erase) {
switch (texIndex) {
case 0:
color.r -= intensity; break;
case 1:
color.g -= intensity; break;
case 2:
color.b -= intensity; break;
case 3:
color.a -= intensity; break;
}
} else {
switch (texIndex) {
case 0:
color.r += intensity; break;
case 1:
color.g += intensity; break;
case 2:
color.b += intensity; break;
case 3:
color.a += intensity; break;
}
}
color.clamp();
manipulatePixel(image, x, y, color, true); // set the new color
}
}
}
image.getData(0).rewind();
}
/**
- We are only using RGBA8 images for alpha textures right now.
-
@param image to get/set the color on
-
@param x location
-
@param y location
-
@param color color to get/set
-
@param write to write the color or not
*/
protected void manipulatePixel(Image image, int x, int y, ColorRGBA color, boolean write){
ByteBuffer buf = image.getData(0);
int width = image.getWidth();
int position = (y * width + x) * 4;
if ( position> buf.capacity()-1 || position<0 )
return;
if (write) {
switch (image.getFormat()){
case RGBA8:
buf.position( position );
buf.put(float2byte(color.r))
.put(float2byte(color.g))
.put(float2byte(color.b))
.put(float2byte(color.a));
return;
default:
throw new UnsupportedOperationException("Image format: "+image.getFormat());
}
} else {
switch (image.getFormat()){
case RGBA8:
buf.position( position );
color.set(byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get()), byte2float(buf.get()));
return;
default:
throw new UnsupportedOperationException("Image format: "+image.getFormat());
}
}
}[/java]
Uh, you are actually painting an image on to the texture? No splatting?
The way the textures work for the terrain editor, and for terrain, is a splatting technique. The terrain material has an alpha texture where each RGBA component is used for one of four textures. When the editor in jMP paints, it is just modifying one of the RGBA values for the alpha splat texture. Then in the material, the fragment shader blends the textures together based on that alpha splat texture.
The image used in the manipulatePixel method is a jme image and you can modify the actual Texture2d image data directly and you do not have to convert it to/from a BufferedImage each frame.
The problem with the splatting technique is the number of texture you can implement to edit your terrain Texture. In the softwarehttp://www.earthsculptor.com/index.htm they have a lighting map and 8 detail Texture how can i do this with only 4 channel RGBA ?
I just tried to test if it’s possible without splatting technique.
I am modifying the terrain material to support up to 12 diffuse textures in the coming week or two. One of those textures can be a lighting map if you so choose.
It also supports normal maps for each diffuse texture to compliment any detail textures you are using.
I’ll wait until you finish to start creating my method. Can you tell me what the trick you will use ?