JVM CRASH EXCEPTION_ACCESS_VIOLATION - Extremely Large Mesh

Hi,



i have a problem and it is reproducible.



It happens when loading an extremely large mesh with about 2,000,000 triangles … 6,000,000 vertexes.



I am using a custom mesh and i am using FloatBuffers to hand down the vertexes with Normals and Color in Triangle mode.



And it happens at rendering-time as you can see in the below thread.



Is it not intended to do that large objects or is it simply a bug???



Here is the error message:


#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006908729a, pid=3496, tid=2476
#
# JRE version: 6.0_25-b06
# Java VM: Java HotSpot(TM) 64-Bit Server VM (20.0-b11 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [atio6axx.dll+0x5729a]
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

T H R E A D

Current thread (0x0000000006152800): JavaThread "LWJGL Renderer Thread" [_thread_in_native, id=2476, stack(0x0000000007470000,0x0000000007570000)]

siginfo: ExceptionCode=0xc0000005, writing address 0x0000000007a19004

Registers:
RAX=0x0000000000000000, RBX=0x000000000793cb10, RCX=0x0000000000000c00, RDX=0x0000000000000001
RSP=0x000000000756e4a0, RBP=0x00000000083d2470, RSI=0x0000000000000007, RDI=0x00000000083d2460
R8 =0x0000000004014c00, R9 =0x0000000007a19004, R10=0x000000000b6ff8d0, R11=0x0000000008407c40
R12=0x0000000000000607, R13=0x0000000000000417, R14=0x0000000000004d18, R15=0x0000000000000000
RIP=0x000000006908729a, EFLAGS=0x0000000000010246

Top of Stack: (sp=0x000000000756e4a0)
0x000000000756e4a0: 000000000793cb10 00000000000000b8
0x000000000756e4b0: 000001100002000d 00000000078e0470
0x000000000756e4c0: 0000000077667288 0000000000000000
0x000000000756e4d0: 0000000000000050 000007fefdf04572
0x000000000756e4e0: 0000000000000040 0000000000000040
0x000000000756e4f0: 0000000000000015 0000000000000000
0x000000000756e500: 0000000040003480 0000000000000000
0x000000000756e510: 000000000756e730 0000000000000124
0x000000000756e520: 0000000000000015 0000000000000000
0x000000000756e530: 0000000003a72900 000000000756ead0
0x000000000756e540: 000000000bcadc10 0000000000000000
0x000000000756e550: 0000000000000000 0000000000000000
0x000000000756e560: 0000000000000000 0000000000000000
0x000000000756e570: 0000000000000000 0000000000000000
0x000000000756e580: 0000000000000000 0000000000000000
0x000000000756e590: 0000000000000000 0000000000000000

Instructions: (pc=0x000000006908729a)
0x000000006908727a: 8b c8 83 e1 02 25 3c 10 00 00 0b c1 41 8b c8 81
0x000000006908728a: e1 00 0c 00 00 d1 e8 81 f9 00 0c 00 00 0f 94 c2
0x000000006908729a: 41 81 21 00 00 00 ff 41 c1 e8 0e 83 e2 01 41 81
0x00000000690872aa: e0 ff fd 03 00 45 09 01 c1 e2 0f 0b c2 41 89 41


Register to memory mapping:

RAX=0x0000000000000000 is an unknown value
RBX=0x000000000793cb10 is an unknown value
RCX=0x0000000000000c00 is an unknown value
RDX=0x0000000000000001 is an unknown value
RSP=0x000000000756e4a0 is pointing into the stack for thread: 0x0000000006152800
RBP=0x00000000083d2470 is an unknown value
RSI=0x0000000000000007 is an unknown value
RDI=0x00000000083d2460 is an unknown value
R8 =0x0000000004014c00 is an unknown value
R9 =0x0000000007a19004 is an unknown value
R10=0x000000000b6ff8d0 is an unknown value
R11=0x0000000008407c40 is an unknown value
R12=0x0000000000000607 is an unknown value
R13=0x0000000000000417 is an unknown value
R14=0x0000000000004d18 is an unknown value
R15=0x0000000000000000 is an unknown value


Stack: [0x0000000007470000,0x0000000007570000], sp=0x000000000756e4a0, free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [atio6axx.dll+0x5729a] DrvPresentBuffers+0x64ca

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.lwjgl.opengl.GL15.nglBufferData(IJLjava/nio/Buffer;IIJ)V+0
j org.lwjgl.opengl.GL15.glBufferData(ILjava/nio/FloatBuffer;I)V+37
j com.jme3.renderer.lwjgl.LwjglRenderer.updateBufferData(Lcom/jme3/scene/VertexBuffer;)V+266
J com.jme3.renderer.lwjgl.LwjglRenderer.renderMeshDefault(Lcom/jme3/scene/Mesh;II)V
J com.jme3.material.Material.render(Lcom/jme3/scene/Geometry;Lcom/jme3/renderer/RenderManager;)V
J com.jme3.renderer.queue.RenderQueue.renderGeometryList(Lcom/jme3/renderer/queue/GeometryList;Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/Camera;Z)V
j com.jme3.renderer.queue.RenderQueue.renderQueue(Lcom/jme3/renderer/queue/RenderQueue$Bucket;Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/Camera;Z)V+68
j com.jme3.renderer.RenderManager.renderViewPortQueues(Lcom/jme3/renderer/ViewPort;Z)V+22
j com.jme3.post.filters.BloomFilter.postQueue(Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/ViewPort;)V+62
j com.jme3.post.FilterPostProcessor.postQueue(Lcom/jme3/renderer/queue/RenderQueue;)V+39
j com.jme3.renderer.RenderManager.renderViewPort(Lcom/jme3/renderer/ViewPort;F)V+250
j com.jme3.renderer.RenderManager.render(F)V+83
j com.jme3.app.SimpleApplication.update()V+175
j com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop()V+22
j com.jme3.system.lwjgl.LwjglDisplay.runLoop()V+69
j com.jme3.system.lwjgl.LwjglAbstractDisplay.run()V+117
j java.lang.Thread.run()V+11
v ~StubRoutines::call_stub

