I am trying to render three points using array buffers, but I can't get anything rendered.
This is my code:
import java.nio.*;
import javax.media.opengl.*;
public class SimpleScene implements GLEventListener
{
private GL3 gl;
int myIdentityShader;
#Override
public void display(GLAutoDrawable drawable) {
gl.glClear(GL3.GL_COLOR_BUFFER_BIT);
gl.glUseProgram(myIdentityShader);
gl.glDrawArrays(GL3.GL_POINTS, 0, 3);
}
#Override
public void dispose(GLAutoDrawable drawable) {
gl.glDeleteProgram(myIdentityShader);
gl.glDeleteVertexArrays(1, vertexArrayObject, 0);
}
#Override
public void init(GLAutoDrawable drawable) {
gl = drawable.getGL().getGL3();
try {
myIdentityShader = createShaderProgram();
} catch (Exception e) {
e.printStackTrace();
return;
}
gl.glPointSize(30);
gl.glClearColor(0.7f, 0, 0, 1);
float[] floatData = {
0.25f, -0.25f, 0.5f, 1.0f,
-0.25f, -0.25f, 0.5f, 1.0f,
0.25f, 0.25f, 0.5f, 1.0f
};
FloatBuffer data = FloatBuffer.allocate(3 * 4);
for (int i=0;i<12;i++)
data.put(floatData[i]);
gl.glGenVertexArrays(1, vertexArrayObject, 0);
gl.glBindVertexArray(vertexArrayObject[0]);
int[] buffers = new int[1];
gl.glGenBuffers(1, buffers, 0);
gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, buffers[0]);
gl.glBufferData(GL3.GL_ARRAY_BUFFER, data.capacity(), data, GL3.GL_STATIC_DRAW);
gl.glVertexAttribPointer(2, 4, GL3.GL_FLOAT, false, 0, 0);
gl.glEnableVertexAttribArray(2);
}
#Override
public void reshape(GLAutoDrawable drawable, int arg1, int arg2, int arg3,
int arg4) {
// TODO Add reshape code
}
private String vertexShader = "#version 130 \n" +
"in vec4 position; \n" +
"void main(void) \n" +
"{ \n" +
" gl_Position = position; \n" +
"} \n";
private String fragmentShader = "#version 130 \n" +
"out vec4 vFragColor; \n" +
"void main(void) \n" +
"{ \n" +
" vFragColor = vec4(0.0, 0.8, 1.0, 1.0); \n" +
"} \n";
private int[] vertexArrayObject = new int[1];
private int createShaderProgram() throws Exception
{
int hVertexShader, hFragmentShader, hShaderProgram;
int[] successTest = new int[] {1};
hVertexShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
hFragmentShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
gl.glShaderSource(hVertexShader, 1, new String[] {vertexShader}, null);
gl.glShaderSource(hFragmentShader, 1, new String[] {fragmentShader}, null);
gl.glCompileShader(hVertexShader);
gl.glCompileShader(hFragmentShader);
gl.glGetShaderiv(hVertexShader, GL3.GL_COMPILE_STATUS, successTest, 0);
if (successTest[0] == 0)
{
byte[] infoLog = new byte[1024];
gl.glGetShaderInfoLog(hVertexShader, 1024, null, 0, infoLog, 0);
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
throw new Exception("Vertex shader compilation failed with: " + new String(infoLog));
}
gl.glGetShaderiv(hFragmentShader, GL3.GL_COMPILE_STATUS, successTest, 0);
if (successTest[0] == 0)
{
byte[] infoLog = new byte[1024];
gl.glGetShaderInfoLog(hFragmentShader, 1024, null, 0, infoLog, 0);
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
throw new Exception("Fragment shader compilation failed with: " + new String(infoLog));
}
hShaderProgram = gl.glCreateProgram();
gl.glAttachShader(hShaderProgram, hVertexShader);
gl.glAttachShader(hShaderProgram, hFragmentShader);
gl.glBindAttribLocation(hShaderProgram, 2, "position");
gl.glLinkProgram(hShaderProgram);
gl.glGetProgramiv(hShaderProgram, GL3.GL_LINK_STATUS, successTest, 0);
if (successTest[0] == 0)
{
byte[] infoLog = new byte[1024];
gl.glGetProgramInfoLog(hShaderProgram, 1024, null, 0, infoLog, 0);
gl.glDeleteProgram(hShaderProgram);
throw new Exception("Shader linking failed with: " + new String(infoLog);
}
gl.glDeleteShader(hVertexShader);
gl.glDeleteShader(hFragmentShader);
return hShaderProgram;
}
}
I am absolutely sure the shaders and the createShaderProgram method are correct. When I use glVertexAttrib4fv, all three points get rendered in the same location (as expected), but when I use glVertexAttribPointer nothing gets rendered and there’s no error (glGetError returns 0).
I discovered that glVertexAttrib4fv does not send the coordinates if the attribute index is 0, thus resulting in all points being rendered in the center of the screen. This doesn't happen with glVertexAttribPointer, so the coordinates are sent.
You are using Vertex Array Objects inefficiently. The whole point of using a VAO is so that you do not have to set your vertex attrib. pointer and enable / disable the pointers every time you draw something. Set the pointer when you initialize the VAO and since it keeps track of this state, all you have to do is change the bound VAO every time you want to draw something.
However, your actual problem is that you are never binding the vertex attribute position in your vertex shader to generic attribute location 2. Most GLSL implementations will automatically assign that vertex attribute location 0, though this is not required behavior (so do not rely on it). You can either query the location (glGetAttribLocation) of this attribute by name after you link your program, or you can bind the attribute location yourself (glBindAttribLocation). In either case, you must match the attribute location for your pointer to the attribute in the shader.
When I use glVertexAttrib4fv, all three points get rendered in the same location, but when I use glVertexAttribPointer nothing gets rendered and there’s no error (glGetError returns 0).
This is to be expected, glVertexAttrib4fv (...) sets up a constant value to use for EVERY vertex shader invocation that pulls data from that location. While it is true that it takes a pointer (in the C language bindings), that pointer is merely OpenGL's way of passing an array. If you change the value of the data pointed to after the call completes, nothing is going to happen. That is literally why there is a different class of functions to set vertex array pointers.
Update:
After seeing your updated code for this question, the real problem popped up. In Java, when you use FloatBuffer.put (...), it increments the base address of the buffer (which JOGL uses when you call glVertexAttribPointer (...)). You need to flip the buffer by calling FloatBuffer.flip (...), and this will effectively rewind the buffer so that JOGL will read beginning with the first element in the buffer.
Related
When i create test for Google Or-Tools and send my distance matrix, solution the solution is always null.
When i use default distance matrix from here https://developers.google.com/optimization/routing/vrp
but when i use my custom distanceMatrix array Assigment solution is always null.
Where is mistake?
Full test class
import com.google.ortools.constraintsolver.*;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.logging.Logger;
#RunWith(SpringRunner.class)
#SpringBootTest
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OrToolsTests {
private static final Logger logger = Logger.getLogger(OrToolsTests.class.getName());
static {
System.loadLibrary("jniortools");
}
#Test
public void b_googleOrTools() throws Exception {
// Instantiate the data problem.
final DataModel data = new DataModel();
// Create Routing Index Manager
RoutingIndexManager manager =
new RoutingIndexManager(data.data.length, data.vehicleNumber, data.depot);
// Create Routing Model.
RoutingModel routing = new RoutingModel(manager);
// Create and register a transit callback.
final int transitCallbackIndex =
routing.registerTransitCallback((long fromIndex, long toIndex) -> {
// Convert from routing variable Index to user NodeIndex.
int fromNode = manager.indexToNode(fromIndex);
int toNode = manager.indexToNode(toIndex);
return data.data[fromNode][toNode];
});
// Define cost of each arc.
routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
// Add Distance constraint.
routing.addDimension(transitCallbackIndex, 0, 3000,
true, // start cumul to zero
"Distance");
RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
distanceDimension.setGlobalSpanCostCoefficient(100);
// Setting first solution heuristic.
RoutingSearchParameters searchParameters =
main.defaultRoutingSearchParameters()
.toBuilder()
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
.build();
// Solve the problem.
Assignment solution = routing.solveWithParameters(searchParameters);
// Print solution on console.
printSolution(data, routing, manager, solution);
}
private void printSolution(
DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
// Inspect solution.
long maxRouteDistance = 0;
for (int i = 0; i < data.vehicleNumber; ++i) {
long index = routing.start(i);
logger.info("Route for Vehicle " + i + ":");
long routeDistance = 0;
String route = "";
while (!routing.isEnd(index)) {
route += manager.indexToNode(index) + " -> ";
long previousIndex = index;
index = solution.value(routing.nextVar(index));
routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
}
logger.info(route + manager.indexToNode(index));
logger.info("Distance of the route: " + routeDistance + "m");
maxRouteDistance = Math.max(routeDistance, maxRouteDistance);
}
logger.info("Maximum of the route distances: " + maxRouteDistance + "m");
}
class DataModel {
public final long[][] data = {
{0, 58305, 41338, 16599, 22834, 36364, 24979, 9797, 22023, 5880, 21282, 39248},
{58147, 0, 82634, 49102, 39605, 93558, 72909, 49687, 67379, 55889, 76274, 22047},
{41663, 81167, 0, 47046, 58798, 56366, 18071, 41586, 60532, 36117, 49432, 74933},
{15666, 49990, 53000, 0, 7358, 51077, 30428, 13558, 34534, 13408, 33793, 30933},
{22151, 39552, 59486, 7391, 0, 57563, 36914, 20043, 41019, 19893, 40278, 24535},
{36164, 93036, 56237, 51331, 57566, 0, 37419, 44529, 44381, 41822, 17567, 73980},
{25224, 72585, 18046, 30880, 37115, 37483, 0, 25147, 44093, 19678, 30549, 53529},
{9218, 49544, 41424, 13485, 19719, 44630, 25065, 0, 28086, 5966, 27345, 30488},
{22816, 72597, 60379, 34430, 40665, 44423, 44020, 27629, 0, 24921, 27138, 57079},
{6858, 56163, 36826, 14458, 20693, 42270, 20467, 6781, 25726, 0, 24985, 37107},
{22678, 75998, 49002, 34292, 40527, 17284, 30184, 27490, 27342, 24783, 0, 56941},
{38986, 22165, 76018, 29941, 24347, 74398, 53749, 30526, 57854, 36728, 57113, 0}};
public final int vehicleNumber = 4;
public final int depot = 0;
}
}
From what I understand, you add a dimension with a max cumul of 3000, while the distance matrix has a lot of inter-node distances above 10k.
The 3000 value in #addDimension represents the vehicle maximum travel distance. Since the values in your distance matrix are higher, or-tools is not able to find a solution.
To fix this you have to change the 3000 value so that it is higher than the highest value in your distance matrix. For example
change
// Add Distance constraint.
routing.addDimension(transitCallbackIndex, 0, 3000,
true, // start cumul to zero
"Distance");
to
// Add Distance constraint.
routing.addDimension(transitCallbackIndex, 0, 100000,
true, // start cumul to zero
"Distance");
and your code will work.
My app features an InfiniteScrollAdapter populated with images through URLImage and URLImage.ImageAdapter.
In the simulator (Iphone3GS or Xoom or GoogleNexus7), and NPE is shown the first time the InfiniteScrollAdapter appears, although the file does exist on the server.
Please note : In this test there was only one entry in the database. So on the image below what you should see is the same row (image + text) duplicated 3 times.
Please note that the order in the undisplayed icon can differ
The code I used to download the image is :
Image tempPlaceholder = Image.createImage(
ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX,
ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX,
ParametresGeneraux.accentColor);
Graphics gr = tempPlaceholder.getGraphics();
gr.setAntiAliased(true);
gr.setColor(ParametresGeneraux.accentColor);
gr.fillArc(0, 0, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 0, 360);
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
final Image reportImage = URLImage.createToStorage(
roundPlaceholder,
photoFilenameInStorage,
currentReport.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
);
And here is the overridden imageAdapter method :
public final static URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() {
#Override
public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) {
final Image[] tmp = new Image[1];
if (!Display.getInstance().isEdt()) {
// The image scaling has to be called from EDT
Display.getInstance().callSeriallyAndWait(() -> {
tmp[0] = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight());
if (tmp[0].getWidth() > placeholderImage.getWidth()) {
int diff = tmp[0].getWidth() - placeholderImage.getWidth();
int x = diff / 2;
tmp[0] = tmp[0].subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true);
} else if (tmp[0].getHeight() > placeholderImage.getHeight()) {
int diff = tmp[0].getHeight() - placeholderImage.getHeight();
int y = diff / 2;
tmp[0] = tmp[0].subImage(0, y, Math.min(placeholderImage.getWidth(), tmp[0].getWidth()),
Math.min(placeholderImage.getHeight(), tmp[0].getHeight()), true);
}
});
} else {
tmp[0] = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight());
if (tmp[0].getWidth() > placeholderImage.getWidth()) {
int diff = tmp[0].getWidth() - placeholderImage.getWidth();
int x = diff / 2;
tmp[0] = tmp[0].subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true);
} else if (tmp[0].getHeight() > placeholderImage.getHeight()) {
int diff = tmp[0].getHeight() - placeholderImage.getHeight();
int y = diff / 2;
tmp[0] = tmp[0].subImage(0, y, Math.min(placeholderImage.getWidth(), tmp[0].getWidth()),
Math.min(placeholderImage.getHeight(), tmp[0].getHeight()), true);
}
}
EncodedImage[] image2Return = new EncodedImage[1];
if (!Display.getInstance().isEdt()) {
// The image scaling has to be called from EDT
Display.getInstance().callSeriallyAndWait(() -> {
Image roundMask = Image.createImage(tmp[0].getWidth(), tmp[0].getHeight(), 0xff000000);
Graphics gr = roundMask.getGraphics();
gr.setColor(0xffffff);
gr.fillArc(0, 0, tmp[0].getWidth(), tmp[0].getHeight(), 0, 360);
Object mask = roundMask.createMask();
tmp[0] = tmp[0].applyMask(mask);
image2Return[0] = EncodedImage.createFromImage(tmp[0], false);
});
} else {
Image roundMask = Image.createImage(tmp[0].getWidth(), tmp[0].getHeight(), 0xff000000);
Graphics gr = roundMask.getGraphics();
gr.setColor(0xffffff);
gr.fillArc(0, 0, tmp[0].getWidth(), tmp[0].getHeight(), 0, 360);
Object mask = roundMask.createMask();
tmp[0] = tmp[0].applyMask(mask);
image2Return[0] = EncodedImage.createFromImage(tmp[0], false);
}
return image2Return[0];
}
In the stacktrace, the NPE seems to stem from the overridden URLImage.ImageAdapter :
java.lang.IllegalArgumentException: create image failed for the given
image data of length: 0 at
com.codename1.ui.Image.createImage(Image.java:654) at
com.codename1.ui.EncodedImage.getInternal(EncodedImage.java:365) at
com.codename1.ui.EncodedImage.getInternalImpl(EncodedImage.java:340)
at com.codename1.ui.EncodedImage.getHeight(EncodedImage.java:522) at
com.codename1.ui.Image.scaledLargerRatio(Image.java:899) at
com.my.application.ParametresGeneraux$1.lambda$adaptImage$0(ParametresGeneraux.java:564)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:95) at
com.codename1.ui.Display.processSerialCalls(Display.java:1154) at
com.codename1.ui.Display.edtLoopImpl(Display.java:1098) at
com.codename1.ui.Display.invokeAndBlock(Display.java:1207) at
com.codename1.ui.Display.invokeAndBlock(Display.java:1244) at
com.codename1.ui.URLImage$DownloadCompleted.actionPerformed(URLImage.java:233)
at com.codename1.ui.URLImage$4.onSucess(URLImage.java:301) at
com.codename1.ui.URLImage$4.onSucess(URLImage.java:297) at
com.codename1.util.CallbackDispatcher.run(CallbackDispatcher.java:53)
at com.codename1.ui.Display.processSerialCalls(Display.java:1154) at
com.codename1.ui.Display.edtLoopImpl(Display.java:1098) at
com.codename1.ui.Display.mainEDTLoop(Display.java:999) at
com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) at
com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
[EDT] 0:0:0,1 - Codename One revisions:
e5c43877074c18b4b5c7748d000e5cfac75ab749 2318
[EDT] 0:0:0,1 - Exception: java.lang.NullPointerException - null
java.lang.NullPointerException at
com.codename1.impl.javase.JavaSEPort.scale(JavaSEPort.java:3996) at
com.codename1.ui.Image.scale(Image.java:1007) at
com.codename1.ui.Image.scaledImpl(Image.java:953) at
com.codename1.ui.Image.scaled(Image.java:918) at
com.codename1.impl.javase.JavaSEPort$71.save(JavaSEPort.java:7659) at
com.codename1.ui.EncodedImage.scaledEncoded(EncodedImage.java:626) at
com.codename1.ui.EncodedImage.scaled(EncodedImage.java:653) at
com.codename1.ui.Image.scaledLargerRatio(Image.java:904) at
com.my.application.ParametresGeneraux$1.lambda$adaptImage$0(ParametresGeneraux.java:564)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:95) at
com.codename1.ui.Display.processSerialCalls(Display.java:1154) at
com.codename1.ui.Display.edtLoopImpl(Display.java:1098) at
com.codename1.ui.Display.invokeAndBlock(Display.java:1207) at
com.codename1.ui.Display.invokeAndBlock(Display.java:1244) at
com.codename1.ui.URLImage$DownloadCompleted.actionPerformed(URLImage.java:233)
at com.codename1.ui.URLImage$4.onSucess(URLImage.java:301) at
com.codename1.ui.URLImage$4.onSucess(URLImage.java:297) at
com.codename1.util.CallbackDispatcher.run(CallbackDispatcher.java:53)
at com.codename1.ui.Display.processSerialCalls(Display.java:1154) at
com.codename1.ui.Display.edtLoopImpl(Display.java:1098) at
com.codename1.ui.Display.mainEDTLoop(Display.java:999) at
com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) at
com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
Moreover, a glance in the .cn1 directory shows the URLImage storage file name with the suffix "ImageURLTMP" which does not appear when everything works without NPE.
Finally, if I come back to this form later, everything works as expected (images were shown, no NPE). I tried to test for downloadedImage nullness in imageAdapter but the EncodedImage is not null.
How can I avoid this NPE?
Edit March 1st 2017
Following the answers from #Diamond and #Shai, I believe the NPE occurs because the InfiniteScrollAdapter wants to fill in the screen with rows and consequently launches the download of the same image simultaneously (because it is not in cache). So a solution could be to prevent the InfiniteScrollAdapter to loop (so it becomes finite). How can I do that ?
Please also note that there is not 404 error, the Network monitor shows response code 200 as depicted below. However the image should not be downloaded 3 times, should it ?
Change your ImageAdapter to the following:
public static final URLImage.ImageAdapter RESIZE_SCALE_WITH_ROUND_MASK = new URLImage.ImageAdapter() {
#Override
public EncodedImage adaptImage(EncodedImage downloadedImage, EncodedImage placeholderImage) {
Image tmp = downloadedImage.scaledLargerRatio(placeholderImage.getWidth(), placeholderImage.getHeight());
if (tmp.getWidth() > placeholderImage.getWidth()) {
int diff = tmp.getWidth() - placeholderImage.getWidth();
int x = diff / 2;
tmp = tmp.subImage(x, 0, placeholderImage.getWidth(), placeholderImage.getHeight(), true);
} else if (tmp.getHeight() > placeholderImage.getHeight()) {
int diff = tmp.getHeight() - placeholderImage.getHeight();
int y = diff / 2;
tmp = tmp.subImage(0, y, Math.min(placeholderImage.getWidth(), tmp.getWidth()),
Math.min(placeholderImage.getHeight(), tmp.getHeight()), true);
}
Image roundMask = Image.createImage(tmp.getWidth(), tmp.getHeight(), 0xff000000);
Graphics gr = roundMask.getGraphics();
gr.setColor(0xffffff);
gr.fillArc(0, 0, tmp.getWidth(), tmp.getHeight(), 0, 360);
Object mask = roundMask.createMask();
tmp = tmp.applyMask(mask);
return EncodedImage.createFromImage(tmp, false);
}
#Override
public boolean isAsyncAdapter() {
return true;
}
};
No need to check EDT.
Make sure your tempPlaceholder image is applied to your component first and at the end of your logic, call your URLImage in a callSerially() method:
Image tempPlaceholder = Image.createImage(
ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX,
ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX,
ParametresGeneraux.accentColor);
Graphics gr = tempPlaceholder.getGraphics();
gr.setAntiAliased(true);
gr.setColor(ParametresGeneraux.accentColor);
gr.fillArc(0, 0, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, ParametresGeneraux.SIZE_OF_REPORT_PIC_IN_PX, 0, 360);
myComponent.setIcon(tempPlaceholder);
...
//Then call this at the end of everything
Display.getInstance().callSerially(() -> {
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
final Image reportImage = URLImage.createToStorage(
roundPlaceholder,
photoFilenameInStorage,
currentReport.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
);
myComponent.setIcon(reportImage);
myComponent.getComponentForm().repaint();
});
Edit:
Based on #Shai's answer, you could check if you are currently downloading the same image and prevent another one from being pulled. Because this usually causes a conflict:
//Declare this at the top of your class
final static private Map<String, Image> LOADED_URLS = new HashMap<>();
//Then change the URLImage image method to this
Display.getInstance().callSerially(() -> {
EncodedImage roundPlaceholder = EncodedImage.createFromImage(tempPlaceholder, true);
final Image reportImage = LOADED_URLS.containsKey(photoFilenameInStorage) ? LOADED_URLS.get(photoFilenameInStorage)
: URLImage.createToStorage(
roundPlaceholder,
photoFilenameInStorage,
currentReport.getPhotoPath(),
ParametresGeneraux.RESIZE_SCALE_WITH_ROUND_MASK
);
LOADED_URLS.put(photoFilenameInStorage, reportImage);
myComponent.setIcon(reportImage);
myComponent.getComponentForm().repaint();
});
In your adapter check if downloadedImage.getData() is null. I assume it's not and it's a 404 error page or something similar to that.
In that case your adapter can catch the exception and just return a fallback that matches what you expect to see when no image exists.
This works the second time around since the system sees the tmp file and assumes a download is in progress so it doesn't invoke the download code again. The tmp file is later renamed to the final downloadable file.
I'm wondering how to get my current camera perspective in an OSM map. I want to save my current camera perspective so that when I refresh the map (with mapView.invalidate()), it will go back to where I was before the refresh (zoom level and latitude/longitude). Right now, I'm only going back to a default location, which is not what I want. I've been searching for a while to no avail, any help is appreciated.
I currently have an update() method which, when called, attempts to reset the zoom level:
void update(boolean zoomToFit) {
if(selectedStop != null) {
new GetBusInfo().execute(selectedStop);
selectedBus = null;
}
busLocnOverlay.removeAllItems();
mapView.invalidate();
Log.d(LOG_TAG, "update - ZOOM_TO_SPAN1: " + ZOOM_TO_SPAN_1);
if (ZOOM_TO_SPAN_1 != 0 && ZOOM_TO_SPAN_2 != 0)
mapView.getController().zoomToSpan(ZOOM_TO_SPAN_1, ZOOM_TO_SPAN_2);
}
It's currently not working, which leads me to think that there's something else responsible for setting the zoom level. ZOOM_TO_SPAN1/2 are set when I plot objects onto the map - the code snippet is quite long so I won't put all of it, but it basically looks like this:
private void plotBuses(boolean zoomToFit) {
// bunch of stuff here
for (GeoPoint p : points) {
int lat = p.getLatitudeE6();
int lon = p.getLongitudeE6();
maxLat = Math.max(lat, maxLat);
minLat = Math.min(lat, minLat);
maxLon = Math.max(lon, maxLon);
minLon = Math.min(lon, minLon);
}
mapController.zoomToSpan(Math.abs(maxLat - minLat), Math.abs(maxLon - minLon));
mapController.animateTo(new GeoPoint( (maxLat + minLat)/2, (maxLon + minLon)/2 ));
ZOOM_TO_SPAN_1 = Math.abs(maxLat - minLat);
ZOOM_TO_SPAN_2 = Math.abs(maxLon - minLon);
}
}
I use jmonkeyengine and I downloaded a spaceship model from blendswap and converted it to j3o to load it with jmonkeyengine for a space scene where I can control the ship and travel around. However the spaceship is not loaded. The space and planets appear but I want the spaceship to be what the player controls and not first-person like it appears.
I expect the spaceship to appear because I load it without errors and add it to the scene but it stil doesn't show.
//add saucer
ufoNode = (Node) assetManager
.loadModel("usaucer_v01.j3o");
rootNode.attachChild(ufoNode);
What should I do to make the spaceship appear? The program is
public class PlanetSimpleTest extends SimpleApplication {
private PlanetAppState planetAppState;
private Geometry mark;
private Node ufoNode;
private GameCharControl ufoControl;
Camera cam2;
public static void main(String[] args){
AppSettings settings = new AppSettings(true);
settings.setResolution(1024,768);
PlanetSimpleTest app = new PlanetSimpleTest();
app.setSettings(settings);
//app.showSettings = true;
app.start();
}
#Override
public void simpleInitApp() {
// Only show severe errors in log
java.util.logging.Logger.getLogger("com.jme3").setLevel(java.util.logging.Level.SEVERE);
// Toggle mouse cursor
inputManager.addMapping("TOGGLE_CURSOR",
new MouseButtonTrigger(MouseInput.BUTTON_LEFT),
new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addListener(actionListener, "TOGGLE_CURSOR");
// Toggle wireframe
inputManager.addMapping("TOGGLE_WIREFRAME",
new KeyTrigger(KeyInput.KEY_T));
inputManager.addListener(actionListener, "TOGGLE_WIREFRAME");
// Collision test
inputManager.addMapping("COLLISION_TEST",
new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
inputManager.addListener(actionListener, "COLLISION_TEST");
// Setup camera
// In orbit
this.getCamera().setLocation(new Vector3f(0f, 0f, 180000f));
// On surface
//this.getCamera().setLocation(new Vector3f(-6657.5254f, 27401.822f, 57199.777f));
//this.getCamera().lookAtDirection(new Vector3f(0.06276598f, 0.94458306f, -0.3222158f), Vector3f.UNIT_Y);
// Add sun
//PointLight sun = new PointLight();
//sun.setPosition(new Vector3f(-100000f,0,180000f));
DirectionalLight sun = new DirectionalLight();
sun.setDirection(new Vector3f(-.1f, 0f, -1f));
sun.setColor(new ColorRGBA(0.75f,0.75f,0.75f,1.0f));
rootNode.addLight(sun);
// Add sky
Node sceneNode = new Node("Scene");
sceneNode.attachChild(Utility.createSkyBox(this.getAssetManager(), "Textures/blue-glow-1024.dds"));
rootNode.attachChild(sceneNode);
// Create collision test mark
Sphere sphere = new Sphere(30, 30, 5f);
mark = new Geometry("mark", sphere);
Material mark_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mark_mat.setColor("Color", ColorRGBA.Red);
mark.setMaterial(mark_mat);
// Add planet app state
planetAppState = new PlanetAppState(rootNode, sun);
stateManager.attach(planetAppState);
// Add planet
FractalDataSource planetDataSource = new FractalDataSource(4);
planetDataSource.setHeightScale(900f);
Planet planet = Utility.createEarthLikePlanet(getAssetManager(), 63710.0f, null, planetDataSource);
planetAppState.addPlanet(planet);
rootNode.attachChild(planet);
// Add moon
FractalDataSource moonDataSource = new FractalDataSource(5);
moonDataSource.setHeightScale(300f);
Planet moon = Utility.createMoonLikePlanet(getAssetManager(), 20000, moonDataSource);
planetAppState.addPlanet(moon);
rootNode.attachChild(moon);
moon.setLocalTranslation(-150000f, 0f, 0f);
//add saucer
ufoNode = (Node) assetManager
.loadModel("usaucer_v01.j3o");
ufoNode.setLocalScale(100f);
rootNode.attachChild(ufoNode);
}
#Override
public void simpleUpdate(float tpf) {
// slow camera down as we approach a planet
Planet planet = planetAppState.getNearestPlanet();
if (planet != null && planet.getPlanetToCamera() != null) {
this.getFlyByCamera().setMoveSpeed(
FastMath.clamp(planet.getDistanceToCamera(), 100, 100000));
}
}
private ActionListener actionListener = new ActionListener(){
public void onAction(String name, boolean pressed, float tpf){
if (name.equals("TOGGLE_CURSOR") && !pressed) {
if (inputManager.isCursorVisible()) {
inputManager.setCursorVisible(false);
} else {
inputManager.setCursorVisible(true);
}
}
if (name.equals("TOGGLE_WIREFRAME") && !pressed) {
for (Planet planet: planetAppState.getPlanets()) {
planet.toogleWireframe();
}
}
if (name.equals("COLLISION_TEST") && !pressed) {
CollisionResults results = new CollisionResults();
Ray ray = new Ray(cam.getLocation(), cam.getDirection());
// Test collision with closest planet's terrain only
planetAppState.getNearestPlanet().getTerrainNode().collideWith(ray, results);
System.out.println("----- Collisions? " + results.size() + "-----");
for (int i = 0; i < results.size(); i++) {
// For each hit, we know distance, impact point, name of geometry.
float dist = results.getCollision(i).getDistance();
Vector3f pt = results.getCollision(i).getContactPoint();
String hit = results.getCollision(i).getGeometry().getName();
System.out.println("* Collision #" + i);
System.out.println(" You shot " + hit + " at " + pt + ", " + dist + " wu away.");
}
if (results.size() > 0) {
// The closest collision point is what was truly hit:
CollisionResult closest = results.getClosestCollision();
// Let's interact - we mark the hit with a red dot.
mark.setLocalTranslation(closest.getContactPoint());
rootNode.attachChild(mark);
} else {
// No hits? Then remove the red mark.
rootNode.detachChild(mark);
}
}
}
};
}
The spaceship I took from here and converted to jme3:s binary format j3o and added to the game, but I'm obviously not doing everything to make it appear in the scene. I've gotten this far in the jmonkeyengine IDE but then when I load it in Eclipse it doesn't work so I'm trying to create the scene with the jmonkeyengine IDE first.
I then try and create a scene with the spaceship but I get an Exception in the JME SDK.
After adding the lines
ufoNode.setLocalScale(300f);
ufoNode.setLocalTranslation((new Vector3f(10f, 10f, 180010f)));
the spaceship does appear but maybe not perfect. Can it be improved?
Update 140104 17:54 CET
It seems the spaceship was upside down(?) so I've rotated it now.
//add saucer
ufoNode = (Node) assetManager.loadModel("usaucer_v01.j3o");
ufoNode.setLocalScale(1000f);
ufoNode.setLocalTranslation((new Vector3f(10f, 10f, 165000f)));
/* This quaternion stores a 180 degree rolling rotation */
Quaternion roll180 = new Quaternion();
roll180.fromAngleAxis(FastMath.PI , new Vector3f(0,0,1));
/* The rotation is applied: The object rolls by 180 degrees. */
ufoNode.setLocalRotation(roll180);
rootNode.attachChild(ufoNode);
You add the spaceship at 0,0,0 (as you don't move it) but have moved your camera to 0f, 0f, 180000f. Most likely it is out of shot or far too small to see.
Try loading the spaceship within the jME SDK and confirm that it works within the engine using the scene editor there.
If that works then try a simple test scene just dropping the spaceship and camera in - then once that works move a step at a time towards your desired setting.
I am coding a simple diagram that parses a .tsv file that has 6 columns and 9 rows. I am attempting to put some text on my diagram that is coloured according to the data existing in the third column. I am able to get all the colours on the screen, but for some reason, the text that ends up red is the text corresponding to the row (in the tsv file) BELOW the row whose text I want to be red. For example, while I want the Liberal candidate to have a fill of (200,60,60), the Parti Quebecois candidate appearing in the row below instead becomes red. Following, the New Dem party candidate ends up with the fill of (155,191,219). The code appears as follows:
PImage mapOfCanada; // background map
Premier[] premiers; // premiers data
void setup() {
size(800, 800);
// modified mapOfCanada from http://www.theblog.ca/map-canada
mapOfCanada = loadImage("bigmapofcanada.png");
// from http://en.wikipedia.org/wiki/List_of_current_Canadian_first_ministers
Table table = new Table("premiers.tsv");
int rows = table.getRowCount();
premiers = new Premier[rows];
// read through each row of the source data to populate our premiers array
for (int i=0; i<rows; i++) {
String name = table.getString(i, 0);
String province = table.getString(i, 1);
String party = table.getString(i, 2);
String imgFile = table.getString(i, 3);
PImage img = loadImage(imgFile);
float x = table.getFloat(i,4);
float y = table.getFloat(i,5);
premiers[i] = new Premier(name, province, party, img, x, y);
}
}
void draw() {
background(255);
// draw the background image with a light tint
tint(255, 25);
image(mapOfCanada, 0, 0);
// draw each premier
noTint();
for (Premier premier : premiers) {
image(premier.img, premier.x, premier.y);
}
//drawing lines for those premier images that cannot fit in the alloted province space
line(158,560,145,460); //Alberta
line(300,560,340,500); //Manitoba
line(650,365,670,410); //Newfoundland
line(750,385,710,535); //PEI
line(730,575,720,550); //Nova Scotia
line(670,595,680,560); //New Brunswick
//adding text labels
for (Premier premier : premiers) { //reading through the source data in a loop
textSize(10); //making the text size small yet readable
textAlign(CENTER); //making sure the text is centered above the image
text(premier.name, premier.x+50, premier.y-10); //positioning the text in relation to the x and y coordinates on the source data
{
String string1 = new String("Liberal");
String string2 = new String("Parti Quebecois");
String string3 = new String("New Democratic");
String string4 = new String ("Progressive Conservative");
String string5 = new String ("Saskatchewan Party");
String string6 = new String ("Yukon Party");
if (premier.party.equals("Liberal")) {
fill(200,60,60);
}
else if (premier.party.equals("Parti Quebecois")) {
fill(155,191,219);
}
else if (premier.party.equals("New Democratic")) {
fill(180,151,107);
}
else if(premier.party.equals("Progressive Conservative")) {
fill(96,104,250);
}
else if(premier.party.equals("Saskatchewan Party")) {
fill (107,180,119);
}
else if(premier.party.equals("Yukon Party")) {
fill (47,85,232);
}
else {
fill (0,0,0);
}
}
}
}
class Premier {
String name, province, party;
PImage img; // this is the thumbnail image
float x, y; // these are the coordinates for the thumbnail
Premier(String name, String province, String party, PImage img, float x, float y) {
this.name = name;
this.province = province;
this.party = party;
this.img = img;
this.x = x;
this.y = y;
}
}
Any help re: what I'm doing wrong would be much appreciated! I've edited the post to feature the full code.
Thank you!
Seems like a one off error in the loop that wraps the code that you have posted.
According to the description of an issue you're having, it may be related to indexing error - i.e. using 0-based indexing where it's actually 1-based or vice versa. But without the loop code and fill() code it will be very hard to pinpoint the problem.