use of com.jme3.math.ColorRGBA in project jmonkeyengine by jMonkeyEngine.
the class TangentBinormalGenerator method writeColorBuffer.
private static void writeColorBuffer(List<VertexData> vertices, ColorRGBA[] cols, Mesh mesh) {
FloatBuffer colors = BufferUtils.createFloatBuffer(vertices.size() * 4);
colors.rewind();
for (ColorRGBA color : cols) {
colors.put(color.r);
colors.put(color.g);
colors.put(color.b);
colors.put(color.a);
}
mesh.clearBuffer(Type.Color);
mesh.setBuffer(Type.Color, 4, colors);
}
use of com.jme3.math.ColorRGBA in project jmonkeyengine by jMonkeyEngine.
the class TangentBinormalGenerator method processTriangleData.
private static void processTriangleData(Mesh mesh, List<VertexData> vertices, boolean approxTangent, boolean splitMirrored) {
ArrayList<VertexInfo> vertexMap = linkVertices(mesh, splitMirrored);
FloatBuffer tangents = BufferUtils.createFloatBuffer(vertices.size() * 4);
ColorRGBA[] cols = null;
if (debug) {
cols = new ColorRGBA[vertices.size()];
}
Vector3f tangent = new Vector3f();
Vector3f binormal = new Vector3f();
//Vector3f normal = new Vector3f();
Vector3f givenNormal = new Vector3f();
Vector3f tangentUnit = new Vector3f();
Vector3f binormalUnit = new Vector3f();
for (int k = 0; k < vertexMap.size(); k++) {
float wCoord = -1;
VertexInfo vertexInfo = vertexMap.get(k);
givenNormal.set(vertexInfo.normal);
givenNormal.normalizeLocal();
TriangleData firstTriangle = vertices.get(vertexInfo.indices.get(0)).triangles.get(0);
// check tangent and binormal consistency
tangent.set(firstTriangle.tangent);
tangent.normalizeLocal();
binormal.set(firstTriangle.binormal);
binormal.normalizeLocal();
for (int i : vertexInfo.indices) {
ArrayList<TriangleData> triangles = vertices.get(i).triangles;
for (int j = 0; j < triangles.size(); j++) {
TriangleData triangleData = triangles.get(j);
tangentUnit.set(triangleData.tangent);
tangentUnit.normalizeLocal();
if (tangent.dot(tangentUnit) < toleranceDot) {
log.log(Level.WARNING, "Angle between tangents exceeds tolerance " + "for vertex {0}.", i);
break;
}
if (!approxTangent) {
binormalUnit.set(triangleData.binormal);
binormalUnit.normalizeLocal();
if (binormal.dot(binormalUnit) < toleranceDot) {
log.log(Level.WARNING, "Angle between binormals exceeds tolerance " + "for vertex {0}.", i);
break;
}
}
}
}
// find average tangent
tangent.set(0, 0, 0);
binormal.set(0, 0, 0);
int triangleCount = 0;
for (int i : vertexInfo.indices) {
ArrayList<TriangleData> triangles = vertices.get(i).triangles;
triangleCount += triangles.size();
if (debug) {
cols[i] = ColorRGBA.White;
}
for (int j = 0; j < triangles.size(); j++) {
TriangleData triangleData = triangles.get(j);
tangent.addLocal(triangleData.tangent);
binormal.addLocal(triangleData.binormal);
}
}
int blameVertex = vertexInfo.indices.get(0);
if (tangent.length() < ZERO_TOLERANCE) {
log.log(Level.WARNING, "Shared tangent is zero for vertex {0}.", blameVertex);
// attempt to fix from binormal
if (binormal.length() >= ZERO_TOLERANCE) {
binormal.cross(givenNormal, tangent);
tangent.normalizeLocal();
} else // if all fails use the tangent from the first triangle
{
tangent.set(firstTriangle.tangent);
}
} else {
tangent.divideLocal(triangleCount);
}
tangentUnit.set(tangent);
tangentUnit.normalizeLocal();
if (Math.abs(Math.abs(tangentUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
log.log(Level.WARNING, "Normal and tangent are parallel for vertex {0}.", blameVertex);
}
if (!approxTangent) {
if (binormal.length() < ZERO_TOLERANCE) {
log.log(Level.WARNING, "Shared binormal is zero for vertex {0}.", blameVertex);
// attempt to fix from tangent
if (tangent.length() >= ZERO_TOLERANCE) {
givenNormal.cross(tangent, binormal);
binormal.normalizeLocal();
} else // if all fails use the binormal from the first triangle
{
binormal.set(firstTriangle.binormal);
}
} else {
binormal.divideLocal(triangleCount);
}
binormalUnit.set(binormal);
binormalUnit.normalizeLocal();
if (Math.abs(Math.abs(binormalUnit.dot(givenNormal)) - 1) < ZERO_TOLERANCE) {
log.log(Level.WARNING, "Normal and binormal are parallel for vertex {0}.", blameVertex);
}
if (Math.abs(Math.abs(binormalUnit.dot(tangentUnit)) - 1) < ZERO_TOLERANCE) {
log.log(Level.WARNING, "Tangent and binormal are parallel for vertex {0}.", blameVertex);
}
}
Vector3f finalTangent = new Vector3f();
Vector3f tmp = new Vector3f();
for (int i : vertexInfo.indices) {
if (approxTangent) {
// Gram-Schmidt orthogonalize
finalTangent.set(tangent).subtractLocal(tmp.set(givenNormal).multLocal(givenNormal.dot(tangent)));
finalTangent.normalizeLocal();
wCoord = tmp.set(givenNormal).crossLocal(tangent).dot(binormal) < 0f ? -1f : 1f;
tangents.put((i * 4), finalTangent.x);
tangents.put((i * 4) + 1, finalTangent.y);
tangents.put((i * 4) + 2, finalTangent.z);
tangents.put((i * 4) + 3, wCoord);
} else {
tangents.put((i * 4), tangent.x);
tangents.put((i * 4) + 1, tangent.y);
tangents.put((i * 4) + 2, tangent.z);
tangents.put((i * 4) + 3, wCoord);
//setInBuffer(binormal, binormals, i);
}
}
}
tangents.limit(tangents.capacity());
// If the model already had a tangent buffer, replace it with the regenerated one
mesh.clearBuffer(Type.Tangent);
mesh.setBuffer(Type.Tangent, 4, tangents);
if (mesh.isAnimated()) {
mesh.clearBuffer(Type.BindPoseNormal);
mesh.clearBuffer(Type.BindPosePosition);
mesh.clearBuffer(Type.BindPoseTangent);
mesh.generateBindPose(true);
}
if (debug) {
writeColorBuffer(vertices, cols, mesh);
}
mesh.updateBound();
mesh.updateCounts();
}
use of com.jme3.math.ColorRGBA in project jmonkeyengine by jMonkeyEngine.
the class MipMapGenerator method scaleImage.
public static Image scaleImage(Image inputImage, int outputWidth, int outputHeight) {
int size = outputWidth * outputHeight * inputImage.getFormat().getBitsPerPixel() / 8;
ByteBuffer buffer = BufferUtils.createByteBuffer(size);
Image outputImage = new Image(inputImage.getFormat(), outputWidth, outputHeight, buffer, inputImage.getColorSpace());
ImageRaster input = ImageRaster.create(inputImage, 0, 0, false);
ImageRaster output = ImageRaster.create(outputImage, 0, 0, false);
float xRatio = ((float) (input.getWidth() - 1)) / output.getWidth();
float yRatio = ((float) (input.getHeight() - 1)) / output.getHeight();
ColorRGBA outputColor = new ColorRGBA();
ColorRGBA bottomLeft = new ColorRGBA();
ColorRGBA bottomRight = new ColorRGBA();
ColorRGBA topLeft = new ColorRGBA();
ColorRGBA topRight = new ColorRGBA();
for (int y = 0; y < outputHeight; y++) {
for (int x = 0; x < outputWidth; x++) {
float x2f = x * xRatio;
float y2f = y * yRatio;
int x2 = (int) x2f;
int y2 = (int) y2f;
float xDiff = x2f - x2;
float yDiff = y2f - y2;
input.getPixel(x2, y2, bottomLeft);
input.getPixel(x2 + 1, y2, bottomRight);
input.getPixel(x2, y2 + 1, topLeft);
input.getPixel(x2 + 1, y2 + 1, topRight);
bottomLeft.multLocal((1f - xDiff) * (1f - yDiff));
bottomRight.multLocal((xDiff) * (1f - yDiff));
topLeft.multLocal((1f - xDiff) * (yDiff));
topRight.multLocal((xDiff) * (yDiff));
outputColor.set(bottomLeft).addLocal(bottomRight).addLocal(topLeft).addLocal(topRight);
output.setPixel(x, y, outputColor);
}
}
return outputImage;
}
use of com.jme3.math.ColorRGBA in project jmonkeyengine by jMonkeyEngine.
the class DefaultImageRaster method getPixel.
@Override
public ColorRGBA getPixel(int x, int y, ColorRGBA store) {
rangeCheck(x, y);
codec.readComponents(getBuffer(), x, y, width, offset, components, temp);
if (store == null) {
store = new ColorRGBA();
}
switch(codec.type) {
case ImageCodec.FLAG_F16:
store.set(FastMath.convertHalfToFloat((short) components[1]), FastMath.convertHalfToFloat((short) components[2]), FastMath.convertHalfToFloat((short) components[3]), FastMath.convertHalfToFloat((short) components[0]));
break;
case ImageCodec.FLAG_F32:
store.set(Float.intBitsToFloat((int) components[1]), Float.intBitsToFloat((int) components[2]), Float.intBitsToFloat((int) components[3]), Float.intBitsToFloat((int) components[0]));
break;
case 0:
// Convert to float and divide by bitsize to get into range 0.0 - 1.0.
store.set((float) components[1] / codec.maxRed, (float) components[2] / codec.maxGreen, (float) components[3] / codec.maxBlue, (float) components[0] / codec.maxAlpha);
break;
}
if (codec.isGray) {
store.g = store.b = store.r;
} else {
if (codec.maxRed == 0) {
store.r = 1;
}
if (codec.maxGreen == 0) {
store.g = 1;
}
if (codec.maxBlue == 0) {
store.b = 1;
}
if (codec.maxAlpha == 0) {
store.a = 1;
}
}
if (convertToLinear) {
// Input image is sRGB, need to convert to linear.
store.setAsSrgb(store.r, store.g, store.b, store.a);
}
return store;
}
use of com.jme3.math.ColorRGBA in project jmonkeyengine by jMonkeyEngine.
the class MipMapImageRaster method setPixel.
@Override
public void setPixel(int x, int y, ColorRGBA color) {
rangeCheck(x, y);
// Check flags for grayscale
if (codec.isGray) {
float gray = color.r * 0.27f + color.g * 0.67f + color.b * 0.06f;
color = new ColorRGBA(gray, gray, gray, color.a);
}
switch(codec.type) {
case ImageCodec.FLAG_F16:
components[0] = (int) FastMath.convertFloatToHalf(color.a);
components[1] = (int) FastMath.convertFloatToHalf(color.r);
components[2] = (int) FastMath.convertFloatToHalf(color.g);
components[3] = (int) FastMath.convertFloatToHalf(color.b);
break;
case ImageCodec.FLAG_F32:
components[0] = (int) Float.floatToIntBits(color.a);
components[1] = (int) Float.floatToIntBits(color.r);
components[2] = (int) Float.floatToIntBits(color.g);
components[3] = (int) Float.floatToIntBits(color.b);
break;
case 0:
// Convert color to bits by multiplying by size
components[0] = Math.min((int) (color.a * codec.maxAlpha + 0.5f), codec.maxAlpha);
components[1] = Math.min((int) (color.r * codec.maxRed + 0.5f), codec.maxRed);
components[2] = Math.min((int) (color.g * codec.maxGreen + 0.5f), codec.maxGreen);
components[3] = Math.min((int) (color.b * codec.maxBlue + 0.5f), codec.maxBlue);
break;
}
codec.writeComponents(getBuffer(), x, y, width[mipLevel], offsets[mipLevel], components, temp);
image.setUpdateNeeded();
}
Aggregations