P R O C E S S

Java Threads: ( => current thread )
0x0000000006b80000 JavaThread "Keep-Alive-Timer" daemon [_thread_blocked, id=3444, stack(0x000000000bb10000,0x000000000bc10000)]
0x000000000722c800 JavaThread "SectorHandler" [_thread_blocked, id=2036, stack(0x000000000ab10000,0x000000000ac10000)]
0x000000000722b800 JavaThread "Thread-4" [_thread_blocked, id=1784, stack(0x000000000aa10000,0x000000000ab10000)]
0x000000000620c800 JavaThread "FleetHandler" [_thread_blocked, id=4560, stack(0x000000000a910000,0x000000000aa10000)]
0x000000000722b000 JavaThread "Thread-3" [_thread_blocked, id=5088, stack(0x000000000a810000,0x000000000a910000)]
0x0000000007228000 JavaThread "ActionHandler" [_thread_blocked, id=4240, stack(0x000000000a710000,0x000000000a810000)]
0x0000000006f58800 JavaThread "Thread-2" [_thread_blocked, id=4616, stack(0x000000000a610000,0x000000000a710000)]
0x0000000007036800 JavaThread "Java2D Disposer" daemon [_thread_blocked, id=4100, stack(0x000000000a510000,0x000000000a610000)]
0x00000000070bf800 JavaThread "jME3 Audio Thread" daemon [_thread_blocked, id=4364, stack(0x0000000008dd0000,0x0000000008ed0000)]
0x00000000003ee000 JavaThread "DestroyJavaVM" [_thread_blocked, id=4668, stack(0x00000000023a0000,0x00000000024a0000)]
=>0x0000000006152800 JavaThread "LWJGL Renderer Thread" [_thread_in_native, id=2476, stack(0x0000000007470000,0x0000000007570000)]
0x00000000060cf800 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=984, stack(0x0000000006670000,0x0000000006770000)]
0x00000000060c2000 JavaThread "C2 CompilerThread1" daemon [_thread_blocked, id=1136, stack(0x0000000006570000,0x0000000006670000)]
0x00000000003d9000 JavaThread "C2 CompilerThread0" daemon [_thread_blocked, id=5104, stack(0x0000000006470000,0x0000000006570000)]
0x00000000003d7800 JavaThread "Attach Listener" daemon [_thread_blocked, id=3148, stack(0x0000000006370000,0x0000000006470000)]
0x00000000003d6800 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=4324, stack(0x0000000006270000,0x0000000006370000)]
0x00000000003c4000 JavaThread "Finalizer" daemon [_thread_blocked, id=2456, stack(0x0000000005f70000,0x0000000006070000)]
0x00000000003ba800 JavaThread "Reference Handler" daemon [_thread_blocked, id=3660, stack(0x0000000005e70000,0x0000000005f70000)]

Other Threads:
0x00000000003b4000 VMThread [stack: 0x0000000005d70000,0x0000000005e70000] [id=5036]
0x00000000060f0800 WatcherThread [stack: 0x0000000006770000,0x0000000006870000] [id=2488]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
PSYoungGen total 152768K, used 115165K [0x00000000f1560000, 0x00000000ff000000, 0x0000000100000000)
eden space 152704K, 75% used [0x00000000f1560000,0x00000000f85cf6d8,0x00000000faa80000)
from space 64K, 50% used [0x00000000feff0000,0x00000000feff8000,0x00000000ff000000)
to space 8064K, 0% used [0x00000000fe040000,0x00000000fe040000,0x00000000fe820000)
PSOldGen total 30016K, used 21408K [0x00000000d4000000, 0x00000000d5d50000, 0x00000000f1560000)
object space 30016K, 71% used [0x00000000d4000000,0x00000000d54e8120,0x00000000d5d50000)
PSPermGen total 21248K, used 15676K [0x00000000cee00000, 0x00000000d02c0000, 0x00000000d4000000)
object space 21248K, 73% used [0x00000000cee00000,0x00000000cfd4f0f8,0x00000000d02c0000)

Code Cache [0x00000000024d0000, 0x0000000002770000, 0x00000000054d0000)
total_blobs=1203 nmethods=762 adapters=393 free_code_cache=47702720 largest_free_block=12992

Dynamic libraries:
0x0000000000400000 - 0x000000000042e000 C:Program FilesJavajdk1.6.0_25binjavaw.exe
0x0000000077550000 - 0x00000000776fb000 C:WindowsSYSTEM32ntdll.dll
0x0000000077430000 - 0x000000007754f000 C:Windowssystem32kernel32.dll
0x000007fefd810000 - 0x000007fefd87b000 C:Windowssystem32KERNELBASE.dll
0x000007fefdd70000 - 0x000007fefde4b000 C:Windowssystem32ADVAPI32.dll
0x000007feff2c0000 - 0x000007feff35f000 C:Windowssystem32msvcrt.dll
0x000007fefdab0000 - 0x000007fefdacf000 C:WindowsSYSTEM32sechost.dll
0x000007feff360000 - 0x000007feff48e000 C:Windowssystem32RPCRT4.dll
0x0000000077330000 - 0x000000007742a000 C:Windowssystem32USER32.dll
0x000007fefdf00000 - 0x000007fefdf67000 C:Windowssystem32GDI32.dll
0x000007feff490000 - 0x000007feff49e000 C:Windowssystem32LPK.dll
0x000007fefdbb0000 - 0x000007fefdc7a000 C:Windowssystem32USP10.dll
0x000007feff1f0000 - 0x000007feff21e000 C:Windowssystem32IMM32.DLL
0x000007fefe0f0000 - 0x000007fefe1f9000 C:Windowssystem32MSCTF.dll
0x0000000180000000 - 0x00000001800f4000 c:progra~1agnitumoutpos~1wl_hoo~1.dll
0x000007fefe460000 - 0x000007feff1e6000 C:Windowssystem32SHELL32.dll
0x000007feff220000 - 0x000007feff291000 C:Windowssystem32SHLWAPI.dll
0x000000006d890000 - 0x000000006e048000 C:Program FilesJavajdk1.6.0_25jrebinserverjvm.dll
0x000007fefaa80000 - 0x000007fefaabb000 C:Windowssystem32WINMM.dll
0x000000006d800000 - 0x000000006d80e000 C:Program FilesJavajdk1.6.0_25jrebinverify.dll
0x000000006d450000 - 0x000000006d477000 C:Program FilesJavajdk1.6.0_25jrebinjava.dll
0x0000000077720000 - 0x0000000077727000 C:Windowssystem32PSAPI.DLL
0x000000006d850000 - 0x000000006d862000 C:Program FilesJavajdk1.6.0_25jrebinzip.dll
0x0000000007570000 - 0x00000000075c0000 C:workspacegenesis2lwjgl64.dll
0x000007fef8920000 - 0x000007fef8a3d000 C:Windowssystem32OPENGL32.dll
0x000007fefa0f0000 - 0x000007fefa11d000 C:Windowssystem32GLU32.dll
0x000007fef9370000 - 0x000007fef9461000 C:Windowssystem32DDRAW.dll
0x000007fefb5c0000 - 0x000007fefb5c8000 C:Windowssystem32DCIMAN32.dll
0x000007fefd8d0000 - 0x000007fefdaa7000 C:Windowssystem32SETUPAPI.dll
0x000007fefd770000 - 0x000007fefd7a6000 C:Windowssystem32CFGMGR32.dll
0x000007fefdad0000 - 0x000007fefdba7000 C:Windowssystem32OLEAUT32.dll
0x000007feff650000 - 0x000007feff851000 C:Windowssystem32ole32.dll
0x000007fefd7b0000 - 0x000007fefd7ca000 C:Windowssystem32DEVOBJ.dll
0x000007fefb580000 - 0x000007fefb598000 C:Windowssystem32dwmapi.dll
0x000007fefc430000 - 0x000007fefc43c000 C:Windowssystem32VERSION.dll
0x000007fefbda0000 - 0x000007fefbf94000 C:WindowsWinSxSamd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7600.16385_none_fa645303170382f6COMCTL32.dll
0x000007fefba60000 - 0x000007fefbab6000 C:Windowssystem32uxtheme.dll
0x0000000010000000 - 0x0000000010024000 C:Program Files (x86)4t Tray MinimizerShellEh519.x64
0x000007fefb500000 - 0x000007fefb508000 C:Windowssystem32atig6pxx.dll
0x0000000069030000 - 0x000000006a25d000 C:Windowssystem32atio6axx.dll
0x000007fefb4f0000 - 0x000007fefb4f9000 C:Windowssystem32atig6txx.dll
0x00000000077d0000 - 0x0000000007825000 C:Windowssystem32atiadlxx.dll
0x000007fefd7d0000 - 0x000007fefd80a000 C:Windowssystem32WINTRUST.dll
0x000007fefd600000 - 0x000007fefd766000 C:Windowssystem32CRYPT32.dll
0x000007fefd550000 - 0x000007fefd55f000 C:Windowssystem32MSASN1.dll
0x000007fefd3a0000 - 0x000007fefd3af000 C:Windowssystem32CRYPTBASE.dll
0x000007feec3f0000 - 0x000007feec48c000 C:Windowssystem32mscms.dll
0x000007fefc800000 - 0x000007fefc81e000 C:Windowssystem32USERENV.dll
0x000007fefd4b0000 - 0x000007fefd4bf000 C:Windowssystem32profapi.dll
0x000007fef9570000 - 0x000007fef95b2000 C:Windowssystem32icm32.dll
0x000007fefb530000 - 0x000007fefb539000 C:Program FilesSynergysynrgyhk.DLL
0x0000000073340000 - 0x00000000733dd000 C:WindowsWinSxSamd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.4926_none_08e1a05ba83fe554MSVCR90.dll
0x000000006d0a0000 - 0x000000006d263000 C:Program FilesJavajdk1.6.0_25jrebinawt.dll
0x000007fef8430000 - 0x000007fef84a0000 C:Windowssystem32WINSPOOL.DRV
0x0000000007a30000 - 0x0000000007a83000 C:workspacegenesis2OpenAL64.dll
0x000007fef92e0000 - 0x000007fef9368000 C:Windowssystem32dsound.dll
0x000007fefbc70000 - 0x000007fefbc9c000 C:Windowssystem32POWRPROF.dll
0x000007fefdcd0000 - 0x000007fefdd69000 C:Windowssystem32CLBCatQ.DLL
0x000007fefbbf0000 - 0x000007fefbc3b000 C:WindowsSystem32MMDevApi.dll
0x000007fefbac0000 - 0x000007fefbbec000 C:WindowsSystem32PROPSYS.dll
0x000007fefb3e0000 - 0x000007fefb42f000 C:Windowssystem32AUDIOSES.DLL
0x000007fefbc40000 - 0x000007fefbc49000 C:Windowssystem32avrt.dll
0x000000006d6a0000 - 0x000000006d6b7000 C:Program FilesJavajdk1.6.0_25jrebinnet.dll
0x000007fefdc80000 - 0x000007fefdccd000 C:Windowssystem32WS2_32.dll
0x000007fefdef0000 - 0x000007fefdef8000 C:Windowssystem32NSI.dll
0x000007fefcce0000 - 0x000007fefcd34000 C:Windowssystem32mswsock.dll
0x000007fefccd0000 - 0x000007fefccd7000 C:WindowsSystem32wship6.dll
0x000007fefc500000 - 0x000007fefc507000 C:WindowsSystem32wshtcpip.dll
0x000007fefcb60000 - 0x000007fefcbbb000 C:Windowssystem32DNSAPI.dll
0x0000000072fe0000 - 0x000000007300e000 C:Program FilesCommon FilesMicrosoft SharedWindows LiveWLIDNSP.DLL
0x000007fefaf20000 - 0x000007fefaf47000 C:Windowssystem32IPHLPAPI.DLL
0x000007fefaee0000 - 0x000007fefaeeb000 C:Windowssystem32WINNSI.DLL
0x000007fef8c30000 - 0x000007fef8c38000 C:Windowssystem32rasadhlp.dll
0x000007fefae00000 - 0x000007fefae53000 C:WindowsSystem32fwpuclnt.dll

VM Arguments:
jvm_args: -Djava.library.path=D:workspacegenesiswebwebstartjogl-natives-windows-i586 -Dfile.encoding=Cp1252
java_command: de.genesis.Genesis3D
Launcher Type: SUN_STANDARD

Environment Variables:
JAVA_HOME=C:Program FilesJavajdk1.6.0_25
CLASSPATH=.;C:Program Files (x86)Javajre6libextQTJava.zip
PATH=C:/Program Files/Java/jdk1.6.0_25/bin/../jre/bin/server;C:/Program Files/Java/jdk1.6.0_25/bin/../jre/bin;C:/Program Files/Java/jdk1.6.0_25/bin/../jre/lib/amd64;C:Program FilesSlikSvnbin;C:Program Files (x86)AMD APPbinx86_64;C:Program Files (x86)AMD APPbinx86;C:Program FilesJavajdk1.6.0_25bin;C:Program FilesCommon FilesMicrosoft SharedWindows Live;C:Windowssystem32;C:Windows;C:WindowsSystem32Wbem;C:WindowsSystem32WindowsPowerShellv1.0;C:Program Files (x86)ATI TechnologiesATI.ACECore-Static;C:Program Files (x86)Common FilesRoxio SharedDLLShared;C:Program Files (x86)Common FilesRoxio SharedDLLShared;C:Program Files (x86)Common FilesRoxio Shared12.0DLLShared;C:Program Files (x86)Common FilesGTK2.0bin;C:Program Files (x86)QuickTimeQTSystem;C:Program Files (x86)Microsoft SQL Server90Toolsbinn;C:Program FilesSlikSvnbin;C:Program Fileseclipse;
USERNAME=Owner
OS=Windows_NT
PROCESSOR_IDENTIFIER=AMD64 Family 16 Model 6 Stepping 3, AuthenticAMD



S Y S T E M

OS: Windows 7 Build 7600

CPU:total 2 (2 cores per cpu, 1 threads per core) family 16 model 6 stepping 3, cmov, cx8, fxsr, mmx, sse, sse2, sse3, popcnt, mmxext, 3dnow, 3dnowext, lzcnt

Memory: 4k page, physical 2878364k(191552k free), swap 5754828k(2256772k free)

vm_info: Java HotSpot(TM) 64-Bit Server VM (20.0-b11) for windows-amd64 JRE (1.6.0_25-b06), built on Apr 14 2011 00:44:38 by "java_re" with MS VC++ 8.0 (VS2005)

time: Thu Jul 28 12:25:38 2011
elapsed time: 19 seconds

I’d say you created bogus mesh data.

OK, that is unlikely … it works with smaller planet sizes …



Here a testcase to reproduce it.

With this line it works:

[java]initSurface(500, 0, 50);[/java]

With this (or higher values) it crashes:

[java]initSurface(800, 0, 50);[/java]

I haven’t tested for the exact value, but somewhere between those two there is a wall of fire blowing all to pieces …



CrashTestDummy.java

[java]

import java.util.Random;



import com.jme3.app.SimpleApplication;

import com.jme3.light.AmbientLight;

import com.jme3.light.DirectionalLight;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Mesh.Mode;



public class CrashTestDummy extends SimpleApplication {



public static void main(String[] args) {

new CrashTestDummy().start();

}



@Override

public void simpleInitApp() {

cam.setLocation(new Vector3f(0, 20, 0));

cam.lookAt(new Vector3f(20, 0, 20), Vector3f.UNIT_Y);

flyCam.setMoveSpeed(50);



initSurface(500, 0, 50);

rootNode.attachChild(createSurface());



AmbientLight ambient = new AmbientLight();

ambient.setColor(new ColorRGBA(0.1f, 0.1f, 0.1f, 1f));

rootNode.addLight(ambient);



DirectionalLight sun = new DirectionalLight();

sun.setColor(ColorRGBA.White);

sun.setDirection(new Vector3f(10, -10, 10).normalizeLocal());

rootNode.addLight(sun);

}



private Spatial createSurface() {

int numTriangles = (surface.length - 1) * (surface.length - 1) * 2;

CustomMesh mesh = new CustomMesh(numTriangles * 3);

mesh.setMode(Mode.Triangles);

mesh.setNormal(0, 1, 0);



for (int x = 0; x < surface.length - 1; x++) {

for (int y = 0; y < surface.length - 1; y++) {

int oben = surface[x][y];

int rechts = surface[x + 1][y];

int unten = surface[x + 1][y + 1];

int links = surface[x][y + 1];

if (oben == rechts && unten == links || oben == links && unten == rechts) {

drawTriangle(mesh, to3D(x, y + 1), to3D(x + 1, y), to3D(x, y)); // oben

drawTriangle(mesh, to3D(x + 1, y), to3D(x, y + 1), to3D(x + 1, y + 1)); // unten

} else {

boolean horizontal = true;

if (oben == unten && ((rechts <= oben && links >= oben) || (rechts >= oben && links <= oben))) horizontal = false;

// if (oben == unten && ((rechts < oben && links >oben) || (rechts > oben && links <=oben))) horizontal = false;

if (oben == unten && rechts == links && oben != rechts) {

if (oben < rechts) { // Mitte unten, Rand oben /

int hRechts2 = surface[wrap(x + 2, surface.length)][wrap(y - 1, surface.length)]; // ein Feld weiter nach rechts …

int hLinks2 = surface[wrap(x - 1, surface.length)][wrap(y + 2, surface.length)]; // ein Feld weiter nach links …

horizontal = hRechts2 <= rechts && links >= hLinks2 || hRechts2 < rechts && links < hLinks2 || hRechts2 > rechts && links > hLinks2;

} else { // Mitte oben, Rand unten /

int hOben2 = surface[wrap(x - 1, surface.length)][wrap(y - 1, surface.length)]; // ein Feld weiter nach oben …

int hUnten2 = surface[wrap(x + 2, surface.length)][wrap(y + 2, surface.length)]; // ein Feld weiter nach unten …

horizontal = !(hOben2 <= oben && unten >= hUnten2 || hOben2 < oben && unten < hUnten2 || hOben2 > oben && unten > hUnten2);

}

}

if (horizontal) {

drawTriangle(mesh, to3D(x, y + 1), to3D(x + 1, y), to3D(x, y)); // oben

drawTriangle(mesh, to3D(x + 1, y), to3D(x, y + 1), to3D(x + 1, y + 1)); // unten

} else {

drawTriangle(mesh, to3D(x, y), to3D(x + 1, y + 1), to3D(x + 1, y)); // rechts

drawTriangle(mesh, to3D(x + 1, y + 1), to3D(x, y), to3D(x, y + 1)); // links

}

}

}

}

mesh.finish();



Geometry geo = new Geometry(“PlanetSurface”, mesh);

Material mat = new Material(assetManager, “Common/MatDefs/Light/Lighting.j3md”);

mat.setFloat(“Shininess”, 25f);

mat.setBoolean(“VertexLighting”, true);

mat.setBoolean(“UseVertexColor”, true);

mat.setColor(“Diffuse”, ColorRGBA.White);

mat.setColor(“Specular”, ColorRGBA.White);

mat.setColor(“Ambient”, ColorRGBA.White);

mat.getAdditionalRenderState().setPolyOffset(1, 1);

geo.setMaterial(mat);

return geo;

}



private void drawTriangle(CustomMesh mesh, Vector3f p1, Vector3f p2, Vector3f p3) {

mesh.addVertex(p1, getColor((int) p1.x, (int) p1.z));

mesh.addVertex(p2, getColor((int) p2.x, (int) p2.z));

mesh.addVertex(p3, getColor((int) p3.x, (int) p3.z));

}



private int wrap(int coord, int max) {

while (coord > max - 2) { // letzte Reihe == erste Reihe …

coord -= max - 1;

}

while (coord < 0) {

coord += max - 1;

}

return coord;

}



private Vector3f to3D(int x, int y) {

return new Vector3f(x, surface[x][y] / 1.4f, y);

}



private ColorRGBA getColor(int x, int y) {

int height = surface[x][y];

switch (height) {

case -1:

return new ColorRGBA(0f, 0f, 1.0f, 1f);

case 0:

return new ColorRGBA(0f, 0.4f, 0f, 1f);

case 1:

return new ColorRGBA(0.4f, 0.3f, 0f, 1f);

case 2:

return new ColorRGBA(0.5f, 0.4f, 0f, 1f);

case 3:

return new ColorRGBA(0.6f, 0.6f, 0.6f, 1f);

case 4:

return new ColorRGBA(0.8f, 0.8f, 0.8f, 1f);

}

return new ColorRGBA(0.4f, 0.4f, 0.4f, 1f); // Grau

}



public int[][] surface;



public void initSurface(int planetSize, long seed, int gebirge) {

surface = new int[planetSize][planetSize];

Random rnd = new Random(seed);



int repeats = planetSize * planetSize / 100 + planetSize;

repeats = gebirge / 25.0;



for (int i = 0; i < repeats; i++) {

int fieldsize = rnd.nextInt(5);

int xStart = rnd.nextInt(planetSize - fieldsize);

int yStart = rnd.nextInt(planetSize - fieldsize);

int height = rnd.nextInt(7) - 2; // -2 bis +4

if (height == 0) height = rnd.nextInt(7) - 2; // -2 bis +4



for (int x = xStart; x < xStart + fieldsize; x++) {

for (int y = yStart; y < yStart + fieldsize; y++) {

setHeight(surface, x, y, height);

}

}

}



for (int x = 0; x < planetSize; x++) {

for (int y = 0; y < planetSize; y++) {

if (surface[x][y] < -1) surface[x][y] = -1; // -1 = Meeresspiegel …

}

}

}



private void setHeight(int[][] surface, int x, int y, int height) {

if (surface[x][y] == height) return; // nix zu tun … verhindert unnötige Rekursion …

surface[x][y] = height;

if ((x == 0 || x == surface.length - 1) && (y == 0 || y == surface.length - 1)) { // alle 4 Ecken durchgehen und setzen …

setHeight(surface, 0, 0, height);

setHeight(surface, surface.length - 1, 0, height);

setHeight(surface, surface.length - 1, surface.length - 1, height);

setHeight(surface, 0, surface.length - 1, height);

} else if (x == 0) {

setHeight(surface, surface.length - 1, y, height); // jeweils die gegenüberliegende Position setzen …

} else if (x == surface.length - 1) {

setHeight(surface, 0, y, height);

} else if (y == 0) {

setHeight(surface, x, surface.length - 1, height);

} else if (y == surface.length - 1) {

setHeight(surface, x, 0, height);

}



for (int cx = x - 1; cx <= x + 1; cx++) {

for (int cy = y - 1; cy <= y + 1; cy++) {

if (cx != x || cy != y) {

if (cx >= 0 && cx < surface.length) {

if (cy >= 0 && cy < surface.length) { // Kanten egal …

int diff = Math.abs(cx - x) + Math.abs(cy - y);

if (surface[cx][cy] < height - diff) {

setHeight(surface, cx, cy, height - diff);

} else if (surface[cx][cy] > height + diff) {

setHeight(surface, cx, cy, height + diff);

}

}

}

}

}

}

surface[x][y] = height;

}



}

[/java]



CustomMesh.java

[java]

import java.nio.
;

import java.util.*;

import java.util.Map.Entry;



import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.util.BufferUtils;



/**

  • This helper class simplifies the creation of custom meshes. It is built so you can add vertex by vertex.<br>
  • It dynamically initializes the needed buffers and manages them automatically when adding and setting the first vertex.<br>
  • By adding a second vertex and not specifying the values for all buffers the values from the previous vertex will be copied automatically.<br>
  • When done adding vertexes and before you can use the mesh you need to call the method {@link #finish()}.

    *
  • @author Finomosec

    */

    public class CustomMesh extends Mesh {



    private final int initialSize;

    private final int increaseBy = 50;



    private int index = 0;



    /**
  • Dynamically managed buffers

    */

    private Map<Type, Buffer> buffers = new HashMap<Type, Buffer>();



    /**
  • Here we store the values set by the set methods for use in {@link #addVertex()}.
  • That way we preserve the prior value and thus can reuse it when the individual value is not changed.
  • Example: We want 9 vertexes in blue. Call {@link #setColor(ColorRGBA)} with blue.
  • Call {@link #addVertex(Vector3f)} 9 times with the wanted vertexes.

    */

    private Map<Type, Object> values = new HashMap<Type, Object>();



    /**
  • @param initialSize
  •        number of Vertexes expected (will increase automatically if needed, but with loss of performance)<br />
    

*/

public CustomMesh(int initialSize) {

this.initialSize = initialSize;

}



private Buffer getBufferFor(Type type) {

Buffer buffer = buffers.get(type);

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (buffer == null) {

buffer = typeMeta.createBuffer(initialSize);

buffers.put(type, buffer);

} else if (buffer.remaining() < typeMeta.getNumValues()) {

if (buffer instanceof FloatBuffer) {

buffer = BufferUtils.ensureLargeEnough((FloatBuffer) buffer, typeMeta.getNumValues() * increaseBy);

} else if (buffer instanceof IntBuffer) {

buffer = ensureLargeEnough((IntBuffer) buffer, typeMeta.getNumValues() * increaseBy);

} else if (buffer instanceof ShortBuffer) {

buffer = BufferUtils.ensureLargeEnough((ShortBuffer) buffer, typeMeta.getNumValues() * increaseBy);

} else if (buffer instanceof FloatBuffer) {

buffer = BufferUtils.ensureLargeEnough((FloatBuffer) buffer, typeMeta.getNumValues() * increaseBy);

}

buffers.put(type, buffer);

}

return buffer;

}



/**

  • Ensures there is at least the <code>required</code> number of entries left after the current galaxyPosition of the
  • buffer. If the buffer is too small a larger one is created and the old one copied to the new buffer.

    *
  • @param buffer
  •        buffer that should be checked/copied (may be null)<br />
    
  • @param required
  •        minimum number of elements that should be remaining in the returned buffer<br />
    
  • @return a buffer large enough to receive at least the <code>required</code> number of entries, same galaxyPosition as
  •     the input buffer, not null<br />
    

*/

public static IntBuffer ensureLargeEnough(IntBuffer buffer, int required) { // Did not exist in BufferUtils so i had to copy & modify it TODO: Add/move to BufferUtils

if (buffer == null || (buffer.remaining() < required)) {

int position = (buffer != null ? buffer.position() : 0);

IntBuffer newVerts = BufferUtils.createIntBuffer(position + required);

if (buffer != null) {

buffer.rewind();

newVerts.put(buffer);

newVerts.position(position);

}

buffer = newVerts;

}

return buffer;

}



public void addVertex() {

((IntBuffer) getBufferFor(Type.Index)).put(index++);

for (Entry<Type, Object> valueEntry : values.entrySet()) {

Buffer buffer = getBufferFor(valueEntry.getKey());

if (buffer instanceof FloatBuffer) {

((FloatBuffer) buffer).put((float[]) valueEntry.getValue());

} else if (buffer instanceof IntBuffer) {

((IntBuffer) buffer).put((int[]) valueEntry.getValue());

} else if (buffer instanceof ShortBuffer) {

((ShortBuffer) buffer).put((short[]) valueEntry.getValue());

} else if (buffer instanceof ByteBuffer) {

((ByteBuffer) buffer).put((byte[]) valueEntry.getValue());

}

}

}



public void addVertex(Vector3f position) {

setPosition(position);

addVertex();

}



public void addVertex(float x, float y, float z) {

setPosition(x, y, z);

addVertex();

}



public void addVertex(Vector3f position, ColorRGBA color) {

setPosition(position);

setColor(color);

addVertex();

}



public void addVertex(Vector3f position, ColorRGBA color, Vector3f normal) {

setPosition(position);

setColor(color);

setNormal(normal);

addVertex();

}



public void setPosition(Vector3f vector) {

setFloatValue(Type.Position, vector.x, vector.y, vector.z);

}



public void setPosition(float x, float y, float z) {

setFloatValue(Type.Position, x, y, z);

}



public void setColor(ColorRGBA color) {

setFloatValue(Type.Color, color.r, color.g, color.b, color.a);

}



public void setColor(float r, float g, float b, float a) {

setFloatValue(Type.Color, r, g, b, a);

}



public void setNormal(Vector3f vector) {

setFloatValue(Type.Normal, vector.x, vector.y, vector.z);

}



public void setNormal(float x, float y, float z) {

setFloatValue(Type.Normal, x, y, z);

}



public void setFloatValue(Type type, float… value) {

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (typeMeta.getBufferType() != FloatBuffer.class) throw new IllegalArgumentException(“This buffer does not take ‘float’ values!”);

if (typeMeta.getNumValues() != value.length) throw new IllegalArgumentException(“This buffer needs " + typeMeta.getNumValues() + " values!”);

values.put(type, value);

}



public void setShortValue(Type type, short… value) {

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (typeMeta.getBufferType() != ShortBuffer.class) throw new IllegalArgumentException(“This buffer does not take ‘short’ values!”);

if (typeMeta.getNumValues() != value.length) throw new IllegalArgumentException(“This buffer needs " + typeMeta.getNumValues() + " values!”);

values.put(type, value);

}



public void setIntValue(Type type, int… value) {

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (typeMeta.getBufferType() != IntBuffer.class) throw new IllegalArgumentException(“This buffer does not take ‘int’ values!”);

if (typeMeta.getNumValues() != value.length) throw new IllegalArgumentException(“This buffer needs " + typeMeta.getNumValues() + " values!”);

values.put(type, value);

}



public void setByteValue(Type type, byte… value) {

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (typeMeta.getBufferType() != ByteBuffer.class) throw new IllegalArgumentException(“This buffer does not take ‘byte’ values!”);

if (typeMeta.getNumValues() != value.length) throw new IllegalArgumentException(“This buffer needs " + typeMeta.getNumValues() + " values!”);

values.put(type, value);

}



public void finish() {

for (Entry<Type, Buffer> bufferEntry : buffers.entrySet()) {

Type type = bufferEntry.getKey();

Buffer buffer = bufferEntry.getValue();

buffer.flip();

TypeMeta typeMeta = TypeMeta.getTypeMeta(type);

if (buffer instanceof FloatBuffer) {

setBuffer(type, typeMeta.getNumValues(), (FloatBuffer) buffer);

} else if (buffer instanceof IntBuffer) {

setBuffer(type, typeMeta.getNumValues(), (IntBuffer) buffer);

} else if (buffer instanceof ShortBuffer) {

setBuffer(type, typeMeta.getNumValues(), (ShortBuffer) buffer);

} else if (buffer instanceof ByteBuffer) {

setBuffer(type, typeMeta.getNumValues(), (ByteBuffer) buffer);

}

}

updateBound();

updateCounts();

}



/**

  • This helper class specifies the meta data needed to create the respective buffers automatically.<br>
  • This whole functionality COULD be integrated into the {@link Type} class to reduce unnecessary overhead!

    *
  • @author Finomosec

    *

    */

    private static class TypeMeta {



    private static Map<Type, TypeMeta> mapping;



    public static TypeMeta getTypeMeta(Type type) {

    if (mapping == null) {

    mapping = new HashMap<Type, TypeMeta>();

    mapping.put(Type.Index, new TypeMeta(1, IntBuffer.class));

    mapping.put(Type.Position, new TypeMeta(3, FloatBuffer.class));

    mapping.put(Type.Normal, new TypeMeta(3, FloatBuffer.class));

    mapping.put(Type.Size, new TypeMeta(1, FloatBuffer.class));

    mapping.put(Type.Color, new TypeMeta(4, FloatBuffer.class));

    // TODO: Complete with other Types! OR Alternatively add this data and functionality in the Type Enum!!

    }

    return mapping.get(type);

    }



    private int numValues;

    private Class<? extends Buffer> bufferType;



    private TypeMeta(int numValues, Class<? extends Buffer> bufferType) {

    this.numValues = numValues;

    this.bufferType = bufferType;

    }



    public int getNumValues() {

    return numValues;

    }



    public Class<? extends Buffer> getBufferType() {

    return bufferType;

    }



    public Buffer createBuffer(int initialSize) {

    Buffer buffer = null;

    if (getBufferType() == FloatBuffer.class) buffer = BufferUtils.createFloatBuffer(initialSize * numValues);

    else if (getBufferType() == IntBuffer.class) buffer = BufferUtils.createIntBuffer(initialSize * numValues);

    else if (getBufferType() == ShortBuffer.class) buffer = BufferUtils.createShortBuffer(initialSize * numValues);

    else if (getBufferType() == ByteBuffer.class) buffer = BufferUtils.createByteBuffer(initialSize * numValues);

    return buffer;

    }



    }



    }

    [/java]



    p.s. can you add this CustomMesh to JME3 please???



    Greetings Fino

Afaik this mesh crashes for sizes >500, so you better test this better before we add it to jme3 :wink: The CustomMesh itself you posted in the contribution repo afaik, so we’ll come around to test and add it some time I guess.

Ehm you got something wrong here!!



The 500 is the planet size!!



The number of Triangles is 5005002 = 500,000 and the number of vertexes is then 50050023 = .1,500,000.



With 800 it fails: 800
80023 = 3,840,000 vertexes.



I can guarantee that it is not the CustomMesh that makes the problem.

The CustomMesh merely capsules the logic to handle the Buffers used with your Mesh class.



So look again please.

And run the testcase so you will see for yourself what happens.



Greetings Fino;

Afaik this mesh crashes for sizes >500

Also ... it's not the CustomMesh that crashes, but your render Thread:
[java]=>0×0000000006152800 JavaThread “LWJGL Renderer Thread” [_thread_in_native, id=2476, stack(0x0000000007470000,0x0000000007570000)][/java]
And this is the stack where the problem occurs exactly (all from the first post):

Stack: [0x0000000007470000,0x0000000007570000], sp=0x000000000756e4a0, free space=1017k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [atio6axx.dll+0x5729a] DrvPresentBuffers+0x64ca
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.lwjgl.opengl.GL15.nglBufferData(IJLjava/nio/Buffer;IIJ)V+0
j org.lwjgl.opengl.GL15.glBufferData(ILjava/nio/FloatBuffer;I)V+37
j com.jme3.renderer.lwjgl.LwjglRenderer.updateBufferData(Lcom/jme3/scene/VertexBuffer;)V+266
J com.jme3.renderer.lwjgl.LwjglRenderer.renderMeshDefault(Lcom/jme3/scene/Mesh;II)V
J com.jme3.material.Material.render(Lcom/jme3/scene/Geometry;Lcom/jme3/renderer/RenderManager;)V
J com.jme3.renderer.queue.RenderQueue.renderGeometryList(Lcom/jme3/renderer/queue/GeometryList;Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/Camera;Z)V
j com.jme3.renderer.queue.RenderQueue.renderQueue(Lcom/jme3/renderer/queue/RenderQueue$Bucket;Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/Camera;Z)V+68
j com.jme3.renderer.RenderManager.renderViewPortQueues(Lcom/jme3/renderer/ViewPort;Z)V+22
j com.jme3.post.filters.BloomFilter.postQueue(Lcom/jme3/renderer/RenderManager;Lcom/jme3/renderer/ViewPort;)V+62
j com.jme3.post.FilterPostProcessor.postQueue(Lcom/jme3/renderer/queue/RenderQueue;)V+39
j com.jme3.renderer.RenderManager.renderViewPort(Lcom/jme3/renderer/ViewPort;F)V+250
j com.jme3.renderer.RenderManager.render(F)V+83
j com.jme3.app.SimpleApplication.update()V+175
j com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop()V+22
j com.jme3.system.lwjgl.LwjglDisplay.runLoop()V+69
j com.jme3.system.lwjgl.LwjglAbstractDisplay.run()V+117
j java.lang.Thread.run()V+11
v ~StubRoutines::call_stub

Yes, I was separating between the two classes. I thought you wanted to add this planet stuff too now because you posted the CustomMesh already. Afaik mythruna also uses pretty big meshes and big ogre models don’t fail with jME3, so I am not as convinced as you are that its not your code, no offense. Nevertheless thanks for the input, we’ll check this out.

Actually that crash happened in native code, so this could be very well a driver error as well.