aboutsummaryrefslogtreecommitdiff
path: root/KaplaDemo/samples
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /KaplaDemo/samples
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'KaplaDemo/samples')
-rwxr-xr-xKaplaDemo/samples/compiler/physx64copy.bat69
-rwxr-xr-xKaplaDemo/samples/compiler/physxcopy.bat70
-rw-r--r--KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/GRB_Samples.sln43
-rw-r--r--KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/Px3-SampleViewer.vcxproj726
-rw-r--r--KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/GRB_Samples.sln43
-rw-r--r--KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/Px3-SampleViewer.vcxproj726
-rw-r--r--KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/GRB_Samples.sln43
-rw-r--r--KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/Px3-SampleViewer.vcxproj726
-rw-r--r--KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/GRB_Samples.sln43
-rw-r--r--KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/Px3-SampleViewer.vcxproj726
-rw-r--r--KaplaDemo/samples/sampleViewer3/AABox.cpp469
-rw-r--r--KaplaDemo/samples/sampleViewer3/AABox.h77
-rw-r--r--KaplaDemo/samples/sampleViewer3/BmpFile.cpp184
-rw-r--r--KaplaDemo/samples/sampleViewer3/BmpFile.h21
-rw-r--r--KaplaDemo/samples/sampleViewer3/Crab.cpp820
-rw-r--r--KaplaDemo/samples/sampleViewer3/Crab.h190
-rw-r--r--KaplaDemo/samples/sampleViewer3/CrabManager.cpp159
-rw-r--r--KaplaDemo/samples/sampleViewer3/CrabManager.h126
-rw-r--r--KaplaDemo/samples/sampleViewer3/FXAAHelper.cpp148
-rw-r--r--KaplaDemo/samples/sampleViewer3/FXAAHelper.h15
-rw-r--r--KaplaDemo/samples/sampleViewer3/FileScanner.cpp236
-rw-r--r--KaplaDemo/samples/sampleViewer3/FileScanner.h64
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Actor.cpp21
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Actor.h25
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Compound.cpp161
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Compound.h59
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.cpp38
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.h23
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.cpp75
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.h18
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Convex.cpp553
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Convex.h39
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.cpp376
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.h77
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.cpp139
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.h54
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.cpp536
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.h136
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.cpp844
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.h103
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.cpp86
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.h68
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.cpp1316
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.h213
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.cpp212
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.h67
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.cpp272
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.h59
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.cpp337
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.h248
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Mesh.cpp165
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/Mesh.h32
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.cpp4
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.h22
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/RTdef.h8
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/SimScene.cpp778
-rw-r--r--KaplaDemo/samples/sampleViewer3/Fracture/SimScene.h80
-rw-r--r--KaplaDemo/samples/sampleViewer3/FrameBufferObject.cpp405
-rw-r--r--KaplaDemo/samples/sampleViewer3/FrameBufferObject.h210
-rw-r--r--KaplaDemo/samples/sampleViewer3/GLFontData.h1047
-rw-r--r--KaplaDemo/samples/sampleViewer3/GLFontRenderer.cpp334
-rw-r--r--KaplaDemo/samples/sampleViewer3/GLFontRenderer.h73
-rw-r--r--KaplaDemo/samples/sampleViewer3/HBAOHelper.cpp289
-rw-r--r--KaplaDemo/samples/sampleViewer3/HBAOHelper.h33
-rw-r--r--KaplaDemo/samples/sampleViewer3/HDRHelper.cpp356
-rw-r--r--KaplaDemo/samples/sampleViewer3/HDRHelper.h37
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.cpp94
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.h32
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/ReadMe.txt29
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/ansi2knr.cpp681
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/cderror.h132
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.cpp182
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.h184
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/cjpeg.cpp630
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/ckconfig.cpp403
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/djpeg.cpp616
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcapimin.cpp282
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcapistd.cpp163
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jccoefct.cpp456
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jccolor.cpp460
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcdctmgr.cpp391
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.cpp410
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.h1
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.cpp274
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.h54
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcinit.cpp58
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jclhuff.cpp600
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jclossls.cpp79
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jclossy.cpp77
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcmainct.cpp297
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcmarker.cpp672
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcmaster.cpp648
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.cpp53
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.h2
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcomapi.cpp107
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jconfig.h47
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcparam.cpp688
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcphuff.cpp849
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcpred.cpp298
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcprepct.cpp355
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcsample.cpp520
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcscale.cpp63
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jcshuff.cpp662
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jctrans.cpp421
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdapimin.cpp402
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdapistd.cpp276
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdatadst.cpp152
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdatasrc.cpp213
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdcoefct.cpp744
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdcolor.cpp397
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdct.h176
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jddctmgr.cpp271
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.cpp399
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.h1
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.cpp316
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.h229
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdinput.cpp348
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdlhuff.cpp291
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossls.cpp95
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossy.cpp229
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdmainct.cpp513
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdmarker.cpp1371
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdmaster.cpp461
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdmerge.cpp401
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdphuff.cpp676
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdpostct.cpp291
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdpred.cpp248
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdsample.cpp479
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdscale.cpp119
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdshuff.cpp361
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jdtrans.cpp139
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.cpp249
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.h304
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctflt.cpp169
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctfst.cpp225
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctint.cpp284
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jidctflt.cpp243
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jidctfst.cpp369
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jidctint.cpp390
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jidctred.cpp399
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jinclude.h91
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jlossls.h152
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jlossy.h120
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jmemdosa.asm379
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jmemmgr.cpp1175
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jmemnobs.cpp110
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jmemsys.h198
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jmorecfg.h403
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jpegint.h355
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jpeglib.h1131
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jquant1.cpp857
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jquant2.cpp1311
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jutils.cpp180
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/jversion.h14
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdbmp.cpp440
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdcolmap.cpp254
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdgif.cpp39
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdppm.cpp461
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdrle.cpp388
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.cpp358
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.h1
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/rdtarga.cpp501
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.cpp8
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.h42
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.cpp930
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.h135
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/wrbmp.cpp443
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/wrgif.cpp400
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/wrppm.cpp269
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/wrrle.cpp306
-rw-r--r--KaplaDemo/samples/sampleViewer3/IJGWin32/wrtarga.cpp253
-rw-r--r--KaplaDemo/samples/sampleViewer3/MathUtils.cpp365
-rw-r--r--KaplaDemo/samples/sampleViewer3/MathUtils.h102
-rw-r--r--KaplaDemo/samples/sampleViewer3/MediaPath.cpp285
-rw-r--r--KaplaDemo/samples/sampleViewer3/MediaPath.h24
-rw-r--r--KaplaDemo/samples/sampleViewer3/PhysXMacros.h13
-rw-r--r--KaplaDemo/samples/sampleViewer3/RawLoader.cpp439
-rw-r--r--KaplaDemo/samples/sampleViewer3/RawLoader.h114
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp342
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h220
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp2878
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/MyShaders.h21
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp271
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/glmesh.h42
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp46
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/newParameters.h42
-rw-r--r--KaplaDemo/samples/sampleViewer3/RenderTarget.cpp80
-rw-r--r--KaplaDemo/samples/sampleViewer3/RenderTarget.h31
-rw-r--r--KaplaDemo/samples/sampleViewer3/SSAOHelper.cpp399
-rw-r--r--KaplaDemo/samples/sampleViewer3/SSAOHelper.h25
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewer.cpp2527
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewer.h21
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.cpp211
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.h69
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewerScene.cpp106
-rw-r--r--KaplaDemo/samples/sampleViewer3/SampleViewerScene.h125
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneCrab.cpp189
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneCrab.h80
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneCrabInputEventIds.h45
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKapla.cpp930
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKapla.h122
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKaplaArena.cpp53
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKaplaArena.h24
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKaplaTower.cpp694
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneKaplaTower.h41
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.cpp106
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.h25
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp1193
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicle.h98
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.cpp214
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.h50
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.cpp100
-rw-r--r--KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.h147
-rw-r--r--KaplaDemo/samples/sampleViewer3/Shader.cpp750
-rw-r--r--KaplaDemo/samples/sampleViewer3/Shader.h146
-rw-r--r--KaplaDemo/samples/sampleViewer3/ShaderShadow.cpp2883
-rw-r--r--KaplaDemo/samples/sampleViewer3/ShaderShadow.h105
-rw-r--r--KaplaDemo/samples/sampleViewer3/ShadowMap.cpp383
-rw-r--r--KaplaDemo/samples/sampleViewer3/ShadowMap.h95
-rw-r--r--KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp367
-rw-r--r--KaplaDemo/samples/sampleViewer3/TerrainMesh.h40
-rw-r--r--KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.cpp92
-rw-r--r--KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.h64
-rw-r--r--KaplaDemo/samples/sampleViewer3/Texture.cpp283
-rw-r--r--KaplaDemo/samples/sampleViewer3/Texture.h13
-rw-r--r--KaplaDemo/samples/sampleViewer3/TgaFile.cpp1212
-rw-r--r--KaplaDemo/samples/sampleViewer3/TgaFile.h230
-rw-r--r--KaplaDemo/samples/sampleViewer3/Timing.cpp36
-rw-r--r--KaplaDemo/samples/sampleViewer3/Timing.h8
-rw-r--r--KaplaDemo/samples/sampleViewer3/Vec/Bounds3.h182
-rw-r--r--KaplaDemo/samples/sampleViewer3/Vec/Plane.h73
-rw-r--r--KaplaDemo/samples/sampleViewer3/Vec/Quat.h301
-rw-r--r--KaplaDemo/samples/sampleViewer3/Vec/Transform.h94
-rw-r--r--KaplaDemo/samples/sampleViewer3/Vec/Vec3.h490
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleCameraController.cpp165
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleCameraController.h93
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleControlInputs.cpp65
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleControlInputs.h145
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleController.cpp808
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleController.h226
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleManager.cpp473
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleManager.h134
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.cpp72
-rw-r--r--KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.h82
-rw-r--r--KaplaDemo/samples/sampleViewer3/XMLParser.cpp198
-rw-r--r--KaplaDemo/samples/sampleViewer3/XMLParser.h60
246 files changed, 74933 insertions, 0 deletions
diff --git a/KaplaDemo/samples/compiler/physx64copy.bat b/KaplaDemo/samples/compiler/physx64copy.bat
new file mode 100755
index 00000000..fe5a3912
--- /dev/null
+++ b/KaplaDemo/samples/compiler/physx64copy.bat
@@ -0,0 +1,69 @@
+SETLOCAL
+
+SET PXFROMDIR=%1
+SET PXTODIR=%2
+SET EXTERNALSFROMDIR=%3
+SET GLUTFROMDIR=%4
+SET CGFROMDIR=%5
+SET PXSHAREDFROMDIR=%6
+SET HBAODIR=%7
+
+CALL :UPDATE_PX_TARGET PhysX3Cooking*_x64.dll
+CALL :UPDATE_PX_TARGET PhysX3*_x64.dll
+CALL :UPDATE_PX_TARGET PhysX3Gpu*_x64.dll
+CALL :UPDATE_PX_TARGET PhysX3Common*_x64.dll
+CALL :UPDATE_PX_TARGET PhysX3CharacterKinematic*_x64.dll
+CALL :UPDATE_PXSHARED_TARGET PxFoundation*_x64.dll
+CALL :UPDATE_PXSHARED_TARGET PxPvdSDK*_x64.dll
+
+rem CALL :UPDATE_PX_TARGET nvToolsExt64_1.dll
+rem CALL :UPDATE_PX_TARGET cudart64_*.dll
+rem CALL :UPDATE_PX_TARGET glut32.dll
+
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cg.dll
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cgGL.dll
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cgD3d9.dll
+
+CALL :UPDATE_TARGET %EXTERNALSFROMDIR%/nvToolsExt/1/bin/x64 %PXTODIR% nvToolsExt64_1.dll
+
+CALL :UPDATE_TARGET %GLUTFROMDIR% %PXTODIR% glut32.dll
+
+CALL :UPDATE_TARGET ../../../bin %PXTODIR% resourcePath.txt
+
+IF "%7"=="" GOTO END
+
+CALL :UPDATE_TARGET %HBAODIR% %PXTODIR% GFSDK_SSAO_GL.win64.dll
+
+ENDLOCAL
+GOTO END
+
+
+REM ********************************************
+REM NO CALLS TO :UPDATE*_TARGET below this line!!
+REM ********************************************
+
+:UPDATE_TARGET
+IF NOT EXIST %1\%3 (
+ rem echo File doesn't exist %1\%3
+) ELSE (
+ XCOPY "%1\%3" "%2" /R /C /Y > nul
+)
+GOTO END
+
+:UPDATE_PX_TARGET
+IF NOT EXIST %PXFROMDIR%\%1 (
+ rem echo File doesn't exist %PXFROMDIR%\%1
+) ELSE (
+ XCOPY "%PXFROMDIR%\%1" "%PXTODIR%" /R /C /Y > nul
+)
+GOTO END
+
+:UPDATE_PXSHARED_TARGET
+IF NOT EXIST %PXSHAREDFROMDIR%\%1 (
+ rem echo File doesn't exist %PXSHAREDFROMDIR%\%8
+) ELSE (
+ XCOPY "%PXSHAREDFROMDIR%\%1" "%PXTODIR%" /R /C /Y > nul
+)
+GOTO END
+
+:END
diff --git a/KaplaDemo/samples/compiler/physxcopy.bat b/KaplaDemo/samples/compiler/physxcopy.bat
new file mode 100755
index 00000000..9843c9e7
--- /dev/null
+++ b/KaplaDemo/samples/compiler/physxcopy.bat
@@ -0,0 +1,70 @@
+SETLOCAL
+
+SET PXFROMDIR=%1
+SET PXTODIR=%2
+SET EXTERNALSFROMDIR=%3
+SET GLUTFROMDIR=%4
+SET CGFROMDIR=%5
+SET PXSHAREDFROMDIR=%6
+SET HBAODIR=%7
+
+CALL :UPDATE_PX_TARGET PhysX3Cooking*_x86.dll
+CALL :UPDATE_PX_TARGET PhysX3*_x86.dll
+CALL :UPDATE_PX_TARGET PhysX3Gpu*_x86.dll
+CALL :UPDATE_PX_TARGET PhysX3Common*_x86.dll
+CALL :UPDATE_PX_TARGET PhysX3CharacterKinematic*_x86.dll
+CALL :UPDATE_PXSHARED_TARGET PxFoundation*_x86.dll
+CALL :UPDATE_PXSHARED_TARGET PxPvdSDK*_x86.dll
+
+rem CALL :UPDATE_PX_TARGET nvToolsExt32_1.dll
+rem CALL :UPDATE_PX_TARGET cudart32_*.dll
+rem CALL :UPDATE_PX_TARGET glut32.dll
+
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cg.dll
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cgGL.dll
+CALL :UPDATE_TARGET %CGFROMDIR% %PXTODIR% cgD3d9.dll
+
+CALL :UPDATE_TARGET %EXTERNALSFROMDIR%/nvToolsExt/1/bin/Win32 %PXTODIR% nvToolsExt32_1.dll
+
+CALL :UPDATE_TARGET %GLUTFROMDIR% %PXTODIR% glut32.dll
+
+CALL :UPDATE_TARGET ../../../bin %PXTODIR% resourcePath.txt
+
+IF "%7"=="" GOTO END
+
+CALL :UPDATE_TARGET %HBAODIR% %PXTODIR% GFSDK_SSAO_GL.win32.dll
+
+ENDLOCAL
+GOTO END
+
+
+REM ********************************************
+REM NO CALLS TO :UPDATE*_TARGET below this line!!
+REM ********************************************
+
+:UPDATE_TARGET
+IF NOT EXIST %1\%3 (
+ rem echo File doesn't exist %1\%3
+) ELSE (
+ XCOPY "%1\%3" "%2" /R /C /Y > nul
+)
+GOTO END
+
+:UPDATE_PX_TARGET
+IF NOT EXIST %PXFROMDIR%\%1 (
+ rem echo File doesn't exist %PXFROMDIR%\%1
+) ELSE (
+ XCOPY "%PXFROMDIR%\%1" "%PXTODIR%" /R /C /Y > nul
+)
+GOTO END
+
+
+:UPDATE_PXSHARED_TARGET
+IF NOT EXIST %PXSHAREDFROMDIR%\%1 (
+ rem echo File doesn't exist %PXSHAREDFROMDIR%\%8
+) ELSE (
+ XCOPY "%PXSHAREDFROMDIR%\%1" "%PXTODIR%" /R /C /Y > nul
+)
+GOTO END
+
+:END
diff --git a/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/GRB_Samples.sln b/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/GRB_Samples.sln
new file mode 100644
index 00000000..456c1541
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/GRB_Samples.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Px3-SampleViewer", "./Px3-SampleViewer.vcxproj", "{FC74E64C-DEA4-2352-C400-6D085370D268}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F} = {7D20139C-09F4-B0C5-B9C9-8E603785931F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew-MT", "./../../../externalIP/glew-1.13.0/compiler/vc11win32/glew-MT.vcxproj", "{7D20139C-09F4-B0C5-B9C9-8E603785931F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ checked|Win32 = checked|Win32
+ debug|Win32 = debug|Win32
+ profile|Win32 = profile|Win32
+ release|Win32 = release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|Win32.ActiveCfg = checked|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|Win32.Build.0 = checked|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|Win32.ActiveCfg = debug|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|Win32.Build.0 = debug|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|Win32.ActiveCfg = profile|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|Win32.Build.0 = profile|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|Win32.ActiveCfg = release|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|Win32.Build.0 = release|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|Win32.ActiveCfg = checked|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|Win32.Build.0 = checked|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|Win32.ActiveCfg = debug|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|Win32.Build.0 = debug|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|Win32.ActiveCfg = profile|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|Win32.Build.0 = profile|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|Win32.ActiveCfg = release|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|Win32.Build.0 = release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddins) = postSolution
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
+EndGlobal
diff --git a/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/Px3-SampleViewer.vcxproj b/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/Px3-SampleViewer.vcxproj
new file mode 100644
index 00000000..9bd125a6
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc11win32-PhysX_3.4/Px3-SampleViewer.vcxproj
@@ -0,0 +1,726 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="debug|Win32">
+ <Configuration>debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="release|Win32">
+ <Configuration>release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="checked|Win32">
+ <Configuration>checked</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="profile|Win32">
+ <Configuration>profile</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FC74E64C-DEA4-2352-C400-6D085370D268}</ProjectGuid>
+ <RootNamespace>Px3-SampleViewer</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <OutDir>./../../../bin/vc11win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/debug\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)DEBUG</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;_DEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3DEBUG_x86.lib;PhysX3CookingDEBUG_x86.lib;PhysX3CommonDEBUG_x86.lib;PhysX3CharacterKinematicDEBUG_x86.lib;PhysX3VehicleDEBUG.lib;PhysX3ExtensionsDEBUG.lib;PxTaskDEBUG_x86.lib;PxPvdSDKDEBUG_x86.lib;PxFoundationDEBUG_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)DEBUG.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win32;./../../../lib/vc11win32;./../../../../PxShared/lib/vc11win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc11win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)DEBUG.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc11win32 ..\..\..\bin\vc11win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc11win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <OutDir>./../../../bin/vc11win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/release\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3_x86.lib;PhysX3Cooking_x86.lib;PhysX3Common_x86.lib;PhysX3CharacterKinematic_x86.lib;PhysX3Vehicle.lib;PhysX3Extensions.lib;PxTask_x86.lib;PxPvdSDK_x86.lib;PxFoundation_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win32;./../../../lib/vc11win32;./../../../../PxShared/lib/vc11win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc11win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName).exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc11win32 ..\..\..\bin\vc11win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc11win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <OutDir>./../../../bin/vc11win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/checked\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)CHECKED</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3CHECKED_x86.lib;PhysX3CookingCHECKED_x86.lib;PhysX3CommonCHECKED_x86.lib;PhysX3CharacterKinematicCHECKED_x86.lib;PhysX3VehicleCHECKED.lib;PhysX3ExtensionsCHECKED.lib;PxTaskCHECKED_x86.lib;PxPvdSDKCHECKED_x86.lib;PxFoundationCHECKED_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)CHECKED.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win32;./../../../lib/vc11win32;./../../../../PxShared/lib/vc11win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc11win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)CHECKED.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc11win32 ..\..\..\bin\vc11win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc11win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <OutDir>./../../../bin/vc11win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/profile\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)PROFILE</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_PROFILE;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3PROFILE_x86.lib;PhysX3CookingPROFILE_x86.lib;PhysX3CommonPROFILE_x86.lib;PhysX3CharacterKinematicPROFILE_x86.lib;PhysX3VehiclePROFILE.lib;PhysX3ExtensionsPROFILE.lib;PxTaskPROFILE_x86.lib;PxPvdSDKPROFILE_x86.lib;PxFoundationPROFILE_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)PROFILE.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win32;./../../../lib/vc11win32;./../../../../PxShared/lib/vc11win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc11win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)PROFILE.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc11win32 ..\..\..\bin\vc11win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc11win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ActorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\MeshBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ActorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\MeshBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Actor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Compound.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundCreator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundGeometry.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Convex.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\ConvexRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Mesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\SimScene.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Actor.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Compound.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundCreator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundGeometry.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Convex.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\ConvexRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Mesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\RTdef.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\SimScene.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\glmesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\MyShaders.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\newParameters.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\glmesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\MyShaders.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\newParameters.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ansi2knr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cdjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ckconfig.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\djpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jchuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcinit.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcodec.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcomapi.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcparam.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcprepct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jctrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatadst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatasrc.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdinput.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmerge.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpostct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdtrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jerror.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemnobs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant1.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant2.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jutils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdcolmap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdswitch.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdtarga.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\stdafx.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\transupp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrtarga.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cderror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cdjpeg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcdiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jchuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcodec.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jconfig.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jddiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdhuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jerror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jinclude.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossls.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossy.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmemsys.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmorecfg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpegint.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpeglib.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jversion.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\rdswitch.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\stdafx.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\transupp.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Bounds3.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Plane.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Quat.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Transform.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Vec3.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\AABox.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\BmpFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Crab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\CrabManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FileScanner.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FrameBufferObject.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FXAAHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\GLFontRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HBAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HDRHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MathUtils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MediaPath.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RawLoader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RenderTarget.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerGamepad.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerScene.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneCrab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKapla.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaArena.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaTower.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneRagdollWashingMachine.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleCooking.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleSceneQuery.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Shader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShaderShadow.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShadowMap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SSAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainMesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Texture.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TgaFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Timing.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleCameraController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleControlInputs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleWheelQueryResults.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\XMLParser.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\AABox.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\BmpFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Crab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\CrabManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FileScanner.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FrameBufferObject.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FXAAHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontData.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HBAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HDRHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MathUtils.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MediaPath.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\PhysXMacros.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RawLoader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RenderTarget.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerGamepad.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerScene.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrabInputEventIds.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKapla.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaArena.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaTower.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneRagdollWashingMachine.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicle.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleCooking.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleSceneQuery.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Shader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShaderShadow.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShadowMap.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SSAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainMesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Texture.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TgaFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Timing.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleCameraController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleControlInputs.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleWheelQueryResults.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\XMLParser.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="./../../../externalIP/glew-1.13.0/compiler/vc11win32/glew-MT.vcxproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets"></ImportGroup>
+</Project>
diff --git a/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/GRB_Samples.sln b/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/GRB_Samples.sln
new file mode 100644
index 00000000..d697445e
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/GRB_Samples.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Px3-SampleViewer", "./Px3-SampleViewer.vcxproj", "{FC74E64C-DEA4-2352-C400-6D085370D268}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F} = {7D20139C-09F4-B0C5-B9C9-8E603785931F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew-MT", "./../../../externalIP/glew-1.13.0/compiler/vc11win64/glew-MT.vcxproj", "{7D20139C-09F4-B0C5-B9C9-8E603785931F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ checked|x64 = checked|x64
+ debug|x64 = debug|x64
+ profile|x64 = profile|x64
+ release|x64 = release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|x64.ActiveCfg = checked|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|x64.Build.0 = checked|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|x64.ActiveCfg = debug|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|x64.Build.0 = debug|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|x64.ActiveCfg = profile|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|x64.Build.0 = profile|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|x64.ActiveCfg = release|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|x64.Build.0 = release|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|x64.ActiveCfg = checked|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|x64.Build.0 = checked|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|x64.ActiveCfg = debug|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|x64.Build.0 = debug|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|x64.ActiveCfg = profile|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|x64.Build.0 = profile|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|x64.ActiveCfg = release|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|x64.Build.0 = release|x64
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddins) = postSolution
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
+EndGlobal
diff --git a/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/Px3-SampleViewer.vcxproj b/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/Px3-SampleViewer.vcxproj
new file mode 100644
index 00000000..bada3e47
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc11win64-PhysX_3.4/Px3-SampleViewer.vcxproj
@@ -0,0 +1,726 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="debug|x64">
+ <Configuration>debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="release|x64">
+ <Configuration>release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="checked|x64">
+ <Configuration>checked</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="profile|x64">
+ <Configuration>profile</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FC74E64C-DEA4-2352-C400-6D085370D268}</ProjectGuid>
+ <RootNamespace>Px3-SampleViewer</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v110</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <OutDir>./../../../bin/vc11win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/debug\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)DEBUG</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;_DEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3DEBUG_x64.lib;PhysX3CookingDEBUG_x64.lib;PhysX3CommonDEBUG_x64.lib;PhysX3CharacterKinematicDEBUG_x64.lib;PhysX3VehicleDEBUG.lib;PhysX3ExtensionsDEBUG.lib;PxTaskDEBUG_x64.lib;PxPvdSDKDEBUG_x64.lib;PxFoundationDEBUG_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)DEBUG.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win64;./../../../lib/vc11win64;./../../../../PxShared/lib/vc11win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc11win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)DEBUG.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc11win64 ..\..\..\bin\vc11win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc11win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <OutDir>./../../../bin/vc11win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/release\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3_x64.lib;PhysX3Cooking_x64.lib;PhysX3Common_x64.lib;PhysX3CharacterKinematic_x64.lib;PhysX3Vehicle.lib;PhysX3Extensions.lib;PxTask_x64.lib;PxPvdSDK_x64.lib;PxFoundation_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win64;./../../../lib/vc11win64;./../../../../PxShared/lib/vc11win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc11win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName).exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc11win64 ..\..\..\bin\vc11win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc11win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <OutDir>./../../../bin/vc11win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/checked\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)CHECKED</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3CHECKED_x64.lib;PhysX3CookingCHECKED_x64.lib;PhysX3CommonCHECKED_x64.lib;PhysX3CharacterKinematicCHECKED_x64.lib;PhysX3VehicleCHECKED.lib;PhysX3ExtensionsCHECKED.lib;PxTaskCHECKED_x64.lib;PxPvdSDKCHECKED_x64.lib;PxFoundationCHECKED_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)CHECKED.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win64;./../../../lib/vc11win64;./../../../../PxShared/lib/vc11win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc11win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)CHECKED.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc11win64 ..\..\..\bin\vc11win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc11win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <OutDir>./../../../bin/vc11win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/profile\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)PROFILE</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_PROFILE;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3PROFILE_x64.lib;PhysX3CookingPROFILE_x64.lib;PhysX3CommonPROFILE_x64.lib;PhysX3CharacterKinematicPROFILE_x64.lib;PhysX3VehiclePROFILE.lib;PhysX3ExtensionsPROFILE.lib;PxTaskPROFILE_x64.lib;PxPvdSDKPROFILE_x64.lib;PxFoundationPROFILE_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)PROFILE.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc11win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc11win64;./../../../lib/vc11win64;./../../../../PxShared/lib/vc11win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc11win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)PROFILE.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc11win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc11win64 ..\..\..\bin\vc11win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc11win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ActorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\MeshBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ActorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\MeshBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Actor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Compound.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundCreator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundGeometry.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Convex.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\ConvexRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Mesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\SimScene.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Actor.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Compound.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundCreator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundGeometry.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Convex.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\ConvexRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Mesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\RTdef.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\SimScene.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\glmesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\MyShaders.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\newParameters.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\glmesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\MyShaders.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\newParameters.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ansi2knr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cdjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ckconfig.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\djpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jchuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcinit.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcodec.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcomapi.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcparam.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcprepct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jctrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatadst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatasrc.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdinput.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmerge.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpostct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdtrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jerror.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemnobs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant1.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant2.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jutils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdcolmap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdswitch.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdtarga.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\stdafx.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\transupp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrtarga.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cderror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cdjpeg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcdiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jchuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcodec.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jconfig.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jddiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdhuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jerror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jinclude.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossls.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossy.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmemsys.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmorecfg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpegint.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpeglib.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jversion.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\rdswitch.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\stdafx.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\transupp.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Bounds3.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Plane.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Quat.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Transform.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Vec3.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\AABox.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\BmpFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Crab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\CrabManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FileScanner.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FrameBufferObject.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FXAAHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\GLFontRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HBAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HDRHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MathUtils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MediaPath.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RawLoader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RenderTarget.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerGamepad.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerScene.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneCrab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKapla.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaArena.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaTower.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneRagdollWashingMachine.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleCooking.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleSceneQuery.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Shader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShaderShadow.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShadowMap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SSAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainMesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Texture.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TgaFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Timing.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleCameraController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleControlInputs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleWheelQueryResults.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\XMLParser.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\AABox.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\BmpFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Crab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\CrabManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FileScanner.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FrameBufferObject.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FXAAHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontData.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HBAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HDRHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MathUtils.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MediaPath.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\PhysXMacros.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RawLoader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RenderTarget.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerGamepad.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerScene.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrabInputEventIds.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKapla.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaArena.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaTower.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneRagdollWashingMachine.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicle.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleCooking.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleSceneQuery.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Shader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShaderShadow.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShadowMap.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SSAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainMesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Texture.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TgaFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Timing.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleCameraController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleControlInputs.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleWheelQueryResults.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\XMLParser.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="./../../../externalIP/glew-1.13.0/compiler/vc11win64/glew-MT.vcxproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets"></ImportGroup>
+</Project>
diff --git a/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/GRB_Samples.sln b/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/GRB_Samples.sln
new file mode 100644
index 00000000..910243fe
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/GRB_Samples.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Px3-SampleViewer", "./Px3-SampleViewer.vcxproj", "{FC74E64C-DEA4-2352-C400-6D085370D268}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F} = {7D20139C-09F4-B0C5-B9C9-8E603785931F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew-MT", "./../../../externalIP/glew-1.13.0/compiler/vc12win32/glew-MT.vcxproj", "{7D20139C-09F4-B0C5-B9C9-8E603785931F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ checked|Win32 = checked|Win32
+ debug|Win32 = debug|Win32
+ profile|Win32 = profile|Win32
+ release|Win32 = release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|Win32.ActiveCfg = checked|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|Win32.Build.0 = checked|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|Win32.ActiveCfg = debug|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|Win32.Build.0 = debug|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|Win32.ActiveCfg = profile|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|Win32.Build.0 = profile|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|Win32.ActiveCfg = release|Win32
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|Win32.Build.0 = release|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|Win32.ActiveCfg = checked|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|Win32.Build.0 = checked|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|Win32.ActiveCfg = debug|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|Win32.Build.0 = debug|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|Win32.ActiveCfg = profile|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|Win32.Build.0 = profile|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|Win32.ActiveCfg = release|Win32
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|Win32.Build.0 = release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddins) = postSolution
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
+EndGlobal
diff --git a/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/Px3-SampleViewer.vcxproj b/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/Px3-SampleViewer.vcxproj
new file mode 100644
index 00000000..c021b01d
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc12win32-PhysX_3.4/Px3-SampleViewer.vcxproj
@@ -0,0 +1,726 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="debug|Win32">
+ <Configuration>debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="release|Win32">
+ <Configuration>release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="checked|Win32">
+ <Configuration>checked</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="profile|Win32">
+ <Configuration>profile</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FC74E64C-DEA4-2352-C400-6D085370D268}</ProjectGuid>
+ <RootNamespace>Px3-SampleViewer</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <OutDir>./../../../bin/vc12win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/debug\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)DEBUG</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;_DEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3DEBUG_x86.lib;PhysX3CookingDEBUG_x86.lib;PhysX3CommonDEBUG_x86.lib;PhysX3CharacterKinematicDEBUG_x86.lib;PhysX3VehicleDEBUG.lib;PhysX3ExtensionsDEBUG.lib;PxTaskDEBUG_x86.lib;PxPvdSDKDEBUG_x86.lib;PxFoundationDEBUG_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)DEBUG.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win32;./../../../lib/vc12win32;./../../../../PxShared/lib/vc12win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc12win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)DEBUG.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc12win32 ..\..\..\bin\vc12win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc12win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <OutDir>./../../../bin/vc12win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/release\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3_x86.lib;PhysX3Cooking_x86.lib;PhysX3Common_x86.lib;PhysX3CharacterKinematic_x86.lib;PhysX3Vehicle.lib;PhysX3Extensions.lib;PxTask_x86.lib;PxPvdSDK_x86.lib;PxFoundation_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win32;./../../../lib/vc12win32;./../../../../PxShared/lib/vc12win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc12win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName).exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc12win32 ..\..\..\bin\vc12win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc12win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <OutDir>./../../../bin/vc12win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/checked\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)CHECKED</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='checked|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3CHECKED_x86.lib;PhysX3CookingCHECKED_x86.lib;PhysX3CommonCHECKED_x86.lib;PhysX3CharacterKinematicCHECKED_x86.lib;PhysX3VehicleCHECKED.lib;PhysX3ExtensionsCHECKED.lib;PxTaskCHECKED_x86.lib;PxPvdSDKCHECKED_x86.lib;PxFoundationCHECKED_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)CHECKED.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win32;./../../../lib/vc12win32;./../../../../PxShared/lib/vc12win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc12win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)CHECKED.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc12win32 ..\..\..\bin\vc12win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc12win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <OutDir>./../../../bin/vc12win32-PhysX_3.4\</OutDir>
+ <IntDir>./Win32/Px3-SampleViewer/profile\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)PROFILE</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='profile|Win32'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win32;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_PROFILE;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3PROFILE_x86.lib;PhysX3CookingPROFILE_x86.lib;PhysX3CommonPROFILE_x86.lib;PhysX3CharacterKinematicPROFILE_x86.lib;PhysX3VehiclePROFILE.lib;PhysX3ExtensionsPROFILE.lib;PxTaskPROFILE_x86.lib;PxPvdSDKPROFILE_x86.lib;PxFoundationPROFILE_x86.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)PROFILE.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win32;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win32;./../../../lib/vc12win32;./../../../../PxShared/lib/vc12win32;./../../../externalIP/glew-1.13.0/lib/win32;./../../../externalIP/glut-3.7.6/lib/win32;./../../../externalIP/hbao+3.0/lib/win32;./../../../../Externals/cg/2.2/lib;./../../../lib/vc12win32-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)PROFILE.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win32-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physxcopy.bat ../../../../PhysX_3.4/bin/vc12win32 ..\..\..\bin\vc12win32-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win32 ../../../../Externals/cg/2.2/bin ../../../../PxShared/bin/vc12win32 ../../../externalIP/hbao+3.0/lib/win32</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ActorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\MeshBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ActorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\MeshBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Actor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Compound.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundCreator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundGeometry.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Convex.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\ConvexRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Mesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\SimScene.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Actor.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Compound.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundCreator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundGeometry.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Convex.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\ConvexRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Mesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\RTdef.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\SimScene.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\glmesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\MyShaders.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\newParameters.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\glmesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\MyShaders.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\newParameters.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ansi2knr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cdjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ckconfig.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\djpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jchuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcinit.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcodec.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcomapi.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcparam.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcprepct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jctrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatadst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatasrc.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdinput.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmerge.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpostct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdtrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jerror.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemnobs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant1.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant2.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jutils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdcolmap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdswitch.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdtarga.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\stdafx.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\transupp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrtarga.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cderror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cdjpeg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcdiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jchuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcodec.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jconfig.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jddiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdhuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jerror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jinclude.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossls.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossy.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmemsys.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmorecfg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpegint.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpeglib.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jversion.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\rdswitch.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\stdafx.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\transupp.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Bounds3.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Plane.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Quat.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Transform.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Vec3.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\AABox.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\BmpFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Crab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\CrabManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FileScanner.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FrameBufferObject.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FXAAHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\GLFontRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HBAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HDRHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MathUtils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MediaPath.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RawLoader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RenderTarget.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerGamepad.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerScene.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneCrab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKapla.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaArena.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaTower.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneRagdollWashingMachine.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleCooking.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleSceneQuery.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Shader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShaderShadow.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShadowMap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SSAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainMesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Texture.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TgaFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Timing.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleCameraController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleControlInputs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleWheelQueryResults.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\XMLParser.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\AABox.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\BmpFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Crab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\CrabManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FileScanner.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FrameBufferObject.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FXAAHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontData.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HBAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HDRHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MathUtils.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MediaPath.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\PhysXMacros.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RawLoader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RenderTarget.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerGamepad.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerScene.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrabInputEventIds.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKapla.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaArena.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaTower.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneRagdollWashingMachine.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicle.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleCooking.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleSceneQuery.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Shader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShaderShadow.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShadowMap.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SSAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainMesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Texture.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TgaFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Timing.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleCameraController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleControlInputs.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleWheelQueryResults.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\XMLParser.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="./../../../externalIP/glew-1.13.0/compiler/vc12win32/glew-MT.vcxproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets"></ImportGroup>
+</Project>
diff --git a/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/GRB_Samples.sln b/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/GRB_Samples.sln
new file mode 100644
index 00000000..6692209e
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/GRB_Samples.sln
@@ -0,0 +1,43 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Px3-SampleViewer", "./Px3-SampleViewer.vcxproj", "{FC74E64C-DEA4-2352-C400-6D085370D268}"
+ ProjectSection(ProjectDependencies) = postProject
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F} = {7D20139C-09F4-B0C5-B9C9-8E603785931F}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glew-MT", "./../../../externalIP/glew-1.13.0/compiler/vc12win64/glew-MT.vcxproj", "{7D20139C-09F4-B0C5-B9C9-8E603785931F}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ checked|x64 = checked|x64
+ debug|x64 = debug|x64
+ profile|x64 = profile|x64
+ release|x64 = release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|x64.ActiveCfg = checked|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.checked|x64.Build.0 = checked|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|x64.ActiveCfg = debug|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.debug|x64.Build.0 = debug|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|x64.ActiveCfg = profile|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.profile|x64.Build.0 = profile|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|x64.ActiveCfg = release|x64
+ {FC74E64C-DEA4-2352-C400-6D085370D268}.release|x64.Build.0 = release|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|x64.ActiveCfg = checked|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.checked|x64.Build.0 = checked|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|x64.ActiveCfg = debug|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.debug|x64.Build.0 = debug|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|x64.ActiveCfg = profile|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.profile|x64.Build.0 = profile|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|x64.ActiveCfg = release|x64
+ {7D20139C-09F4-B0C5-B9C9-8E603785931F}.release|x64.Build.0 = release|x64
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddins) = postSolution
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ EndGlobalSection
+EndGlobal
diff --git a/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/Px3-SampleViewer.vcxproj b/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/Px3-SampleViewer.vcxproj
new file mode 100644
index 00000000..384db2d7
--- /dev/null
+++ b/KaplaDemo/samples/compiler/vc12win64-PhysX_3.4/Px3-SampleViewer.vcxproj
@@ -0,0 +1,726 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="debug|x64">
+ <Configuration>debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="release|x64">
+ <Configuration>release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="checked|x64">
+ <Configuration>checked</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="profile|x64">
+ <Configuration>profile</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FC74E64C-DEA4-2352-C400-6D085370D268}</ProjectGuid>
+ <RootNamespace>Px3-SampleViewer</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <OutDir>./../../../bin/vc12win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/debug\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)DEBUG</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;_DEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3DEBUG_x64.lib;PhysX3CookingDEBUG_x64.lib;PhysX3CommonDEBUG_x64.lib;PhysX3CharacterKinematicDEBUG_x64.lib;PhysX3VehicleDEBUG.lib;PhysX3ExtensionsDEBUG.lib;PxTaskDEBUG_x64.lib;PxPvdSDKDEBUG_x64.lib;PxFoundationDEBUG_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)DEBUG.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win64;./../../../lib/vc12win64;./../../../../PxShared/lib/vc12win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc12win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)DEBUG.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc12win64 ..\..\..\bin\vc12win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc12win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <OutDir>./../../../bin/vc12win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/release\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3_x64.lib;PhysX3Cooking_x64.lib;PhysX3Common_x64.lib;PhysX3CharacterKinematic_x64.lib;PhysX3Vehicle.lib;PhysX3Extensions.lib;PxTask_x64.lib;PxPvdSDK_x64.lib;PxFoundation_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win64;./../../../lib/vc12win64;./../../../../PxShared/lib/vc12win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc12win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName).exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc12win64 ..\..\..\bin\vc12win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc12win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <OutDir>./../../../bin/vc12win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/checked\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)CHECKED</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='checked|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_CHECKED;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3CHECKED_x64.lib;PhysX3CookingCHECKED_x64.lib;PhysX3CommonCHECKED_x64.lib;PhysX3CharacterKinematicCHECKED_x64.lib;PhysX3VehicleCHECKED.lib;PhysX3ExtensionsCHECKED.lib;PxTaskCHECKED_x64.lib;PxPvdSDKCHECKED_x64.lib;PxFoundationCHECKED_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)CHECKED.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win64;./../../../lib/vc12win64;./../../../../PxShared/lib/vc12win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc12win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)CHECKED.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc12win64 ..\..\..\bin\vc12win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc12win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <OutDir>./../../../bin/vc12win64-PhysX_3.4\</OutDir>
+ <IntDir>./x64/Px3-SampleViewer/profile\</IntDir>
+ <TargetExt>.exe</TargetExt>
+ <TargetName>$(ProjectName)PROFILE</TargetName>
+ <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules />
+ <CodeAnalysisRuleAssemblies />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='profile|x64'">
+ <ClCompile>
+ <StringPooling>true</StringPooling>
+ <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
+ <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <FloatingPointModel>Fast</FloatingPointModel>
+ <AdditionalOptions>/EHsc /MP /D GLEW_STATIC /d2Zi+</AdditionalOptions>
+ <Optimization>Full</Optimization>
+ <AdditionalIncludeDirectories>./../../../../PhysX_3.4/Source/GeomUtils/src;./../../../../PhysX_3.4/Source/PhysX/src;./../../../../PhysX_3.4/Source/PhysX/src/buffering;./../../../../PhysX_3.4/Source/PvdRuntime/src;./../../../../PhysX_3.4/Source/GeomUtils/headers;./../../../../PhysX_3.4/Source/GeomUtils/include;./../../../../PhysX_3.4/Source/GeomUtils/opcode;./../../../../PhysX_3.4/Source/RepX/include;./../../../../PhysX_3.4/Source/RepXUpgrader/include;./../../../../PhysX_3.4/Source/foundation/source;./../../../../PhysX_3.4/Source/foundation/include;./../../../../PhysX_3.4/Source/Common/src;./../../../../PhysX_3.4/Source/LowLevel/software/include;./../../../../PhysX_3.4/Source/LowLevel/api/include;./../../../../PhysX_3.4/Source/SimulationController/include;./../../../../PhysX_3.4/Source/SceneQuery;./../../../../PhysX_3.4/Include;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../PhysX_3.4/Include/characterkinematic;./../../../../PhysX_3.4/Include/common;./../../../../PhysX_3.4/Include/cooking;./../../../../PhysX_3.4/Include/extensions;./../../../../PhysX_3.4/Include/foundation;./../../../../PhysX_3.4/Include/geometry;./../../../../PhysX_3.4/Include/gpu;./../../../../PhysX_3.4/Include/physxprofilesdk;./../../../../PhysX_3.4/Include/physxvisualdebuggersdk;./../../../../PhysX_3.4/Include/pvd;./../../../../PhysX_3.4/Include/pxtask;./../../../../PhysX_3.4/Include/RepX;./../../../../PhysX_3.4/Include/RepXUpgrader;./../../SampleCommonCode/src;./../../sampleViewer3;./../../sampleViewer3/Fracture;./../../sampleViewer3/Fracture/Core;./../../sampleViewer3/Render;./../../sampleViewer3/Vec;./../../../include_3;./../../../../PhysX_3.4/Samples/PxToolkit/include;./../../../../Externals/cg/2.2/include;./../../../../PhysX_3.4/Snippets/Graphics/include/win64;./../../../../PxShared/include;./../../../../PxShared/src/foundation/include;./../../../externalIP/hbao+3.0/include;./../../../externalIP/glew-1.13.0/include;./../../../Tools/nsight;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;WIN64;_CRT_SECURE_NO_DEPRECATE;_WIN32;AG_PERFMON;NDEBUG;PX_PROFILE;PX_SUPPORT_VISUAL_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ExceptionHandling>false</ExceptionHandling>
+ <WarningLevel>Level3</WarningLevel>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>NotUsing</PrecompiledHeader>
+ <PrecompiledHeaderFile></PrecompiledHeaderFile>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>OpenGL32.lib;glut32.lib;PhysX3PROFILE_x64.lib;PhysX3CookingPROFILE_x64.lib;PhysX3CommonPROFILE_x64.lib;PhysX3CharacterKinematicPROFILE_x64.lib;PhysX3VehiclePROFILE.lib;PhysX3ExtensionsPROFILE.lib;PxTaskPROFILE_x64.lib;PxPvdSDKPROFILE_x64.lib;PxFoundationPROFILE_x64.lib;cgGL.lib;cg.lib;GFSDK_SSAO_GL.win64.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <OutputFile>$(OutDir)$(ProjectName)PROFILE.exe</OutputFile>
+ <AdditionalLibraryDirectories>./../../../../PhysX_3.4/lib/vc12win64;./../../../../PhysX_3.4/Samples/PxToolkit/lib/vc12win64;./../../../lib/vc12win64;./../../../../PxShared/lib/vc12win64;./../../../externalIP/glew-1.13.0/lib/win64;./../../../externalIP/glut-3.7.6/lib/win64;./../../../externalIP/hbao+3.0/lib/win64;./../../../../Externals/cg/2.2/lib.x64;./../../../lib/vc12win64-PhysX_3.4;./../../../lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <ProgramDatabaseFile>$(OutDir)/$(ProjectName)PROFILE.exe.pdb</ProgramDatabaseFile>
+ <SubSystem>Console</SubSystem>
+ <ImportLibrary>./../../../lib/vc12win64-PhysX_3.4/$(TargetName).lib</ImportLibrary>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <TargetMachine>MachineX64</TargetMachine>
+ </Link>
+ <ResourceCompile>
+ </ResourceCompile>
+ <ProjectReference>
+ </ProjectReference>
+ <PostBuildEvent>
+ <Command>..\physx64copy.bat ../../../../PhysX_3.4/bin/vc12win64 ..\..\..\bin\vc12win64-PhysX_3.4 ../../../../Externals ../../../externalIP/glut-3.7.6/bin/win64 ../../../../Externals/cg/2.2/bin.x64 ../../../../PxShared/bin/vc12win64 ../../../externalIP/hbao+3.0/lib/win64</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ActorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\MeshBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ActorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundCreatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\CompoundGeometryBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\ConvexBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\MeshBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\PolygonTriangulatorBase.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Core\SimSceneBase.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Actor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Compound.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundCreator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\CompoundGeometry.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Convex.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\ConvexRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\Mesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Fracture\SimScene.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Actor.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Compound.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundCreator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\CompoundGeometry.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Convex.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\ConvexRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\Mesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\PolygonTriangulator.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\RTdef.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Fracture\SimScene.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\glmesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\MyShaders.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Render\newParameters.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\Render\FrameBufferObjectMRT.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\glmesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\MyShaders.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Render\newParameters.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ansi2knr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cdjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\cjpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\ckconfig.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\djpeg.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jccolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcdiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jchuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcinit.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jclossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcodec.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcomapi.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcparam.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcprepct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jcshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jctrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapimin.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdapistd.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatadst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdatasrc.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcoefct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdcolor.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddctmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jddiffct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdinput.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlhuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossls.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdlossy.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmainct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmarker.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmaster.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdmerge.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdphuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpostct.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdpred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdsample.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdscale.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdshuff.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jdtrans.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jerror.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jfdctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctflt.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctfst.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctint.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jidctred.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemmgr.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jmemnobs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant1.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jquant2.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\jutils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdcolmap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdswitch.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\rdtarga.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\stdafx.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\transupp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrbmp.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrgif.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrppm.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrrle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\IJGWin32\wrtarga.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cderror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\cdjpeg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\CPPJPEGWrapper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcdiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jchuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jcodec.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jconfig.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jddiffct.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jdhuff.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jerror.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jinclude.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossls.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jlossy.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmemsys.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jmorecfg.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpegint.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jpeglib.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\jversion.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\rdswitch.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\stdafx.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\IJGWin32\transupp.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Bounds3.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Plane.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Quat.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Transform.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Vec\Vec3.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\sampleViewer3\AABox.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\BmpFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Crab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\CrabManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FileScanner.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FrameBufferObject.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\FXAAHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\GLFontRenderer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HBAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\HDRHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MathUtils.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\MediaPath.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RawLoader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\RenderTarget.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewer.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerGamepad.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SampleViewerScene.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneCrab.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKapla.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaArena.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneKaplaTower.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneRagdollWashingMachine.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicle.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleCooking.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SceneVehicleSceneQuery.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Shader.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShaderShadow.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\ShadowMap.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\SSAOHelper.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainMesh.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Texture.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\TgaFile.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\Timing.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleCameraController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleControlInputs.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleController.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleManager.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\VehicleWheelQueryResults.cpp">
+ </ClCompile>
+ <ClCompile Include="..\..\sampleViewer3\XMLParser.cpp">
+ </ClCompile>
+ <ClInclude Include="..\..\sampleViewer3\AABox.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\BmpFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Crab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\CrabManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FileScanner.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FrameBufferObject.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\FXAAHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontData.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\GLFontRenderer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HBAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\HDRHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MathUtils.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\MediaPath.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\PhysXMacros.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RawLoader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\RenderTarget.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewer.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerGamepad.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SampleViewerScene.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrab.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneCrabInputEventIds.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKapla.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaArena.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneKaplaTower.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneRagdollWashingMachine.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicle.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleCooking.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SceneVehicleSceneQuery.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Shader.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShaderShadow.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\ShadowMap.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\SSAOHelper.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainMesh.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TerrainRandomSamplePrecompute.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Texture.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\TgaFile.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\Timing.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleCameraController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleControlInputs.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleController.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleManager.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\VehicleWheelQueryResults.h">
+ </ClInclude>
+ <ClInclude Include="..\..\sampleViewer3\XMLParser.h">
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="./../../../externalIP/glew-1.13.0/compiler/vc12win64/glew-MT.vcxproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets"></ImportGroup>
+</Project>
diff --git a/KaplaDemo/samples/sampleViewer3/AABox.cpp b/KaplaDemo/samples/sampleViewer3/AABox.cpp
new file mode 100644
index 00000000..c49929b6
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/AABox.cpp
@@ -0,0 +1,469 @@
+//--------------------------------------------------------------------------------------
+// FroggyAA
+// Author: Tristan Lorach
+//
+// Implementation of different antialiasing methods.
+// - typical MSAA
+// - CSAA
+// - Hardware AA mixed with FBO for supersampling pass
+// - simple downsampling
+// - downsampling with 1 or 2 kernel filters
+//
+// AABox is the class that will handle everything related to supersampling through
+// an offscreen surface defined thanks to FBO
+//
+// Copyright (c) NVIDIA Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+#include <stdlib.h>
+#include <stdio.h>
+#include <map>
+
+#include <GL/glew.h>
+#include <windows.h>
+#include "GL/glut.h"
+
+#include <Cg/CgGL.h>
+
+#include "AABox.h"
+
+AABox::AABox(std::string path) :
+ bValid(false),
+ vpx(0), vpy(0), vpw(0), vph(0),
+ posx(0), posy(0),
+ cgContext(NULL),
+ cgEffect(NULL),
+ cgPassDownSample(NULL), path(path), oldFbo(0)
+{
+ for(int i=0; i<4; i++) cgTechnique[i] = NULL;
+}
+AABox::~AABox()
+{
+}
+void AABox::Destroy()
+{
+ if(depth_rb)
+ glDeleteRenderbuffersEXT(1, &depth_rb);
+ if(color_rb)
+ glDeleteRenderbuffersEXT(1, &color_rb);
+ if(textureID)
+ glDeleteTextures(1, &textureID);
+ if(textureDepthID)
+ glDeleteTextures(1, &textureDepthID);
+ if(fb)
+ glDeleteFramebuffersEXT(1, &fb);
+ if(fbms)
+ glDeleteFramebuffersEXT(1, &fbms);
+ if(cgEffect)
+ cgDestroyEffect(cgEffect);
+ if(cgContext)
+ cgDestroyContext(cgContext);
+ depth_rb=0;
+ color_rb=0;
+ textureID=0;
+ textureDepthID=0;
+ fb=0;
+ fbms=0;
+ cgEffect=0;
+ cgContext=0;
+}
+/*-------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------*/
+void CheckFramebufferStatus()
+{
+ GLenum status;
+ status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ switch(status) {
+ case GL_FRAMEBUFFER_COMPLETE_EXT:
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ printf("Unsupported framebuffer format\n");
+ fprintf(stderr, "Unsupported framebuffer format");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ printf("Framebuffer incomplete, missing attachment\n");
+ fprintf(stderr, "Framebuffer incomplete, missing attachment");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ printf("Framebuffer incomplete, attached images must have same dimensions\n");
+ fprintf(stderr, "Framebuffer incomplete, attached images must have same dimensions");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ printf("Framebuffer incomplete, attached images must have same format\n");
+ fprintf(stderr, "Framebuffer incomplete, attached images must have same format");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing draw buffer\n");
+ fprintf(stderr, "Framebuffer incomplete, missing draw buffer");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing read buffer\n");
+ fprintf(stderr, "Framebuffer incomplete, missing read buffer");
+ break;
+ default:
+ printf("Error %x\n", status);
+ break;
+ }
+}
+bool AABox::initRT(int depthSamples, int coverageSamples)
+{
+ bool multisample = depthSamples > 0;
+ bool csaa = coverageSamples > depthSamples;
+ bool ret = true;
+ int query;
+ //
+ // init the texture that will also be the buffer to render to
+ //
+ glGenTextures(1, &textureID);
+ glBindTexture( GL_TEXTURE_2D, textureID);
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA16F, bufw, bufh, 0,
+ GL_RGBA, GL_FLOAT, NULL);
+
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glGenFramebuffersEXT(1, &fb);
+
+ //
+ // Handle multisample FBO's first
+ //
+ if (multisample)
+ {
+ //multisample : so we need to resolve from the MS FBO down to a FBO at non MS resolution
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0);
+ glGenTextures(1, &textureDepthID);
+ glBindTexture(GL_TEXTURE_2D, textureDepthID);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, bufw, bufh, 0,
+ GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textureDepthID, 0);
+ CheckFramebufferStatus();
+
+ //now handle the FBO in MS resolution
+ glGenFramebuffersEXT(1, &fbms);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms);
+ // initialize color renderbuffer
+ glGenRenderbuffersEXT(1, &color_rb);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, color_rb);
+
+ if (csaa & bCSAA)
+ {
+ glRenderbufferStorageMultisampleCoverageNV( GL_RENDERBUFFER_EXT, coverageSamples, depthSamples, GL_RGBA16F,
+ bufw, bufh);
+
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);
+
+ if ( query < coverageSamples)
+ ret = false;
+ else if ( query > coverageSamples)
+ {
+ // report back the actual number
+ coverageSamples = query;
+ }
+
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);
+
+ if ( query < depthSamples)
+ ret = false;
+ else if ( query > depthSamples)
+ {
+ // report back the actual number
+ depthSamples = query;
+ }
+ }
+ else
+ {
+
+ // create a regular MSAA color buffer
+ glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, depthSamples, GL_RGBA16F, bufw, bufh);
+
+ // check the number of samples
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query);
+
+ if ( query < depthSamples)
+ ret = false;
+ else if ( query > depthSamples)
+ {
+ depthSamples = query;
+ }
+
+ }
+
+ // attach the multisampled color buffer
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, color_rb);
+ CheckFramebufferStatus();
+
+ // bind the multisampled depth buffer
+ glGenRenderbuffersEXT(1, &depth_rb);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_rb);
+
+ // create the multisampled depth buffer (with or without coverage sampling)
+ if (csaa & bCSAA)
+ {
+
+ // create a coverage sampled MSAA depth buffer
+ glRenderbufferStorageMultisampleCoverageNV( GL_RENDERBUFFER_EXT, coverageSamples, depthSamples, GL_DEPTH_COMPONENT24,
+ bufw, bufh);
+
+ // check the number of coverage samples
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COVERAGE_SAMPLES_NV, &query);
+
+ if ( query < coverageSamples)
+ ret = false;
+ else if ( query > coverageSamples)
+ // set the coverage samples value to return the actual value
+ coverageSamples = query;
+
+ // cehck the number of stored color samples (same as depth samples)
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_COLOR_SAMPLES_NV, &query);
+
+ if ( query < depthSamples)
+ ret = false;
+ else if ( query > depthSamples)
+ // set the depth samples value to return the actual value
+ depthSamples = query;
+ }
+ else {
+
+ // create a regular (not coverage sampled) MSAA depth buffer
+ glRenderbufferStorageMultisampleEXT( GL_RENDERBUFFER_EXT, depthSamples, GL_DEPTH_COMPONENT24, bufw, bufh);
+
+ // check the number of depth samples
+ glGetRenderbufferParameterivEXT( GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &query);
+
+ if ( query < depthSamples)
+ ret = false;
+ else if ( query < depthSamples)
+ depthSamples = query;
+ }
+
+ // attach the depth buffer
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_rb);
+
+ CheckFramebufferStatus();
+
+ } // if (multisample)
+ else // Depth buffer created as a texture...
+ {
+ //non-multisample, so bind things directly to the FBO
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureID, 0);
+
+ glGenTextures(1, &textureDepthID);
+ glBindTexture( GL_TEXTURE_2D, textureDepthID);
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, bufw, bufh, 0,
+ GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf( GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
+
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, textureDepthID, 0);
+
+ CheckFramebufferStatus();
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, multisample ? fbms : fb);
+ glGetIntegerv( GL_RED_BITS, &query);
+ if ( query != 16)
+ {
+ printf( "Got %d red bits expected %d\n", query, 16);
+ ret = false;
+ }
+ glGetIntegerv( GL_DEPTH_BITS, &query);
+ if ( query != 24)
+ {
+ printf( "Got %d depth bits expected %d\n", query, 24);;
+ ret = false;
+ }
+ if (multisample)
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);
+ glGetIntegerv( GL_RED_BITS, &query);
+ if ( query != 16)
+ {
+ printf( "Got %d red bits expected %d\n", query, 16);
+ ret = false;
+ }
+ }
+
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
+
+ return ret;
+}
+/*-------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------*/
+bool AABox::Initialize(int w, int h, float ssfact, int depthSamples, int coverageSamples)
+{
+ if (!glewIsSupported(
+ "GL_VERSION_2_0 "
+ "GL_EXT_framebuffer_object "
+ ))
+ {
+ printf("Unable to load extensions\n");
+ return false;
+ }
+ bCSAA = glewIsExtensionSupported("GL_NV_framebuffer_multisample_coverage") ? true : false;
+ if((!bCSAA) && coverageSamples)
+ {
+ printf("Note: GL_NV_framebuffer_multisample_coverage unavailable, using regular MSAA only\n");
+ }
+
+ Destroy();
+
+ bufw = (int)(ssfact*(float)w+0.99f);
+ bufh = (int)(ssfact*(float)h+0.99f);
+ //
+ // FBO
+ //
+ initRT(depthSamples, coverageSamples);
+ CheckFramebufferStatus();
+ //
+ // CGFX things
+ //
+ cgContext = cgCreateContext();
+ cgGLRegisterStates(cgContext);
+
+ char fileName[200];
+ sprintf(fileName, "%s/AABox.cgfx", path.c_str());
+
+ cgEffect = cgCreateEffectFromFile(cgContext, fileName, NULL);
+ if(!cgEffect)
+ {
+ const char *listing = cgGetLastListing(cgContext);
+ //fprintf(stderr, "CgFx Parse error : \n %s\n", listing);
+ bValid = false;
+ //printf("Trying other path...\n");
+ cgEffect = cgCreateEffectFromFile(cgContext, fileName, NULL);
+ if(!cgEffect)
+ {
+ fprintf(stderr, "CgFx Parse error : \n %s\n", listing);
+ bValid = false;
+ return false;
+ }
+ }
+ cgTechnique[0] = cgGetFirstTechnique(cgEffect);
+ cgTechnique[1] = cgGetNextTechnique(cgTechnique[0]);
+ cgTechnique[2] = cgGetNextTechnique(cgTechnique[1]);
+ cgTechnique[3] = cgGetNextTechnique(cgTechnique[2]);
+ cgBlendFactor = cgGetNamedEffectParameter(cgEffect, "blendFactor");
+ cgSSsampler = cgGetNamedEffectParameter(cgEffect, "SSsampler");
+ cgDepthSSsampler = cgGetNamedEffectParameter(cgEffect, "DepthSSsampler");
+ cgTexelSize = cgGetNamedEffectParameter(cgEffect, "SSTexelSize");
+ cgBlendFactor = cgGetNamedEffectParameter(cgEffect, "blendFactor");
+
+ cgGLSetParameter2f(cgTexelSize, 1.0f/(float)bufw, 1.0f/(float)bufh);
+
+ bValid = true;
+ return true;
+}
+
+#define FULLSCRQUAD()\
+ glBegin(GL_QUADS);\
+ glTexCoord2f(0,0);\
+ glVertex4f(-1, -1, 0.0,1);\
+ glTexCoord2f(1,0);\
+ glVertex4f(1, -1,0.0,1);\
+ glTexCoord2f(1,1);\
+ glVertex4f(1, 1,0.0,1);\
+ glTexCoord2f(0,1);\
+ glVertex4f(-1, 1,0.0,1);\
+ glEnd();
+
+/*-------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------*/
+void AABox::Draw(int technique)
+{
+ CGbool bRes;
+ if(technique > 4)
+ return;
+ bRes = cgValidateTechnique(cgTechnique[technique]);
+ if(!bRes)
+ {
+ if(bValid)
+ {
+ fprintf(stderr, "Validation of FilterRect failed\n");
+ bValid = false;
+ }
+ return;
+ }
+ else bValid = true;
+ if(!bValid)
+ return;
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
+ //
+ // if this FBO is multisampled, resolve it, so it can be displayed
+ // the blit will allow the multisampled buffer to be stretched to a normal buffer at res bufw/bufh
+ //
+ if( fbms )
+ {
+
+ glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, fbms);
+ glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, fb);
+ glBlitFramebufferEXT(0, 0, bufw, bufh, 0, 0, bufw, bufh, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
+
+ cgGLSetupSampler(cgSSsampler, textureID);
+ cgGLSetupSampler(cgDepthSSsampler, textureDepthID);
+
+
+
+ CGpass cgPass = cgGetFirstPass(cgTechnique[technique]);
+ cgSetPassState(cgPass);
+ //
+ // During this full screen pass, we will down-sample the buffer and
+ // eventually filter it
+ //
+ FULLSCRQUAD();
+ cgResetPassState(cgPass);
+}
+/*-------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------*/
+void AABox::Activate(int x, int y)
+{
+ if(!bValid)
+ return;
+ glBindTexture(GL_TEXTURE_2D, 0);
+ //
+ // Bind the framebuffer to render on : can be either Multisampled one or normal one
+ //
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms ? fbms : fb);
+
+ glPushAttrib(GL_VIEWPORT_BIT);
+ posx = x;
+ posy = y;
+ glViewport(0, 0, bufw, bufh);
+}
+/*-------------------------------------------------------------------------
+
+ -------------------------------------------------------------------------*/
+void AABox::Deactivate()
+{
+ if(!bValid)
+ return;
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldFbo);
+ glPopAttrib();
+}
+
+void AABox::Rebind() {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbms ? fbms : fb);
+ glViewport(0, 0, bufw, bufh);
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/AABox.h b/KaplaDemo/samples/sampleViewer3/AABox.h
new file mode 100644
index 00000000..912cc148
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/AABox.h
@@ -0,0 +1,77 @@
+//--------------------------------------------------------------------------------------
+// FroggyAA
+// Author: Tristan Lorach
+//
+// Implementation of different antialiasing methods.
+// - typical MSAA
+// - CSAA
+// - Hardware AA mixed with FBO for supersampling pass
+// - simple downsampling
+// - downsampling with 1 or 2 kernel filters
+//
+// AABox is the class that will handle everything related to supersampling through
+// an offscreen surface defined thanks to FBO
+// Basic use is :
+//
+// Initialize()
+// ...
+// Activate(int x=0, int y=0)
+// Draw the scene (so, in the offscreen supersampled buffer)
+// Deactivate()
+// Draw() : downsample to backbuffer
+// ...
+// Destroy()
+//
+//
+// Copyright (c) NVIDIA Corporation. All rights reserved.
+//--------------------------------------------------------------------------------------
+#define FB_SS 0
+#include <Cg/CgGL.h>
+#include <string>
+class AABox
+{
+public:
+ AABox(std::string path);
+ ~AABox();
+
+ bool Initialize(int w, int h, float ssfact, int depthSamples, int coverageSamples);
+ void Destroy();
+
+ void Activate(int x=0, int y=0);
+ void Deactivate();
+ void Rebind();
+ void Draw(int technique);
+ int getBufW() const {return bufw;};
+ int getBufH() const {return bufh;};
+ GLuint getTextureID() {return textureID;};
+
+ CGparameter cgBlendFactor;
+//protected:
+ bool bValid;
+ bool bCSAA;
+
+ int vpx, vpy, vpw, vph;
+ int posx, posy;
+ int bufw, bufh;
+
+ CGcontext cgContext;
+ CGeffect cgEffect;
+ CGtechnique cgTechnique[4];
+ CGpass cgPassDownSample;
+ CGpass cgPassDrawFinal;
+ GLuint textureID;
+ GLuint textureDepthID;
+ CGparameter cgSrcSampler;
+ CGparameter cgSSsampler;
+ CGparameter cgDepthSSsampler;
+ CGparameter cgTexelSize;
+ GLuint fb;
+ GLuint fbms;
+ GLuint depth_rb;
+ GLuint color_rb;
+ GLuint oldFbo;
+ std::string path;
+
+ bool initRT(int depthSamples, int coverageSamples);
+}; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/BmpFile.cpp b/KaplaDemo/samples/sampleViewer3/BmpFile.cpp
new file mode 100644
index 00000000..50c213a2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/BmpFile.cpp
@@ -0,0 +1,184 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "BmpFile.h"
+
+static bool isBigEndian() { int i = 1; return *((char*)&i)==0; }
+
+static unsigned short endianSwap(unsigned short nValue)
+{
+ return (((nValue>> 8)) | (nValue << 8));
+
+}
+
+static unsigned int endianSwap(unsigned int i)
+{
+ unsigned char b1, b2, b3, b4;
+
+ b1 = i & 255;
+ b2 = ( i >> 8 ) & 255;
+ b3 = ( i>>16 ) & 255;
+ b4 = ( i>>24 ) & 255;
+
+ return ((unsigned int)b1 << 24) + ((unsigned int)b2 << 16) + ((unsigned int)b3 << 8) + b4;
+}
+
+// -------------------------------------------------------------------
+
+#pragma pack(1)
+
+struct BMPHEADER {
+ unsigned short Type;
+ unsigned int Size;
+ unsigned short Reserved1;
+ unsigned short Reserved2;
+ unsigned int OffBits;
+};
+
+// Only Win3.0 BMPINFO (see later for OS/2)
+struct BMPINFO {
+ unsigned int Size;
+ unsigned int Width;
+ unsigned int Height;
+ unsigned short Planes;
+ unsigned short BitCount;
+ unsigned int Compression;
+ unsigned int SizeImage;
+ unsigned int XPelsPerMeter;
+ unsigned int YPelsPerMeter;
+ unsigned int ClrUsed;
+ unsigned int ClrImportant;
+};
+
+#pragma pack()
+
+// Compression Type
+#define BI_RGB 0L
+#define BI_RLE8 1L
+#define BI_RLE4 2L
+
+// -------------------------------------------------------------------
+BmpLoaderBuffer::BmpLoaderBuffer()
+{
+ mWidth = 0;
+ mHeight = 0;
+ mRGB = NULL;
+}
+
+
+// -------------------------------------------------------------------
+BmpLoaderBuffer::~BmpLoaderBuffer()
+{
+ if (mRGB) free(mRGB);
+}
+
+// -------------------------------------------------------------------
+bool BmpLoaderBuffer::loadFile(const char *filename)
+{
+ if (mRGB) {
+ free(mRGB);
+ mRGB = NULL;
+ }
+ mWidth = 0;
+ mHeight = 0;
+
+ FILE *f = fopen(filename, "rb");
+ if (!f)
+ return false;
+
+ size_t num;
+ BMPHEADER header;
+ num = fread(&header, sizeof(BMPHEADER), 1, f);
+ if(isBigEndian()) header.Type = endianSwap(header.Type);
+ if (num != 1) { fclose(f); return false; }
+ if (header.Type != 'MB') { fclose(f); return false; }
+
+ BMPINFO info;
+ num = fread(&info, sizeof(BMPINFO), 1, f);
+ if (num != 1) { fclose(f); return false; }
+ if(isBigEndian()) info.Size = endianSwap(info.Size);
+ if(isBigEndian()) info.BitCount = endianSwap(info.BitCount);
+ if(isBigEndian()) info.Compression = endianSwap(info.Compression);
+ if(isBigEndian()) info.Width = endianSwap(info.Width);
+ if(isBigEndian()) info.Height = endianSwap(info.Height);
+
+ if (info.Size != sizeof(BMPINFO)) { fclose(f); return false; }
+ if (info.BitCount != 24) { fclose(f); return false; }
+ if (info.Compression != BI_RGB) { fclose(f); return false; }
+
+ mWidth = info.Width;
+ mHeight = info.Height;
+ mRGB = (unsigned char*)malloc(mWidth * mHeight * 3);
+
+ int lineLen = (((info.Width * (info.BitCount>>3)) + 3)>>2)<<2;
+ unsigned char *line = (unsigned char *)malloc(lineLen);
+
+ for(int i = info.Height-1; i >= 0; i--) {
+ num = fread(line, lineLen, 1, f);
+ if (num != 1) { fclose(f); return false; }
+ unsigned char *src = line;
+ unsigned char *dest = mRGB + i*info.Width*3;
+ for(unsigned int j = 0; j < info.Width; j++) {
+ unsigned char r,g,b;
+ b = *src++; g = *src++; r = *src++;
+ *dest++ = r; *dest++ = g; *dest++ = b;
+ }
+ }
+
+ free(line);
+ fclose(f);
+
+ return true;
+}
+
+// -------------------------------------------------------------------
+bool saveBmpRBG(const char *filename, int width, int height, void *data)
+{
+ FILE *f = fopen(filename, "wb");
+ if (!f) return false;
+
+ // todo : works on pcs only, swap correctly if big endian
+ BMPHEADER header;
+ header.Type = 'MB';
+ header.Size = sizeof(BMPINFO);
+ header.Reserved1 = 0;
+ header.Reserved2 = 0;
+ header.OffBits = sizeof(BMPHEADER) + sizeof(BMPINFO);
+ fwrite(&header, sizeof(BMPHEADER), 1, f);
+
+ BMPINFO info;
+ info.Size = sizeof(BMPINFO);
+ info.Width = width;
+ info.Height = height;
+ info.Planes = 1;
+ info.BitCount = 24;
+ info.Compression = BI_RGB;
+ info.XPelsPerMeter = 4000;
+ info.YPelsPerMeter = 4000;
+ info.ClrUsed = 0;
+ info.ClrImportant = 0;
+ fwrite(&info, sizeof(info), 1, f);
+
+ // padded to multiple of 4
+ int lineLen = (((info.Width * (info.BitCount>>3)) + 3)>>2)<<2;
+ info.SizeImage = lineLen * height;
+
+ unsigned char *line = (unsigned char *)malloc(lineLen);
+
+ for(int i = 0; i < height; i++) {
+ unsigned char *src = (unsigned char*)data + i*width*3;
+ unsigned char *dest = line;
+ for(int j = 0; j < width; j++) {
+ unsigned char r,g,b;
+ r = *src++; g = *src++; b = *src++;
+ *dest++ = b; *dest++ = g; *dest++ = r;
+ }
+ for (int j = 3*width; j < lineLen; j++)
+ *dest++ = 0;
+ fwrite(line, lineLen, 1, f);
+ }
+
+ free(line);
+ fclose(f);
+
+ return true;
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/BmpFile.h b/KaplaDemo/samples/sampleViewer3/BmpFile.h
new file mode 100644
index 00000000..8e4206d2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/BmpFile.h
@@ -0,0 +1,21 @@
+#ifndef BMP_LOADER_H
+#define BMP_LOADER_H
+
+class BmpLoaderBuffer
+{
+public:
+
+ BmpLoaderBuffer(void);
+ ~BmpLoaderBuffer(void);
+
+ // Data is persists until the class is destructed.
+ bool loadFile(const char *filename);
+
+ int mWidth;
+ int mHeight;
+ unsigned char *mRGB;
+};
+
+bool saveBmpRBG(const char *filename, int width, int height, void *data);
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Crab.cpp b/KaplaDemo/samples/sampleViewer3/Crab.cpp
new file mode 100644
index 00000000..2eba5e23
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Crab.cpp
@@ -0,0 +1,820 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "PxPhysicsAPI.h"
+#include "extensions/PxExtensionsAPI.h"
+#include "Crab.h"
+#include "CrabManager.h"
+#include "SceneCrab.h"
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include <GL/glut.h>
+
+#include "PxTkStream.h"
+#include "PxTkFile.h"
+using namespace PxToolkit;
+// if enabled: runs the crab AI in sync, not as a parallel task to physx.
+#define DEBUG_RENDERING 0
+
+
+void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask);
+
+// table with default times in seconds how the crab AI will try to stay in a state
+static const PxReal gDefaultStateTime[CrabState::eNUM_STATES] = { 5.0f, 30.0f, 30.0f, 10.0f, 10.0f, 6.0f };
+
+
+Crab::Crab(CrabManager* crabManager, PxU32 updateFrequency)
+{
+ mUpdateFrequency = updateFrequency;
+ mManager = crabManager;
+ initMembers();
+}
+
+
+void Crab::initMembers()
+{
+ mCrabBody = NULL;
+ //mSqRayBuffer = NULL;
+ mSqSweepBuffer = NULL;
+ mLegHeight = 0;
+ mMaterial = mManager->getPhysics().createMaterial(0.9f, 0.7f, 0.01f);
+ mCrabState = CrabState::eWAITING;
+ mStateTime = gDefaultStateTime[CrabState::eWAITING];
+ mAccumTime = 0;
+ mElapsedTime = 0;
+
+ mAcceleration[0] = 0;
+ mAcceleration[1] = 0;
+
+ mAccelerationBuffer[0] = 0;
+ mAccelerationBuffer[1] = 0;
+ for (PxU32 a = 0; a < 6; ++a)
+ mDistances[a] = 0;
+
+ // setup buffer for 10 batched rays and 10 hits
+ //mSqRayBuffer = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(SqRayBuffer), PX_DEBUG_EXP("SqRayBuffer")), SqRayBuffer)(this, 10, 10);
+ mSqSweepBuffer = PX_PLACEMENT_NEW(PX_ALLOC(sizeof(SqSweepBuffer), PX_DEBUG_EXP("SqSweepBuffer")), SqSweepBuffer)(this, 6, 6);
+
+}
+
+Crab::~Crab()
+{
+ //mSqRayBuffer->~SqRayBuffer();
+ //PX_FREE(mSqRayBuffer);
+
+ mSqSweepBuffer->~SqSweepBuffer();
+ PX_FREE(mSqSweepBuffer);
+}
+
+void Crab::setScene(PxScene* scene)
+{
+ mSqSweepBuffer->setScene(scene);
+}
+
+
+static void setShapeFlag(PxRigidActor* actor, PxShapeFlag::Enum flag, bool flagValue)
+{
+ const PxU32 numShapes = actor->getNbShapes();
+ PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*numShapes, PX_DEBUG_EXP("SceneCrab:setShapeFlag"));
+ actor->getShapes(shapes, numShapes);
+ for (PxU32 i = 0; i < numShapes; i++)
+ {
+ PxShape* shape = shapes[i];
+ shape->setFlag(flag, flagValue);
+ }
+ PX_FREE(shapes);
+}
+
+PxVec3 Crab::getPlaceOnFloor(PxVec3 start)
+{
+ PxRaycastBuffer rayHit;
+ mManager->getScene().raycast(start, PxVec3(0, -1, 0), 1000.0f, rayHit);
+
+ return rayHit.block.position + PxVec3(0, mLegHeight, 0);
+}
+
+//static const PxSerialObjectId mMaterial_id = (PxSerialObjectId)0x01;
+//static const PxSerialObjectId mCrabBody_id = (PxSerialObjectId)0x02;
+//static const PxSerialObjectId mMotorJoint0_id = (PxSerialObjectId)0x03;
+//static const PxSerialObjectId mMotorJoint1_id = (PxSerialObjectId)0x04;
+//
+//struct FilterGroup
+//{
+// enum Enum
+// {
+// eSUBMARINE = (1 << 0),
+// eMINE_HEAD = (1 << 1),
+// eMINE_LINK = (1 << 2),
+// eCRAB = (1 << 3),
+// eHEIGHTFIELD = (1 << 4),
+// };
+//};
+//
+//void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask)
+//{
+// PxFilterData filterData;
+// filterData.word0 = filterGroup; // word0 = own ID
+// filterData.word1 = filterMask; // word1 = ID mask to filter pairs that trigger a contact callback;
+// const PxU32 numShapes = actor->getNbShapes();
+// PxShape** shapes = (PxShape**)PX_ALLOC(sizeof(PxShape*)*numShapes, PX_DEBUG_EXP("setupFiltering"));
+// actor->getShapes(shapes, numShapes);
+// for (PxU32 i = 0; i < numShapes; i++)
+// {
+// PxShape* shape = shapes[i];
+// shape->setSimulationFilterData(filterData);
+// }
+// PX_FREE(shapes);
+//}
+
+void setupSQFiltering(PxRigidActor* actor, PxU32 crabId)
+{
+ PxFilterData filterData(0, 0, 0, crabId);
+ PxShape* shape;
+ PxU32 nbShapes = actor->getNbShapes();
+ for (PxU32 a = 0; a < nbShapes; ++a)
+ {
+ actor->getShapes(&shape, 1, a);
+ shape->setQueryFilterData(filterData);
+ }
+}
+
+Crab* Crab::create(const PxVec3& _crabPos, const PxReal crabDepth, const PxReal scale, const PxReal legMass, const PxU32 numLegs)
+{
+ static PxU32 crabId = 0;
+ crabId++;
+ /*static const PxReal scale = 0.8f;
+ static const PxReal crabDepth = 2.0f;
+ static const PxVec3 crabBodyDim = PxVec3(0.8f, 0.8f, crabDepth*0.5f)*scale;
+ static const PxReal legMass = 0.03f;*/
+
+ const PxVec3 crabBodyDim = PxVec3(0.8f, 0.8f, crabDepth*0.5f)*scale;
+ const PxReal velocity = 0.0f;
+ //static const PxReal maxForce = 4000.0f;
+
+ const PxReal maxForce = 50000.0f;
+
+ LegParameters params; // check edge ascii art in Crab.h
+ params.a = 0.5f;
+ params.b = 0.6f;
+ params.c = 0.5f;
+ params.d = 0.5f;
+ params.e = 1.5f;
+ params.m = 0.3f;
+ params.n = 0.1f;
+
+ mLegHeight = scale*2.0f*(params.d + params.c);
+ mLegHeight += 0.5f;
+ PxVec3 crabPos = getPlaceOnFloor(_crabPos);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ PxVec3 vel(0), omega(0);
+ PxTransform localPose = PxTransform(PxQuat(PxHalfPi*0.5f, PxVec3(0, 0, 1)));
+ SimScene* simScene = mManager->getSceneCrab()->getSimScene();
+ simScene->getCompoundCreator()->createBox(2.f*crabBodyDim, &localPose);
+ //mCrabBody = PxCreateDynamic(getPhysics(), PxTransform(crabPos), PxBoxGeometry(crabBodyDim), *mMaterial, 10.f);
+ Compound* compound = mManager->createObject(PxTransform(crabPos), vel, omega, false, mat);
+ mCrabBody = compound->getPxActor();
+
+
+ /*PxShape* shape; mCrabBody->getShapes(&shape, 1);
+ shape->setLocalPose(PxTransform(PxQuat(PxHalfPi*0.5f, PxVec3(0, 0, 1))));*/
+ PxRigidBodyExt::setMassAndUpdateInertia(*mCrabBody, legMass*10.0f);
+ PxTransform cmPose = mCrabBody->getCMassLocalPose();
+ cmPose.p.y -= 1.8f;
+ mCrabBody->setCMassLocalPose(cmPose);
+ //mCrabBody->setAngularDamping(100.0f);
+ mCrabBody->setAngularDamping(0.5f);
+ mCrabBody->userData = this;
+ //mActors.push_back(mCrabBody);
+
+ PxQuat rotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
+
+ PxD6Joint* joint = PxD6JointCreate(mManager->getPhysics(), NULL, PxTransform(rotation), mCrabBody, PxTransform(mCrabBody->getGlobalPose().q.getConjugate() * rotation));
+
+ joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
+
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
+
+ PxJointLimitCone limitCone(3.1415 / 6.f, 3.1415 / 6.f);
+ joint->setSwingLimit(limitCone);
+
+
+
+ // legs
+ PxReal recipNumLegs = 1.0f / PxReal(numLegs);
+ PxReal recipNumLegsMinus1 = 1.0f / PxReal(numLegs - 1);
+ //PX_COMPILE_TIME_ASSERT((numLegs & 1) == 0);
+
+ PxRigidDynamic* motor[2];
+ {
+ const PxReal density = 1.0f;
+ const PxReal m = params.m * scale;
+ const PxReal n = params.n * scale;
+ const PxBoxGeometry boxGeomM = PxBoxGeometry(m, m, crabBodyDim.z * 0.5f + 0.15f);
+
+ // create left and right motor
+ PxVec3 motorPos = crabPos + PxVec3(0, n, 0);
+ for (PxU32 i = 0; i < 2; i++)
+ {
+ PxVec3 motorOfs = i == 0 ? PxVec3(0, 0, boxGeomM.halfExtents.z) : -PxVec3(0, 0, boxGeomM.halfExtents.z);
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomM.halfExtents);
+ Compound* motorCompound = mManager->createObject(PxTransform(motorPos + motorOfs), vel, omega, false, mat);
+ motor[i] = motorCompound->getPxActor();
+
+ PxRigidBodyExt::setMassAndUpdateInertia(*motor[i], legMass);
+ motor[i]->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+ setShapeFlag(motor[i], PxShapeFlag::eSIMULATION_SHAPE, false);
+ setShapeFlag(motor[i], PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+
+ /*mMotorJoint[i] = PxRevoluteJointCreate(mManager->getPhysics(),
+ mCrabBody, PxTransform(motorOfs, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ motor[i], PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ mMotorJoint[i]->setDriveVelocity(velocity);
+ mMotorJoint[i]->setDriveForceLimit(maxForce);
+ mMotorJoint[i]->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, true);*/
+
+ mMotorJoint[i] = PxD6JointCreate(mManager->getPhysics(),
+ mCrabBody, PxTransform(motorOfs, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ motor[i], PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ mMotorJoint[i]->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+ mMotorJoint[i]->setDriveVelocity(PxVec3(0), PxVec3(velocity, 0.f, 0.f));
+ mMotorJoint[i]->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 30.f, maxForce));
+
+ //mActors.push_back(motor[i]);
+ //mJoints.push_back(mMotorJoint[i]);
+ }
+
+ // create legs and attach to left and right motor
+ PxReal legSpacing = crabDepth*recipNumLegsMinus1*scale;
+ PxVec3 bodyToLegPos0 = PxVec3(0, 0, crabBodyDim.z);
+ PxVec3 bodyToLegPos1 = PxVec3(0, 0, crabBodyDim.z - (numLegs / 2)*legSpacing);
+ PxVec3 motorToLegPos0 = PxVec3(0, 0, crabBodyDim.z*0.5f);
+ PxVec3 motorToLegPos1 = PxVec3(0, 0, (crabBodyDim.z - legSpacing)*0.5f);
+ for (PxU32 i = 0; i < numLegs / 2; i++)
+ {
+ PxReal angle0 = -PxHalfPi + PxTwoPi*recipNumLegs*i;
+ PxReal angle1 = angle0 + PxPi;
+
+ createLeg(mCrabBody, bodyToLegPos0, legMass, params, scale, motor[0], motorToLegPos0 + m * PxVec3(PxCos(angle0), PxSin(angle0), 0));
+ createLeg(mCrabBody, bodyToLegPos1, legMass, params, scale, motor[1], motorToLegPos1 + m * PxVec3(PxCos(angle1), PxSin(angle1), 0));
+ bodyToLegPos0.z -= legSpacing;
+ bodyToLegPos1.z -= legSpacing;
+ motorToLegPos0.z -= legSpacing;
+ motorToLegPos1.z -= legSpacing;
+ }
+ }
+
+ setupSQFiltering(mCrabBody, crabId);
+
+ return this;
+}
+
+void Crab::createLeg(PxRigidDynamic* mainBody, PxVec3 localPos, PxReal mass, const LegParameters& params, PxReal scale, PxRigidDynamic* motor, PxVec3 motorAttachmentPos)
+{
+ PxVec3 crabLegPos = mainBody->getGlobalPose().p + localPos;
+
+ // params for Theo Jansen's machine
+ // check edge ascii art in Crab.h
+ const PxReal stickExt = 0.125f * 0.5f * scale;
+ const PxReal a = params.a * scale;
+ const PxReal b = params.b * scale;
+ const PxReal c = params.c * scale;
+ const PxReal d = params.d * scale;
+ const PxReal e = params.e * scale;
+ const PxReal m = params.m * scale;
+ const PxReal n = params.n * scale;
+
+ const PxReal density = 1.0f;
+
+ PxBoxGeometry boxGeomA = PxBoxGeometry(a, stickExt, stickExt);
+ PxBoxGeometry boxGeomB = PxBoxGeometry(stickExt, b, stickExt);
+ PxBoxGeometry boxGeomC = PxBoxGeometry(stickExt, c, stickExt);
+
+ //PxCapsuleGeometry capsGeomD = PxCapsuleGeometry(stickExt*2.0f, d);
+ PxBoxGeometry boxGeomD = PxBoxGeometry(d, stickExt*3.0f, stickExt*3.0f);
+
+ ShaderMaterial mat;
+ mat.init();
+ PxVec3 vel(0), omega(0);
+
+ SimScene* simScene = mManager->getSceneCrab()->getSimScene();
+ PxPhysics& physics = mManager->getPhysics();
+
+ for (PxU32 leg = 0; leg < 2; leg++)
+ {
+ bool left = (leg == 0);
+#define MIRROR(X) left ? -1.0f*(X) : (X)
+ PxVec3 startPos = crabLegPos + PxVec3(MIRROR(e), 0, 0);
+
+ // create upper triangle from boxes
+ PxRigidDynamic* upperTriangle = NULL;
+ {
+ PxTransform poseA = PxTransform(PxVec3(MIRROR(a), 0, 0));
+ PxTransform poseB = PxTransform(PxVec3(MIRROR(0), b, 0));
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomA.halfExtents, &poseA);
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomB.halfExtents, &poseB, false);
+
+ Compound* upperTriangleCompound = mManager->createObject(PxTransform(startPos), vel, omega, false, mat);
+ upperTriangle = upperTriangleCompound->getPxActor();
+ upperTriangle->setAngularDamping(0.5f);
+ PxRigidBodyExt::updateMassAndInertia(*upperTriangle, density);
+
+ setShapeFlag(upperTriangle, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+ }
+
+ // create lower triangle from boxes
+ PxRigidDynamic* lowerTriangle = NULL;
+ {
+ PxTransform poseA = PxTransform(PxVec3(MIRROR(a), 0, 0));
+ //PxTransform poseD = PxTransform(PxVec3(MIRROR(0), -d, 0));
+ PxTransform poseD = PxTransform(PxVec3(MIRROR(0), -d, 0), PxQuat(PxHalfPi, PxVec3(0, 0, 1)));
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomA.halfExtents, &poseA);
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomD.halfExtents, &poseD, false);
+
+ Compound* lowerTriangleCompound = mManager->createObject(PxTransform(startPos + PxVec3(0, -2.0f*c, 0)), vel, omega, false, mat);
+ lowerTriangle = lowerTriangleCompound->getPxActor();
+ lowerTriangle->setAngularDamping(0.5f);
+ PxShape* shapes[2];
+
+ lowerTriangle->getShapes(shapes, 2);
+ shapes[1]->setMaterials(&mMaterial, 1);
+ PxRigidBodyExt::updateMassAndInertia(*lowerTriangle, density);
+
+ setShapeFlag(lowerTriangle, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+
+ }
+
+ // create vertical boxes to connect the triangles
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomC.halfExtents);
+ Compound* verticalBox0Compound = mManager->createObject(PxTransform(startPos + PxVec3(0, -c, 0)), vel, omega, false, mat);
+ PxRigidDynamic* verticalBox0 = verticalBox0Compound->getPxActor();
+ PxRigidBodyExt::updateMassAndInertia(*verticalBox0, 10.f);
+
+ setShapeFlag(verticalBox0, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+
+ simScene->getCompoundCreator()->createBox(2.f*boxGeomC.halfExtents);
+ Compound* verticalBox1Compound = mManager->createObject(PxTransform(startPos + PxVec3(MIRROR(2.0f*a), -c, 0)), vel, omega, false, mat);
+ PxRigidDynamic* verticalBox1 = verticalBox1Compound->getPxActor();
+ PxRigidBodyExt::updateMassAndInertia(*verticalBox1, 10.f);
+
+ setShapeFlag(verticalBox1, PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+
+
+ // disable gravity
+ /*upperTriangle->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+ lowerTriangle->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+ verticalBox0->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);
+ verticalBox1->setActorFlag(PxActorFlag::eDISABLE_GRAVITY, true);*/
+
+ // set mass
+ PxRigidBodyExt::setMassAndUpdateInertia(*upperTriangle, mass);
+ PxRigidBodyExt::setMassAndUpdateInertia(*lowerTriangle, mass);
+ PxRigidBodyExt::setMassAndUpdateInertia(*verticalBox0, mass);
+ PxRigidBodyExt::setMassAndUpdateInertia(*verticalBox1, mass);
+
+ // turn off collision upper triangle and vertical boxes
+ setShapeFlag(upperTriangle, PxShapeFlag::eSIMULATION_SHAPE, false);
+ setShapeFlag(verticalBox0, PxShapeFlag::eSIMULATION_SHAPE, false);
+ setShapeFlag(verticalBox1, PxShapeFlag::eSIMULATION_SHAPE, false);
+
+ // d6 joint in lower corner of upper triangle
+
+ PxD6Joint* jointD6 = PxD6JointCreate(physics,
+ mainBody, PxTransform(PxVec3(MIRROR(e), 0, 0) + localPos, PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ upperTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+
+ // 4 d6 joints to connect triangles
+
+ jointD6 = PxD6JointCreate(physics,
+ upperTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ verticalBox0, PxTransform(PxVec3(0, c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+
+ jointD6 = PxD6JointCreate(physics,
+ upperTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ verticalBox1, PxTransform(PxVec3(0, c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+
+ jointD6 = PxD6JointCreate(physics,
+ lowerTriangle, PxTransform(PxVec3(0, 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ verticalBox0, PxTransform(PxVec3(0, -c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+ //mJoints.push_back(jointD6);
+
+ jointD6 = PxD6JointCreate(physics,
+ lowerTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))),
+ verticalBox1, PxTransform(PxVec3(0, -c, 0), PxQuat(-PxHalfPi, PxVec3(0, 1, 0))));
+
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+ // 2 distance constraints to connect motor with the triangles
+ PxTransform motorTransform = PxTransform(motorAttachmentPos);
+ PxReal dist0 = PxSqrt((2.0f*b - n)*(2.0f*b - n) + (e - m)*(e - m));
+ PxReal dist1 = PxSqrt((2.0f*c + n)*(2.0f*c + n) + (e - m)*(e - m));
+
+ PxDistanceJoint* distJoint0 = PxDistanceJointCreate(physics, upperTriangle, PxTransform(PxVec3(0, 2.0f*b, 0)), motor, motorTransform);
+
+ // set min & max distance to dist0
+ distJoint0->setMaxDistance(dist0);
+ distJoint0->setMinDistance(dist0);
+ // setup damping & spring
+ //distJoint0->setDamping(0.1f);
+ //distJoint0->setStiffness(100.0f);
+ distJoint0->setDamping(0.2f);
+ distJoint0->setStiffness(500.0f);
+ distJoint0->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
+
+ /*
+ jointD6 = PxD6JointCreate(physics, upperTriangle, PxTransform(PxVec3(0, 2.0f*b, 0)), motor, motorTransform);
+ jointD6->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+ jointD6->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+ jointD6->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+ jointD6->setMotion(PxD6Axis::eX, PxD6Motion::eLIMITED);
+ jointD6->setMotion(PxD6Axis::eY, PxD6Motion::eLIMITED);
+ jointD6->setMotion(PxD6Axis::eZ, PxD6Motion::eLIMITED);
+ jointD6->setLinearLimit(PxJointLinearLimit(dist0, PxSpring(100.f, 0.1f)));
+ mJoints.push_back(jointD6);*/
+
+
+ PxDistanceJoint* distJoint1 = PxDistanceJointCreate(physics, lowerTriangle, PxTransform(PxVec3(0, 0, 0)), motor, motorTransform);
+
+ // set min & max distance to dist0
+ distJoint1->setMaxDistance(dist1);
+ distJoint1->setMinDistance(dist1);
+ // setup damping & spring
+ /* distJoint1->setDamping(0.1f);
+ distJoint1->setStiffness(100.0f);*/
+ distJoint1->setDamping(0.2f);
+ distJoint1->setStiffness(500.0f);
+ distJoint1->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
+
+ /*jointD6 = PxD6JointCreate(physics, lowerTriangle, PxTransform(PxVec3(0, 0, 0)), motor, motorTransform);
+ mJoints.push_back(jointD6);*/
+
+ // one distance joint to ensure that the vertical boxes do not get stuck if they cross the diagonal.
+ PxReal halfDiagDist = PxSqrt(a*a + c*c);
+ PxDistanceJoint* noFlip = PxDistanceJointCreate(physics, lowerTriangle, PxTransform(PxVec3(MIRROR(2.0f*a), 0, 0)), upperTriangle, PxTransform(PxVec3(0)));
+
+ // set min & max distance to dist0
+ noFlip->setMaxDistance(2.0f * (a + c));
+ noFlip->setMinDistance(halfDiagDist);
+ // setup damping & spring
+ noFlip->setDamping(1.0f);
+ noFlip->setStiffness(100.0f);
+ noFlip->setDistanceJointFlags(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED | PxDistanceJointFlag::eMIN_DISTANCE_ENABLED | PxDistanceJointFlag::eSPRING_ENABLED);
+ }
+}
+
+
+
+void Crab::update(PxReal dt)
+{
+ PxReal maxVelocity = 16.0f;
+ PxReal velDamping = 0.8f;
+
+ flushAccelerationBuffer();
+
+ for (PxU32 i = 0; i < 2; i++)
+ {
+ /*PxReal prevVelocity = mMotorJoint[i]->getDriveVelocity();
+ PxReal velocityChange = mAcceleration[i] ? mAcceleration[i] * dt : -prevVelocity*velDamping*dt;
+ PxReal newVelocity = PxClamp(prevVelocity + velocityChange, -maxVelocity, maxVelocity);
+ mMotorJoint[i]->setDriveVelocity(newVelocity);*/
+
+ PxVec3 linear, angular;
+ mMotorJoint[i]->getDriveVelocity(linear, angular);
+ PxReal prevVelocity = -angular.x;
+ PxReal velocityChange = mAcceleration[i] ? mAcceleration[i] * dt : -prevVelocity*velDamping*dt;
+ PxReal newVelocity = PxClamp(prevVelocity + velocityChange, -maxVelocity, maxVelocity);
+ mMotorJoint[i]->setDriveVelocity(linear, PxVec3(-newVelocity, 0.f, 0.f));
+
+ if (mAcceleration[i] != 0.0f)
+ mCrabBody->wakeUp();
+
+ mAcceleration[i] = 0;
+ }
+
+ // add up elapsed time
+ mAccumTime += dt;
+
+ {
+ mElapsedTime = mAccumTime;
+ mAccumTime = 0;
+ }
+}
+
+void Crab::run()
+{
+ scanForObstacles();
+ updateState();
+}
+
+
+void Crab::setAcceleration(PxReal leftAcc, PxReal rightAcc)
+{
+ mAccelerationBuffer[0] = -leftAcc;
+ mAccelerationBuffer[1] = -rightAcc;
+}
+
+
+void Crab::flushAccelerationBuffer()
+{
+ mAcceleration[0] = mAccelerationBuffer[0];
+ mAcceleration[1] = mAccelerationBuffer[1];
+}
+
+void Crab::scanForObstacles()
+{
+ if (mCrabState != CrabState::eWAITING)
+ {
+ if (mUpdateFrequency == 0)
+ {
+ mUpdateFrequency = UPDATE_FREQUENCY_RESET;
+ PxSceneReadLock scopedLock(mManager->getScene());
+
+ PxTransform crabPose = mCrabBody->getGlobalPose();
+ PxVec3 rayStart[2] = { PxVec3(2.0f, 0.0f, 0.0f), PxVec3(-2.0f, 0.0f, 0.0f) };
+ rayStart[0] = crabPose.transform(rayStart[0]);
+ rayStart[1] = crabPose.transform(rayStart[1]);
+ PxReal rayDist = 100.0f;
+
+ PxShape* shape;
+ mCrabBody->getShapes(&shape, 1);
+
+ PxBoxGeometry boxGeom;
+ shape->getBoxGeometry(boxGeom);
+
+ PxVec3 forward = crabPose.rotate(PxVec3(0, 0, 1));
+ PxVec3 sideDir = (forward.cross(PxVec3(0, 1, 0)) - PxVec3(0, 0.4f, 0)).getNormalized();
+
+ // setup raycasts
+ // 3 front & 3 back
+ for (PxU32 j = 0; j < 2; j++)
+ {
+ //PxVec3 rayDir = crabPose.rotate(PxVec3(j ? -1.0f : 1.0f, 0, 0));
+ PxVec3 rayDir = j ? -sideDir : sideDir;
+ PxQuat rotY = PxQuat(0.4f, PxVec3(0, 1, 0));
+ rayDir = rotY.rotateInv(rayDir);
+ for (PxU32 i = 0; i < 3; i++)
+ {
+ rayDir.normalize();
+ //mSqRayBuffer->mBatchQuery->raycast(rayStart[j], rayDir, rayDist);
+ mSqSweepBuffer->mBatchQuery->sweep(boxGeom, crabPose, rayDir, rayDist, 0, PxHitFlag::eDEFAULT,
+ PxQueryFilterData(shape->getQueryFilterData(), PxQueryFlags(PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER)));
+ rayDir = rotY.rotate(rayDir);
+ }
+ }
+
+ mSqSweepBuffer->mBatchQuery->execute();
+ for (PxU32 i = 0; i < mSqSweepBuffer->mQueryResultSize; i++)
+ {
+ PxSweepQueryResult& result = mSqSweepBuffer->mSweepResults[i];
+ if (result.queryStatus == PxBatchQueryStatus::eSUCCESS && result.getNbAnyHits() == 1)
+ {
+ const PxSweepHit& hit = result.getAnyHit(0);
+ mDistances[i] = hit.distance;
+
+ // don't see flat terrain as wall
+ //SampleRenderer::RendererColor rayColor(0, 0, 255);
+ //PxReal angle = hit.normal.dot(crabPose.q.rotate(PxVec3(0, 1, 0)));
+ PxReal angle = hit.normal.dot(PxVec3(0, 1, 0));
+ if (angle > 0.92f) // = 11.5 degree difference
+ {
+ mDistances[i] = rayDist;
+ // rayColor = SampleRenderer::RendererColor(0, 255, 0);
+ }
+ }
+ else
+ mDistances[i] = rayDist;
+ }
+ }
+
+ mUpdateFrequency--;
+ }
+}
+
+void Crab::initState(CrabState::Enum state)
+{
+ //if the original crabstate is waitting, we need to do scan for obstacles. Otherwise, we have done the scan for obstacles before we updateState
+ if (mCrabState == CrabState::eWAITING)
+ scanForObstacles();
+ mCrabState = state;
+ mStateTime = gDefaultStateTime[mCrabState];
+}
+
+void Crab::updateState()
+{
+ // update remaining time in current state
+ // transition if needed
+ mStateTime -= mElapsedTime;
+ mElapsedTime = 0;
+ if (mStateTime <= 0.0f)
+ {
+ initState(CrabState::Enum((rand()%(CrabState::eNUM_STATES-1))+1));
+ }
+
+ PxTransform crabPose;
+ {
+ PxSceneReadLock scopedLock(mManager->getScene());
+ crabPose = mCrabBody->getGlobalPose();
+ }
+
+
+ PxReal leftAcc = 0, rightAcc = 0;
+ // compute fwd and bkwd distances
+ static const PxReal minDist = 10.0f;
+ static const PxReal fullSpeedDist = 50.0f;
+ static const PxReal recipFullSpeedDist = 1.0f / fullSpeedDist;
+ PxReal fDist = 0, bDist = 0;
+ fDist = PxMin(mDistances[0], PxMin(mDistances[1], mDistances[2]));
+ bDist = PxMin(mDistances[3], PxMin(mDistances[4], mDistances[5]));
+
+ // handle states
+ if (mCrabState == CrabState::eMOVE_FWD)
+ {
+ if (fDist < minDist && fDist < bDist)
+ {
+ initState(CrabState::eMOVE_BKWD);
+ }
+ else
+ {
+ leftAcc = PxMin(fullSpeedDist, mDistances[0])*recipFullSpeedDist*2.0f - 1.0f;
+ rightAcc = PxMin(fullSpeedDist, mDistances[2])*recipFullSpeedDist*2.0f - 1.0f;
+ leftAcc *= 3.0f;
+ rightAcc *= 3.0f;
+ }
+ }
+ else if (mCrabState == CrabState::eMOVE_BKWD)
+ {
+ if (bDist < minDist && bDist < fDist)
+ {
+ // find rotation dir, where we have some free space
+ bool rotateLeft = mDistances[0] < mDistances[2];
+ initState(rotateLeft ? CrabState::eROTATE_LEFT : CrabState::eROTATE_RIGHT);
+ }
+ else
+ {
+ leftAcc = -(PxMin(fullSpeedDist, mDistances[5])*recipFullSpeedDist*2.0f - 1.0f);
+ rightAcc = -(PxMin(fullSpeedDist, mDistances[3])*recipFullSpeedDist*2.0f - 1.0f);
+ leftAcc *= 3.0f;
+ rightAcc *= 3.0f;
+ }
+ }
+ else if (mCrabState == CrabState::eROTATE_LEFT)
+ {
+ leftAcc = -3.0f;
+ rightAcc = 3.0f;
+ if (fDist > minDist)
+ {
+ initState(CrabState::eMOVE_FWD);
+ }
+ }
+ else if (mCrabState == CrabState::eROTATE_RIGHT)
+ {
+ leftAcc = 3.0f;
+ rightAcc = -3.0f;
+ if (fDist > minDist)
+ {
+ initState(CrabState::eMOVE_FWD);
+ }
+ }
+ else if (mCrabState == CrabState::ePANIC)
+ {
+
+ }
+ else if (mCrabState == CrabState::eWAITING)
+ {
+ // have a break
+ }
+
+ // change acceleration
+ setAcceleration(leftAcc, rightAcc);
+
+}
+
+PxQueryHitType::Enum myFilterShader(
+ PxFilterData queryFilterData, PxFilterData objectFilterData,
+ const void* constantBlock, PxU32 constantBlockSize,
+ PxHitFlags& hitFlags)
+{
+ if (objectFilterData.word0 == 128 || objectFilterData.word3 == queryFilterData.word3)
+ return PxQueryHitType::eNONE;
+ return PxQueryHitType::eBLOCK;
+}
+
+SqRayBuffer::SqRayBuffer(Crab* crab, PxU32 numRays, PxU32 numHits) :
+mQueryResultSize(numRays), mHitSize(numHits)
+{
+ mCrab = crab;
+ mOrigAddresses[0] = malloc(mQueryResultSize*sizeof(PxRaycastQueryResult) + 15);
+ mOrigAddresses[1] = malloc(mHitSize*sizeof(PxRaycastHit) + 15);
+
+ mRayCastResults = reinterpret_cast<PxRaycastQueryResult*>((size_t(mOrigAddresses[0]) + 15) & ~15);
+ mRayCastHits = reinterpret_cast<PxRaycastHit*>((size_t(mOrigAddresses[1]) + 15)& ~15);
+
+ PxBatchQueryDesc batchQueryDesc(mQueryResultSize, 0, 0);
+ batchQueryDesc.queryMemory.userRaycastResultBuffer = mRayCastResults;
+ batchQueryDesc.queryMemory.userRaycastTouchBuffer = mRayCastHits;
+ batchQueryDesc.queryMemory.raycastTouchBufferSize = mHitSize;
+ batchQueryDesc.preFilterShader = myFilterShader;
+
+ mBatchQuery = mCrab->getManager()->getScene().createBatchQuery(batchQueryDesc);
+}
+
+SqRayBuffer::~SqRayBuffer()
+{
+ mBatchQuery->release();
+ free(mOrigAddresses[0]);
+ free(mOrigAddresses[1]);
+}
+
+void SqRayBuffer::setScene(PxScene* scene)
+{
+ PxBatchQueryDesc batchQueryDesc(mQueryResultSize, 0, 0);
+ batchQueryDesc.queryMemory.userRaycastResultBuffer = mRayCastResults;
+ batchQueryDesc.queryMemory.userRaycastTouchBuffer = mRayCastHits;
+ batchQueryDesc.queryMemory.raycastTouchBufferSize = mHitSize;
+ batchQueryDesc.preFilterShader = myFilterShader;
+
+ mBatchQuery = scene->createBatchQuery(batchQueryDesc);
+}
+
+SqSweepBuffer::SqSweepBuffer(Crab* crab, PxU32 numRays, PxU32 numHits) :
+mQueryResultSize(numRays), mHitSize(numHits)
+{
+ mCrab = crab;
+ mOrigAddresses[0] = malloc(mQueryResultSize*sizeof(PxSweepQueryResult) + 15);
+ mOrigAddresses[1] = malloc(mHitSize*sizeof(PxSweepHit) + 15);
+
+ mSweepResults = reinterpret_cast<PxSweepQueryResult*>((size_t(mOrigAddresses[0]) + 15) & ~15);
+ mSweepHits = reinterpret_cast<PxSweepHit*>((size_t(mOrigAddresses[1]) + 15)& ~15);
+
+ PxBatchQueryDesc batchQueryDesc(0, mQueryResultSize, 0);
+ batchQueryDesc.queryMemory.userSweepResultBuffer = mSweepResults;
+ batchQueryDesc.queryMemory.userSweepTouchBuffer = mSweepHits;
+ batchQueryDesc.queryMemory.sweepTouchBufferSize = mHitSize;
+ batchQueryDesc.preFilterShader = myFilterShader;
+
+ mBatchQuery = mCrab->getManager()->getScene().createBatchQuery(batchQueryDesc);
+}
+
+void SqSweepBuffer::setScene(PxScene* scene)
+{
+ PxBatchQueryDesc batchQueryDesc(0, mQueryResultSize, 0);
+ batchQueryDesc.queryMemory.userSweepResultBuffer = mSweepResults;
+ batchQueryDesc.queryMemory.userSweepTouchBuffer = mSweepHits;
+ batchQueryDesc.queryMemory.sweepTouchBufferSize = mHitSize;
+ batchQueryDesc.preFilterShader = myFilterShader;
+
+ mBatchQuery = scene->createBatchQuery(batchQueryDesc);
+}
+
+SqSweepBuffer::~SqSweepBuffer()
+{
+ mBatchQuery->release();
+ free(mOrigAddresses[0]);
+ free(mOrigAddresses[1]);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/Crab.h b/KaplaDemo/samples/sampleViewer3/Crab.h
new file mode 100644
index 00000000..829abe8e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Crab.h
@@ -0,0 +1,190 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef CRAB_H
+#define CRAB_H
+
+#include "foundation/Px.h"
+#include "foundation/PxSimpleTypes.h"
+#include "common/PxPhysXCommonConfig.h"
+#include "task/PxTask.h"
+#include <vector>
+
+#define UPDATE_FREQUENCY_RESET 10
+
+
+struct CrabState
+{
+ enum Enum
+ {
+ eWAITING,
+ eMOVE_FWD,
+ eMOVE_BKWD,
+ eROTATE_LEFT,
+ eROTATE_RIGHT,
+ ePANIC,
+ eNUM_STATES,
+ };
+};
+
+
+
+namespace physx
+{
+ class PxRigidDynamic;
+ class PxRevoluteJoint;
+ class PxJoint;
+ class PxScene;
+}
+
+// Edge Labels for Theo Jansen's Mechanism
+// _.
+// ,' | m
+// ,' |2b .....
+// ,' 2a | e |n
+// +-------+---------+
+// | |
+// | |2c
+// | |
+// +-------+
+// `. |
+// `. |2d
+// `. |
+// `|
+
+struct LegParameters
+{
+ physx::PxReal a; // half x-dim leg
+ physx::PxReal b; // half height upper triangle
+ physx::PxReal c; // half height distance joints (square)
+ physx::PxReal d; // half height lower triangle
+ physx::PxReal e; // x distance from main body centre
+ physx::PxReal m; // half extent of the motor box
+ physx::PxReal n; // y offset of the motor from the main body centre
+};
+
+class Crab;
+class CrabManager;
+
+struct SqRayBuffer
+{
+ SqRayBuffer(Crab* crab, physx::PxU32 numRays, physx::PxU32 numHits);
+ ~SqRayBuffer();
+
+ Crab* mCrab;
+ physx::PxBatchQuery* mBatchQuery;
+
+ physx::PxRaycastQueryResult* mRayCastResults;
+ physx::PxRaycastHit* mRayCastHits;
+
+ physx::PxU32 mQueryResultSize;
+ physx::PxU32 mHitSize;
+ void* mOrigAddresses[2];
+
+ void setScene(physx::PxScene* scene);
+private:
+ SqRayBuffer& operator=(const SqRayBuffer&);
+};
+
+struct SqSweepBuffer
+{
+ SqSweepBuffer(Crab* crab, physx::PxU32 numRays, physx::PxU32 numHits);
+ ~SqSweepBuffer();
+
+ Crab* mCrab;
+ physx::PxBatchQuery* mBatchQuery;
+
+ physx::PxSweepQueryResult* mSweepResults;
+ physx::PxSweepHit* mSweepHits;
+
+ physx::PxU32 mQueryResultSize;
+ physx::PxU32 mHitSize;
+ void* mOrigAddresses[2];
+
+ void setScene(physx::PxScene* scene);
+private:
+ SqSweepBuffer& operator=(const SqSweepBuffer&);
+};
+
+class Crab
+{
+public:
+
+ Crab(CrabManager* crabManager, physx::PxU32 updateFrequency);
+ ~Crab();
+
+ void update(physx::PxReal dt);
+ void setAcceleration(physx::PxReal leftAcc, physx::PxReal rightAcc);
+ void flushAccelerationBuffer();
+
+ PX_INLINE const physx::PxRigidDynamic* getCrabBody() const { return mCrabBody; }
+ PX_INLINE physx::PxRigidDynamic* getCrabBody() { return mCrabBody; }
+
+
+ void run();
+
+ void setScene(physx::PxScene* scene);
+
+
+
+ void initMembers();
+ Crab* create(const physx::PxVec3& _crabPos, const physx::PxReal crabDepth, const physx::PxReal scale, const physx::PxReal legMass, const physx::PxU32 numLegs);
+
+ physx::PxVec3 getPlaceOnFloor(physx::PxVec3 pos);
+ void createLeg(physx::PxRigidDynamic* mainBody, physx::PxVec3 localPos, physx::PxReal mass, const LegParameters& params, physx::PxReal scale, physx::PxRigidDynamic* motor, physx::PxVec3 motorAttachmentPos);
+ void scanForObstacles();
+ void updateState();
+ void initState(CrabState::Enum state);
+
+ void setManager(CrabManager* crabManager) { mManager = crabManager; }
+ CrabManager* getManager(){ return mManager; }
+
+private:
+ CrabManager* mManager;
+ physx::PxRigidDynamic* mCrabBody;
+ //physx::PxRevoluteJoint* mMotorJoint[2];
+ physx::PxD6Joint* mMotorJoint[2];
+ physx::PxMaterial* mMaterial;
+
+ physx::PxReal mAcceleration[2];
+ //SqRayBuffer* mSqRayBuffer;
+ SqSweepBuffer* mSqSweepBuffer;
+
+ physx::PxReal mLegHeight;
+
+ CrabState::Enum mCrabState;
+ physx::PxReal mStateTime;
+ physx::PxReal mDistances[10];
+ physx::PxReal mAccumTime;
+ physx::PxReal mElapsedTime;
+ physx::PxReal mAccelerationBuffer[2];
+ physx::PxU32 mUpdateFrequency;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/CrabManager.cpp b/KaplaDemo/samples/sampleViewer3/CrabManager.cpp
new file mode 100644
index 00000000..fa7649e9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/CrabManager.cpp
@@ -0,0 +1,159 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "PxPhysicsAPI.h"
+#include "extensions/PxExtensionsAPI.h"
+#include "SceneCrab.h"
+#include "Crab.h"
+#include "CrabManager.h"
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include <GL/glut.h>
+
+#include "PxTkStream.h"
+#include "PxTkFile.h"
+#include "CmTask.h"
+using namespace PxToolkit;
+
+
+CrabManager::CrabManager() : mSceneCrab(NULL), mCrabs(NULL), mCompletionTask(mSync)
+{
+ mSync.set();
+}
+
+CrabManager::~CrabManager()
+{
+ for (PxU32 i = 0; i < mCrabs.size(); ++i)
+ {
+ mCrabs[i]->~Crab();
+ PX_FREE(mCrabs[i]);
+ }
+
+ mCrabs.clear();
+
+ for (PxU32 i = 0; i < mUpdateStateTask.size(); ++i)
+ {
+ mUpdateStateTask[i]->~CrabUpdateStateTask();
+ PX_FREE(mUpdateStateTask[i]);
+ }
+
+ mUpdateStateTask.clear();
+}
+
+PxScene& CrabManager::getScene()
+{
+ return mSceneCrab->getScene();
+}
+
+PxPhysics& CrabManager::getPhysics()
+{
+ return mSceneCrab->getPhysics();
+}
+
+void CrabManager::setSceneCrab(SceneCrab* sceneCrab)
+{
+ mSceneCrab = sceneCrab;
+}
+
+void CrabManager::setScene(PxScene* scene)
+{
+ for (PxU32 a = 0; a < mCrabs.size(); ++a)
+ {
+ mCrabs[a]->setScene(scene);
+ }
+}
+
+SceneCrab* CrabManager::getSceneCrab()
+{
+ return mSceneCrab;
+}
+
+Compound* CrabManager::createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader)
+{
+ return mSceneCrab->createObject(pose, vel, omega, particles, mat, useSecondaryPattern, shader,1,1);
+}
+
+void CrabManager::initialize(const PxU32 nbCrabs)
+{
+ mCrabs.reserve(nbCrabs);
+}
+
+void CrabManager::createCrab(const PxVec3& crabPos, const physx::PxReal crabDepth, const PxReal scale, const PxReal legMass, const PxU32 numLegs)
+{
+ PxU32 idx = mCrabs.size();
+ mCrabs.pushBack(PX_PLACEMENT_NEW(PX_ALLOC(sizeof(Crab), PX_DEBUG_EXP("Crabs")), Crab)(this, idx%UPDATE_FREQUENCY_RESET));
+ mCrabs[idx]->create(crabPos, crabDepth, scale, legMass, numLegs);
+ PxU32 taskSize = mUpdateStateTask.size();
+ if (taskSize == 0 || ((mCrabs.size() - mUpdateStateTask[taskSize - 1]->mStartIndex) == 64))
+ {
+ //Create a new task...
+ mUpdateStateTask.pushBack(PX_PLACEMENT_NEW(PX_ALLOC(sizeof(CrabUpdateStateTask), PX_DEBUG_EXP("CrabUpdateTask")), CrabUpdateStateTask)(this, idx, mCrabs.size()));
+ }
+ mUpdateStateTask[mUpdateStateTask.size() - 1]->mEndIndex = mCrabs.size();
+}
+
+void CrabManager::update(const PxReal dt)
+{
+ mSync.reset();
+ PxSceneWriteLock scopedLock(getScene());
+ PxTaskManager* manager = getScene().getTaskManager();
+
+ mCompletionTask.setContinuation(*manager, NULL);
+
+ for (PxU32 i = 0; i < mCrabs.size(); ++i)
+ {
+ mCrabs[i]->update(dt);
+ }
+
+ for (PxU32 i = 0; i < mUpdateStateTask.size(); ++i)
+ {
+ mUpdateStateTask[i]->setContinuation(&mCompletionTask);
+ mUpdateStateTask[i]->removeReference();
+ }
+
+ mCompletionTask.removeReference();
+
+ //mSync.wait();
+}
+
+void CrabManager::syncWork()
+{
+ mSync.wait();
+}
+
+void CrabUpdateStateTask::runInternal()
+{
+ Crab** crab = mCrabManager->getCrabs();
+
+ for (PxU32 i = mStartIndex; i < mEndIndex; ++i)
+ {
+ crab[i]->run();
+ }
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/CrabManager.h b/KaplaDemo/samples/sampleViewer3/CrabManager.h
new file mode 100644
index 00000000..f76ef6cf
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/CrabManager.h
@@ -0,0 +1,126 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef CRAB_MANAGER_H
+#define CRAB_MANAGER_H
+
+#include "foundation/Px.h"
+#include "foundation/PxSimpleTypes.h"
+#include "common/PxPhysXCommonConfig.h"
+#include "PsSync.h"
+#include "CmTask.h"
+#include "PsArray.h"
+
+class SceneCrab;
+class Crab;
+class Compound;
+struct ShaderMaterial;
+class ShaderShadow;
+class CrabManager;
+
+
+class CompletionTask : public physx::Cm::Task
+{
+ physx::shdfnd::Sync& mSync;
+
+public:
+
+ CompletionTask(physx::shdfnd::Sync& sync) : mSync(sync)
+ {
+ }
+
+ virtual void runInternal() { mSync.set(); }
+
+ virtual const char* getName() const { return "CrabCompletionTask"; }
+};
+
+class CrabUpdateStateTask : public physx::Cm::Task
+{
+public:
+ CrabManager* mCrabManager;
+ physx::PxU32 mStartIndex;
+ physx::PxU32 mEndIndex;
+
+
+ CrabUpdateStateTask(CrabManager* crabManager, const physx::PxU32 startIndex, const physx::PxU32 endIndex) :
+ mCrabManager(crabManager), mStartIndex(startIndex), mEndIndex(endIndex)
+ {
+ }
+
+ virtual void runInternal();
+
+
+ virtual const char* getName() const { return "CrabCompletionTask"; }
+};
+
+class CrabManager
+{
+public:
+ CrabManager();
+ ~CrabManager();
+
+ void initialize(const physx::PxU32 nbCrabs);
+ void setCrabScene(SceneCrab* sceneCrab) { mSceneCrab = sceneCrab; }
+
+ void createCrab(const physx::PxVec3& crabPos, const physx::PxReal crabDepth, const physx::PxReal scale, const physx::PxReal legMass, const physx::PxU32 nbLegs);
+ void update(const physx::PxReal dt);
+
+ physx::PxScene& getScene();
+ physx::PxPhysics& getPhysics();
+ //SimScene* getSimScene();
+
+ void setScene(physx::PxScene* scene);
+
+ void setSceneCrab(SceneCrab* sceneCrab);
+ SceneCrab* getSceneCrab();
+
+ Compound* createObject(const physx::PxTransform &pose, const physx::PxVec3 &vel, const physx::PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL);
+
+ void syncWork();
+ Crab** getCrabs() { return mCrabs.begin(); }
+
+
+
+private:
+
+ SceneCrab* mSceneCrab;
+ //Crab* mCrabs;
+ //physx::PxU32 mNbCrabs;
+
+ physx::shdfnd::Array<Crab*> mCrabs;
+
+ physx::shdfnd::Sync mSync;
+
+ CompletionTask mCompletionTask;
+ //CrabUpdateStateTask* mUpdateStateTask;
+ physx::shdfnd::Array<CrabUpdateStateTask*> mUpdateStateTask;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/FXAAHelper.cpp b/KaplaDemo/samples/sampleViewer3/FXAAHelper.cpp
new file mode 100644
index 00000000..cdb3d41d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FXAAHelper.cpp
@@ -0,0 +1,148 @@
+#include "FXAAHelper.h"
+#include "foundation/PxMat44.h"
+const char *computeLumaVS = STRINGIFY(
+ void main(void)
+ {
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex * 2.0 - 1.0;
+ }
+);
+
+const char *computeLumaFS = STRINGIFY(
+ uniform sampler2D imgTex;
+
+ void main (void)
+ {
+ vec4 col = texture2D(imgTex,gl_TexCoord[0].xy);
+ gl_FragColor = vec4(col.xyz, sqrt(dot(col.rgb, vec3(0.299, 0.587, 0.114))));
+ }
+);
+
+FXAAHelper::FXAAHelper( const char* resourcePath) {
+
+ char fxaaVSF[5000];
+ char fxaaFSF[5000];
+ sprintf(fxaaVSF, "%s\\fxaa.vs", resourcePath);
+ sprintf(fxaaFSF, "%s\\fxaa.fs", resourcePath);
+ computeLuma.loadShaderCode(computeLumaVS,computeLumaFS);
+ fxaa.loadShaders(fxaaVSF,fxaaFSF);
+
+
+ glUseProgram(computeLuma);
+ glUniform1i(glGetUniformLocation(computeLuma,"imgTex"),0);
+ glUseProgram(0);
+
+ glUseProgram(fxaa);
+ glUniform1i(glGetUniformLocation(fxaa,"imgWithLumaTex"),0);
+ glUseProgram(0);
+
+ glGenTextures(1,&imgTex);
+ glGenTextures(1,&imgWithLumaTex);
+ glGenTextures(1,&depthTex);
+ glGenFramebuffers(1,&FBO);
+}
+
+void FXAAHelper::Resize(int w,int h) {
+
+ Width = w;
+ Height = h;
+
+ glViewport(0,0,Width,Height);
+
+ glBindTexture(GL_TEXTURE_2D,imgTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width,Height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,imgWithLumaTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width,Height,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,depthTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT32,Width,Height,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL);
+
+
+ glUseProgram(fxaa);
+ glUniform2f(glGetUniformLocation(fxaa,"rcpFrame"), 1.0f / ((float)Width), 1.0f / ((float)Height));
+
+ glUseProgram(0);
+
+}
+void FXAAHelper::Destroy() {
+
+ computeLuma.deleteShaders();
+ fxaa.deleteShaders();
+
+ glDeleteTextures(1,&imgTex);
+ glDeleteTextures(1,&imgWithLumaTex);
+ glDeleteTextures(1,&depthTex);
+ glDeleteFramebuffers(1,&FBO);
+}
+
+void FXAAHelper::StartFXAA() {
+ glBindFramebuffer(GL_FRAMEBUFFER,FBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,imgTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,depthTex,0);
+
+ glViewport(0,0,Width,Height);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void FXAAHelper::EndFXAA(GLuint oldFBO) {
+
+
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+// if(Blur)
+// {
+ glBindFramebuffer(GL_FRAMEBUFFER,FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,imgWithLumaTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,0,0);
+
+ glClearColor(0.0f,0.0f,0.0f,0.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,imgTex);
+
+ glUseProgram(computeLuma);
+ glBegin(GL_QUADS);
+
+ glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f,0.0f); glVertex2f(1.0f,0.0f);
+ glTexCoord2f(1.0f,1.0f); glVertex2f(1.0f,1.0f);
+ glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,1.0f);
+ glEnd();
+
+ glUseProgram(0);
+
+
+ glBindFramebuffer(GL_FRAMEBUFFER,oldFBO);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,imgWithLumaTex);
+ glUseProgram(fxaa);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f,0.0f); glVertex2f(1.0f,0.0f);
+ glTexCoord2f(1.0f,1.0f); glVertex2f(1.0f,1.0f);
+ glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,1.0f);
+ glEnd();
+
+ glUseProgram(0);
+
+ glBindTexture(GL_TEXTURE_2D,0);
+ glDepthMask(GL_TRUE);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/FXAAHelper.h b/KaplaDemo/samples/sampleViewer3/FXAAHelper.h
new file mode 100644
index 00000000..55befd92
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FXAAHelper.h
@@ -0,0 +1,15 @@
+#pragma once
+#include <GL/glew.h>
+#include "Shader.h"
+
+class FXAAHelper{
+public:
+ int Width, Height;
+ Shader computeLuma, fxaa;
+ FXAAHelper(const char* resourcePath);
+ void Resize(int w, int h);
+ void StartFXAA(); // Call before rendering things
+ void EndFXAA(GLuint oldFBO); // Compute luma and then do FXAA
+ void Destroy();
+ GLuint FBO, depthTex, imgTex, imgWithLumaTex;
+};
diff --git a/KaplaDemo/samples/sampleViewer3/FileScanner.cpp b/KaplaDemo/samples/sampleViewer3/FileScanner.cpp
new file mode 100644
index 00000000..a2dc6019
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FileScanner.cpp
@@ -0,0 +1,236 @@
+#include <string.h>
+#include <float.h>
+#include "FileScanner.h"
+
+#pragma warning(disable : 4996) //deprecated warnings for string ops not necessary
+#define _CRT_SECURE_NO_DEPRECATE
+
+#define EOL 10
+
+// ------------------------------------------------------------------------------------
+FileScanner::FileScanner()
+// ------------------------------------------------------------------------------------
+{
+ f = NULL;
+ lineNr = 0;
+ pos = line;
+ strcpy(errorMessage, "");
+}
+
+// ------------------------------------------------------------------------------------
+FileScanner::~FileScanner()
+// ------------------------------------------------------------------------------------
+{
+ if (f)
+ fclose(f);
+}
+
+// ------------------------------------------------------------------------------------
+bool FileScanner::equalSymbol(const char *sym, const char *expectedSym, bool caseSensitive)
+// ------------------------------------------------------------------------------------
+{
+ if (caseSensitive)
+ return strcmp(expectedSym, sym) == 0;
+ else
+#if defined(__BCPLUSPLUS__)
+ return strcmpi(expectedSym, sym) == 0;
+#elif defined(__WXMAC__)
+ return strcasecmp(expectedSym, sym) == 0;
+#else
+ return _stricmp(expectedSym, sym) == 0;
+#endif
+}
+
+
+// ------------------------------------------------------------------------------------
+bool FileScanner::open(const char *filename)
+// ------------------------------------------------------------------------------------
+{
+ f = fopen(filename, "rb");
+ if (!f) {
+ strcpy(errorMessage, "file open error");
+ return false;
+ }
+ fgets(line, maxLineLen, f);
+ pos = line;
+ lineNr = 1;
+ return true;
+}
+
+// ------------------------------------------------------------------------------------
+void FileScanner::close()
+// ------------------------------------------------------------------------------------
+{
+ if (f) fclose(f);
+ f = NULL;
+}
+
+// ------------------------------------------------------------------------------------
+void FileScanner::getNextLine()
+// ------------------------------------------------------------------------------------
+{
+ fgets(line, maxLineLen, f);
+ pos = line;
+ lineNr++;
+}
+
+bool singleCharSymbol(char ch)
+{
+ if (ch == '<' || ch == '>') return true;
+ if (ch == '(' || ch == ')') return true;
+ if (ch == '{' || ch == '}') return true;
+ if (ch == '[' || ch == ']') return true;
+ if (ch == '/' || ch == '=') return true;
+ return false;
+}
+
+bool separatorChar(char ch)
+{
+ if ((unsigned char)ch <= ' ') return true;
+ if (ch == ',') return true;
+ if (ch == ';') return true;
+ return false;
+}
+
+// ------------------------------------------------------------------------------------
+void FileScanner::getSymbol(char *sym)
+// ------------------------------------------------------------------------------------
+{
+ while (!feof(f)) {
+ while (!feof(f) && separatorChar(*pos)) { // separators
+ if (*pos == EOL)
+ getNextLine();
+ else pos++;
+ }
+ if (!feof(f) && *pos == '/' && *(pos+1) == '/') // line comment
+ getNextLine();
+ else if (!feof(f) && *pos == '/' && *(pos+1) == '*') { // long comment
+ pos += 2;
+ while (!feof(f) && (*pos != '*' || *(pos+1) != '/')) {
+ if (*pos == EOL)
+ getNextLine();
+ else pos++;
+ }
+ if (!feof(f)) pos += 2;
+ }
+ else break;
+ }
+
+ char *cp = sym;
+ if (*pos == '\"' && !feof(f)) { // read string
+ pos++;
+ while (!feof(f) && *pos != '\"' && *pos != EOL) {
+ *cp++ = *pos++;
+ }
+ if (!feof(f) && *pos == '\"') pos++; // override <">
+ }
+ else { /* read other symbol */
+ if (!feof(f)) {
+ if (singleCharSymbol(*pos)) // single char symbol
+ *cp++ = *pos++;
+ else { // multiple char symbol
+ while (!separatorChar(*pos) && !singleCharSymbol(*pos) && !feof(f)) {
+ *cp++ = *pos++;
+ }
+ }
+ }
+ }
+ *cp = 0;
+}
+
+
+// ------------------------------------------------------------------------------------
+bool FileScanner::checkSymbol(const char *expectedSym, bool caseSensitive)
+// ------------------------------------------------------------------------------------
+{
+ static char sym[maxLineLen+1];
+ getSymbol(sym);
+
+ if (!equalSymbol(sym, expectedSym, caseSensitive)) {
+ sprintf(errorMessage, "Parse error line %i, position %i: %s expected, %s read\n",
+ lineNr, (int)(pos - line), expectedSym, sym);
+ return false;
+ }
+ return true;
+}
+
+/* ------------------------------------------------------------------- */
+bool FileScanner::getIntSymbol(int &i)
+/* ------------------------------------------------------------------- */
+{
+ static char sym[maxLineLen+1];
+ getSymbol(sym);
+
+ int n = 0;
+ for (int k = 0; k < (int)strlen(sym); k++) {
+ if ((sym[k] >= '0') && (sym[k] <= '9')) n++;
+ if ((sym[k] == '+') || (sym[k] == '-')) n++;
+ }
+ if (n < (int)strlen(sym)) {
+ setErrorMessage("integer expected");
+ return false;
+ }
+ sscanf(sym,"%i",&i);
+ return true;
+}
+
+
+/* ------------------------------------------------------------------- */
+bool FileScanner::getFloatSymbol(float &r)
+/* ------------------------------------------------------------------- */
+{
+ static char sym[maxLineLen+1];
+ getSymbol(sym);
+
+#if defined(__BCPLUSPLUS__)
+ if (strcmpi(sym, "infinity") == 0) {
+#elif defined(__WXMAC__)
+ if (strcasecmp(sym, "infinity") == 0) {
+#else
+ if (_stricmp(sym, "infinity") == 0) {
+#endif
+ r = FLT_MAX;
+ return true;
+ }
+#if defined(__BCPLUSPLUS__)
+ if (strcmpi(sym, "-infinity") == 0) {
+#elif defined(__WXMAC__)
+ if (strcasecmp(sym, "-�infinity") == 0) {
+#else
+ if (_stricmp(sym, "-infinity") == 0) {
+#endif
+ r = -FLT_MAX;
+ return true;
+ }
+
+ int n = 0;
+ for (int k = 0; k < (int)strlen(sym); k++) {
+ if ((sym[k] >= '0') && (sym[k] <= '9')) n++;
+ if ((sym[k] == '+') || (sym[k] == '-')) n++;
+ if ((sym[k] == '.') || (sym[k] == 'e')) n++;
+ }
+ if (n < (int)strlen(sym)) {
+ setErrorMessage("float expected");
+ return false;
+ }
+ sscanf(sym,"%f",&r);
+ return true;
+}
+
+/* ------------------------------------------------------------------- */
+bool FileScanner::getBinaryData(void *buffer, int size)
+{
+ size_t num = fread(buffer, 1, size, f);
+ getNextLine();
+ return num == size;
+
+}
+
+/* ------------------------------------------------------------------- */
+void FileScanner::setErrorMessage(char *msg)
+/* ------------------------------------------------------------------- */
+{
+ sprintf(errorMessage, "parse error line %i, position %i: %s",
+ lineNr, (int)(pos - line), msg);
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/FileScanner.h b/KaplaDemo/samples/sampleViewer3/FileScanner.h
new file mode 100644
index 00000000..2ba875aa
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FileScanner.h
@@ -0,0 +1,64 @@
+#ifndef FILESCANNER_H
+#define FILESCANNER_H
+
+#include <stdio.h>
+
+#define EOL 10
+#define MAX_BONDS 5
+
+#ifdef __BCPLUSPLUS__
+#define STRCMPI(s, t) (strcmpi(s, t))
+#elif defined (__WXWINDOWS25__) && defined (__WXMAC__) && defined (__WXMAC_XCODE__)
+#define STRCMPI(s, t) (strcasecmp(s, t))
+#else
+#define STRCMPI(s, t) (_stricmp(s, t))
+#endif
+
+#ifdef __BCPLUSPLUS__
+#define STRNCMPI(s, t, m) (strncmpi(s, t, m))
+#elif defined (__WXWINDOWS25__) && defined (__WXMAC__) && defined (__WXMAC_XCODE__)
+#define STRNCMPI(s, t, m) (strncasecmp(s, t, m))
+#else
+#define STRNCMPI(s, t, m) (_strnicmp(s, t, m))
+#endif
+
+
+// ------------------------------------------------------------------------------------
+class FileScanner {
+// ------------------------------------------------------------------------------------
+public:
+ FileScanner();
+ ~FileScanner();
+
+ bool open(const char *filename);
+ void close();
+
+ void getSymbol(char *sym);
+ bool checkSymbol(const char *expectedSym, bool caseSensitive = false);
+ bool getIntSymbol(int &i);
+ bool getFloatSymbol(float &r);
+
+ bool getBinaryData(void *buffer, int size); // must start after newline
+
+ int getLineNr() const { return lineNr; }
+ int getPositionNr() const { return (int)(pos - line); }
+
+ bool endReached() const { if (feof(f)) return true; else return false; }
+
+ void setErrorMessage(char *msg);
+
+ char errorMessage[256];
+
+ // ------------------------------------------------------
+ static bool equalSymbol(const char *sym, const char *expectedSym, bool caseSensitive = false);
+ static const int maxLineLen = 1024;
+
+private:
+ void getNextLine();
+ FILE *f;
+ int lineNr;
+ char line[maxLineLen+1];
+ char *pos;
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Actor.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Actor.cpp
new file mode 100644
index 00000000..54adbe25
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Actor.cpp
@@ -0,0 +1,21 @@
+#include "Actor.h"
+
+#include <foundation/PxMat44.h>
+#include "PxRigidBodyExt.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxShape.h"
+
+#include "SimScene.h"
+#include "Compound.h"
+
+Actor::Actor(base::SimScene* scene):
+ base::Actor(scene)
+{
+
+}
+
+Actor::~Actor()
+{
+
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Actor.h b/KaplaDemo/samples/sampleViewer3/Fracture/Actor.h
new file mode 100644
index 00000000..ef2a3522
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Actor.h
@@ -0,0 +1,25 @@
+#ifndef RT_ACTOR_H
+#define RT_ACTOR_H
+
+//#include <PxFoundation.h>
+
+#include "ActorBase.h"
+
+class RegularCell3D;
+
+using namespace physx;
+using namespace physx::fracture;
+
+class Actor : public base::Actor
+{
+ friend class SimScene;
+protected:
+ Actor(base::SimScene* scene);
+public:
+ virtual ~Actor();
+
+protected:
+
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Compound.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Compound.cpp
new file mode 100644
index 00000000..c73b2ecf
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Compound.cpp
@@ -0,0 +1,161 @@
+
+#include "Mesh.h"
+#include "CompoundGeometry.h"
+#include "CompoundCreator.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxRigidBodyExt.h"
+#include "foundation/PxMat44.h"
+#include "PxScene.h"
+#include "PxShape.h"
+
+#include "SimScene.h"
+#include "Compound.h"
+#include "Convex.h"
+#include "XMLParser.h"
+#include "foundation/PxMathUtils.h"
+
+#include <vector>
+
+#include <stdio.h>
+
+#include "MathUtils.h"
+
+using namespace std;
+
+#define CREATE_DEBRIS 1
+
+float Compound::getSleepingThresholdRB()
+{
+ return 0.1f;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::draw(bool useShader, bool debug)
+{
+ if (useShader && mShader)
+ mShader->activate(mShaderMat);
+ else {
+ glColor3f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2]);
+ }
+
+ for (int i = 0; i < (int)mConvexes.size(); i++)
+ mConvexes[i]->draw(debug);
+
+ if (useShader && mShader)
+ mShader->deactivate();
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::clear()
+{
+ base::Compound::clear();
+
+ mShader = NULL;
+ mShaderMat.init();
+}
+
+void Compound::copyShaders(base::Compound* m)
+{
+ ((Compound*)m)->mShader = mShader;
+ ((Compound*)m)->mShaderMat = mShaderMat;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh)
+{
+ clear();
+ PxVec3 center;
+
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "name") {
+ // not used currently
+ }
+ else if (p->vars[i].name == "centerX")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.x);
+ else if (p->vars[i].name == "centerY")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.y);
+ else if (p->vars[i].name == "centerZ")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.z);
+ }
+ p->readNextTag();
+
+ // create Px objects
+ shdfnd::Array<PxShape*> shapes;
+
+ while (!p->endOfFile() && p->tagName != "Compound") {
+ if (p->tagName == "Convex") {
+ Convex *c = (Convex*)mScene->createConvex();
+ if (!c->createFromXml(p, scale, ignoreVisualMesh)) {
+ delete c;
+ return false;
+ }
+ c->increaseRefCounter();
+
+ // added overlap test in island detector, no need for ghost anymore!
+ if (c->isGhostConvex()) {
+// mConvexes.pushBack(c);
+ continue;
+ }
+
+ bool reused = c->getPxConvexMesh() != NULL;
+
+ PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
+ if (mesh == NULL) {
+ delete c;
+ continue;
+ }
+
+ if (!reused)
+ convexAdded(c, NULL); //mScene->getConvexRenderer().add(c);
+
+ PxShape *shape = mScene->getPxPhysics()->createShape(
+ PxConvexMeshGeometry(mesh),
+ *mScene->getPxDefaultMaterial(),
+ true
+ );
+ shape->setLocalPose(c->getLocalPose());
+
+ //shape->setContactOffset(mContactOffset);
+ //shape->setRestOffset(mRestOffset);
+
+ if (mContactOffset < mRestOffset || mContactOffset < 0.0f)
+ {
+ printf("WRONG2\n");
+ }
+
+ mScene->mapShapeToConvex(*shape, *c);
+
+ shapes.pushBack(shape);
+
+ if (!c->hasExplicitVisMesh())
+ c->createVisMeshFromConvex();
+
+ mConvexes.pushBack(c);
+ }
+ }
+ p->readNextTag();
+
+ PxVec3 vel(0.0f, 0.0f, 0.0f);
+ PxVec3 omega(0.0f, 0.0f, 0.0f);
+ createPxActor(shapes, trans * PxTransform(scale * center), vel, omega);
+
+ bool indestructible = false;
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ if (mConvexes[i]->isIndestructible()) {
+ indestructible = true;
+ break;
+ }
+ }
+
+ return true;
+}
+
+void Compound::convexAdded(base::Convex* c, Shader* shader)
+{
+ ((SimScene*)mScene)->getConvexRenderer().add(c, shader);
+}
+
+void Compound::convexRemoved(base::Convex* c)
+{
+ ((SimScene*)mScene)->getConvexRenderer().remove(c);
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Compound.h b/KaplaDemo/samples/sampleViewer3/Fracture/Compound.h
new file mode 100644
index 00000000..cfa635b6
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Compound.h
@@ -0,0 +1,59 @@
+#ifndef COMPOUND
+#define COMPOUND
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <foundation/PxBounds3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+#include <PxRigidDynamic.h>
+
+#include "Shader.h"
+
+#include "CompoundBase.h"
+
+using namespace physx;
+
+class Convex;
+class Particles;
+class Mesh;
+class SimScene;
+class CompoundGeometry;
+class XMLParser;
+
+class ShaderShadow;
+
+using namespace physx::fracture;
+
+class Compound : public base::Compound
+{
+ friend class SimScene;
+protected:
+ Compound(SimScene* scene, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f):
+ physx::fracture::base::Compound((base::SimScene*)scene,contactOffset,restOffset) {}
+public:
+
+ virtual void convexAdded(base::Convex* c, Shader* shader);
+ virtual void convexRemoved(base::Convex* c);
+
+ bool createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh = false);
+
+ void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
+ Shader* getShader() const { return mShader; }
+ const ShaderMaterial& getShaderMat() { return mShaderMat; }
+
+ virtual void draw(bool useShader, bool debug = false);
+
+ virtual void clear();
+
+ virtual void copyShaders(base::Compound*);
+
+protected:
+
+ virtual float getSleepingThresholdRB();
+
+ Shader *mShader;
+ ShaderMaterial mShaderMat;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.cpp
new file mode 100644
index 00000000..96227fa7
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.cpp
@@ -0,0 +1,38 @@
+#include "CompoundCreator.h"
+#include <algorithm>
+#include <assert.h>
+#include "CompoundGeometry.h"
+
+#define DEBUG_DRAW 1
+
+#if DEBUG_DRAW
+#include <windows.h>
+#include <GL/gl.h>
+#endif
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::debugDraw()
+{
+#if DEBUG_DRAW
+
+ const bool drawEdges = false;
+
+ if (drawEdges) {
+ glBegin(GL_LINES);
+ for (int i = 0; i < (int)mTetEdges.size(); i++) {
+ TetEdge &e = mTetEdges[i];
+ if (e.onSurface)
+ glColor3f(1.0f, 0.0f, 0.0f);
+ else
+ glColor3f(1.0f, 1.0f, 0.0f);
+
+ PxVec3 &p0 = mTetVertices[e.i0];
+ PxVec3 &p1 = mTetVertices[e.i1];
+ glVertex3f(p0.x, p0.y, p0.z);
+ glVertex3f(p1.x, p1.y, p1.z);
+ }
+ glEnd();
+ }
+
+#endif
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.h b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.h
new file mode 100644
index 00000000..92bf17a2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundCreator.h
@@ -0,0 +1,23 @@
+#ifndef COMPOUND_CREATOR_H
+#define COMPOUND_CREATOR_H
+
+// Matthias M�ller-Fischer
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+
+#include "CompoundCreatorBase.h"
+
+using namespace physx::fracture;
+
+class CompoundCreator : public base::CompoundCreator
+{
+ friend class SimScene;
+public:
+ virtual void debugDraw();
+protected:
+ CompoundCreator(SimScene* scene): base::CompoundCreator((base::SimScene*)scene) {}
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.cpp
new file mode 100644
index 00000000..fb22900e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.cpp
@@ -0,0 +1,75 @@
+#include "CompoundGeometry.h"
+
+#define DEBUG_DRAW 1
+
+#if DEBUG_DRAW
+#include <windows.h>
+#include <GL/gl.h>
+#endif
+
+// -------------------------------------------------------------------------------
+void CompoundGeometry::debugDraw(int maxConvexes) const
+{
+#if DEBUG_DRAW
+ const bool drawConvexes = true;
+ const bool drawWireframe = true;
+ const bool drawClipped = false;
+ const float clipMaxX = 0.0f;
+
+ if (drawConvexes) {
+ float s = drawClipped ? 1.0f : 0.95f;
+
+ if (drawWireframe)
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ PxVec3 n;
+ int num = convexes.size();
+ if (maxConvexes > 0 && maxConvexes < num)
+ num = maxConvexes;
+
+ for (int i = 0; i < num; i++) {
+
+ switch (i%7) {
+ case 0 : glColor3f(1.0f, 0.0f, 0.0f); break;
+ case 1 : glColor3f(0.0f, 1.0f, 0.0f); break;
+ case 2 : glColor3f(1.0f, 0.0f, 1.0f); break;
+ case 3 : glColor3f(0.0f, 1.0f, 1.0f); break;
+ case 4 : glColor3f(1.0f, 0.0f, 1.0f); break;
+ case 5 : glColor3f(1.0f, 1.0f, 0.0f); break;
+ case 6 : glColor3f(1.0f, 1.0f, 1.0f); break;
+ };
+
+ const Convex &c = convexes[i];
+ const PxVec3 *verts = &vertices[c.firstVert];
+ PxVec3 center;
+ center = PxVec3(0.0f, 0.0f, 0.0f);
+ for (int j = 0; j < c.numVerts; j++)
+ center += verts[j];
+ center /= (float)c.numVerts;
+ if (drawClipped && center.x > clipMaxX)
+ continue;
+
+ const int *ids = &indices[c.firstIndex];
+ for (int j = 0; j < c.numFaces; j++) {
+ int numVerts = *ids++;
+ int flags = *ids++;
+
+ n = (verts[ids[1]] - verts[ids[0]]).cross(verts[ids[2]] - verts[ids[0]]);
+ n.normalize();
+ glNormal3f(n.x, n.y, n.z);
+
+ glBegin(GL_POLYGON);
+ for (int k = 0; k < numVerts; k++) {
+ PxVec3 p = verts[ids[k]];
+ p = center + (p - center) * s;
+ glVertex3f(p.x, p.y, p.z);
+ }
+ glEnd();
+
+ ids += numVerts;
+ }
+ }
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ }
+#endif
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.h b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.h
new file mode 100644
index 00000000..b3612482
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/CompoundGeometry.h
@@ -0,0 +1,18 @@
+#ifndef COMPOUND_GEOMETRY
+#define COMPOUND_GEOMETRY
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <PsArray.h>
+
+#include "CompoundGeometryBase.h"
+
+using namespace physx;
+
+class CompoundGeometry : public physx::fracture::base::CompoundGeometry
+{
+public:
+ virtual void debugDraw(int maxConvexes = 0) const;
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Convex.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Convex.cpp
new file mode 100644
index 00000000..24580386
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Convex.cpp
@@ -0,0 +1,553 @@
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxDefaultStreams.h"
+#include "PxShape.h"
+#include "foundation/PxMath.h"
+#include "PxRigidDynamic.h"
+#include "PxConvexMesh.h"
+#include "foundation/PxMat44.h"
+#include "foundation/PxMathUtils.h"
+
+#include "CompoundGeometry.h"
+#include "Shader.h"
+#include "PolygonTriangulator.h"
+#include "XMLParser.h"
+
+#include "Convex.h"
+
+#include "PhysXMacros.h"
+
+class physx::PxPhysics;
+class physx::PxCooking;
+class physx::PxActor;
+class physx::PxScene;
+class physx::PxConvexMesh;
+
+#define COOK_TRIANGLES 0
+
+#include <algorithm>
+
+// --------------------------------------------------------------------------------------------
+void Convex::draw(bool debug)
+{
+//if (!mIsGhostConvex)
+// return; // foo
+
+ bool drawConvex = true;
+ bool drawVisMesh = true;
+ bool wireframe = false;
+ bool drawWorldBounds = false;
+ bool drawInsideTest = false;
+ bool drawVisPolys = true;
+ bool drawTangents = false;
+ bool drawNewFlag = false;
+
+ glEnable(GL_POLYGON_OFFSET_FILL);
+ glPolygonOffset(1.0f, 1.0f);
+
+ if (!debug) {
+ drawConvex = false;
+ drawVisMesh = true;
+ wireframe = false;
+ drawWorldBounds = false;
+ drawInsideTest = false;
+ drawVisPolys = false;
+ drawTangents = false;
+ }
+
+ if (drawConvex) {
+ if (mHasExplicitVisMesh)
+ glColor3f(0.0f, 0.0f, 1.0f);
+ else if (mIsGhostConvex)
+ glColor3f(0.0f, 1.0f, 0.0f);
+ else
+ glColor3f(1.0f, 1.0f, 1.0f);
+ glDisable(GL_LIGHTING);
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ PxMat44 mat(getGlobalPose());
+ glMultMatrixf((GLfloat*)mat.front());
+ }
+
+ glBegin(GL_LINES);
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ Face &f = mFaces[i];
+ for (int j = 0; j < f.numIndices; j++) {
+ PxVec3 &p0 = mVertices[mIndices[f.firstIndex + j]];
+ PxVec3 &p1 = mVertices[mIndices[f.firstIndex + (j+1)%f.numIndices]];
+ glVertex3f(p0.x, p0.y, p0.z);
+ glVertex3f(p1.x, p1.y, p1.z);
+ }
+
+ if (drawNewFlag && (f.flags & CompoundGeometry::FF_NEW) && f.numIndices > 0) {
+ float r = 0.01f;
+
+ PxVec3 c(0.0f, 0.0f, 0.0f);
+ for (int j = 0; j < f.numIndices; j++)
+ c += mVertices[mIndices[f.firstIndex + j]];
+ c /= (float)f.numIndices;
+ glVertex3f(c.x - r, c.y, c.z); glVertex3f(c.x + r, c.y, c.z);
+ glVertex3f(c.x, c.y - r, c.z); glVertex3f(c.x, c.y + r, c.z);
+ glVertex3f(c.x, c.y, c.z - r); glVertex3f(c.x, c.y, c.z + r);
+ }
+ }
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ }
+
+ if (mVisVertices.empty())
+ return;
+
+ if (drawVisPolys) {
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ PxMat44 mat(getGlobalPose());
+ glMultMatrixf((GLfloat*)mat.front());
+ }
+
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ for (int i = 0; i < (int)mVisPolyStarts.size()-1; i++) {
+ int first = mVisPolyStarts[i];
+ int num = mVisPolyStarts[i+1] - first;
+
+ for (int j = 0; j < num; j++) {
+ PxVec3 &p0 = mVisVertices[mVisPolyIndices[first + j]];
+ PxVec3 &p1 = mVisVertices[mVisPolyIndices[first + (j+1)%num]];
+ glVertex3f(p0.x, p0.y, p0.z);
+ glVertex3f(p1.x, p1.y, p1.z);
+ }
+ }
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ }
+
+ if (drawTangents) {
+ const float r = 0.1f;
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ PxMat44 mat(getGlobalPose());
+ glMultMatrixf((GLfloat*)mat.front());
+ }
+
+ glColor3f(1.0f, 1.0f, 0.0f);
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+ for (int i = 0; i < (int)mVisVertices.size()-1; i++) {
+ PxVec3 p0 = mVisVertices[i];
+ PxVec3 p1 = p0 + r * mVisTangents[i];
+ glVertex3f(p0.x, p0.y, p0.z);
+ glVertex3f(p1.x, p1.y, p1.z);
+ }
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+ }
+
+ if (drawVisMesh && mVisTriIndices.size() > 0) {
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ PxMat44 mat(getGlobalPose());
+ glMultMatrixf((GLfloat*)mat.front());
+ }
+
+ if (wireframe) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ glDisable(GL_LIGHTING);
+ }
+
+ if (debug)
+ glColor3f(1.0f, 1.0f, 1.0f);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+
+ glVertexPointer(3, GL_FLOAT, 0, &mVisVertices[0]);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), &mVisNormals[0]);
+
+ glDrawElements(GL_TRIANGLES, mVisTriIndices.size(), GL_UNSIGNED_INT, &mVisTriIndices[0]);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ if (mPxActor != NULL) {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ if (wireframe) {
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ glEnable(GL_LIGHTING);
+ }
+ }
+
+
+ if (drawWorldBounds) {
+ static const int corners[12 * 2][3] = {
+ {0,0,0}, {1,0,0}, {0,1,0}, {1,1,0}, {0,1,1}, {1,1,1}, {0,0,1}, {1,0,1},
+ {0,0,0}, {0,1,0}, {1,0,0}, {1,1,0}, {1,0,1}, {1,1,1}, {0,0,1}, {0,1,1},
+ {0,0,0}, {0,0,1}, {1,0,0}, {1,0,1}, {1,1,0}, {1,1,1}, {0,1,0}, {0,1,1}};
+ PxBounds3 b;
+ getWorldBounds(b);
+ glBegin(GL_LINES);
+ for (int i = 0; i < 24; i++) {
+ glVertex3f(
+ corners[i][0] ? b.minimum.x : b.maximum.x,
+ corners[i][1] ? b.minimum.y : b.maximum.y,
+ corners[i][2] ? b.minimum.z : b.maximum.z);
+ }
+ glEnd();
+ }
+
+ if (drawInsideTest) {
+ PxBounds3 bounds;
+ bounds.setEmpty();
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ bounds.include(mVertices[i]);
+
+ int num = 20;
+ float r = 0.05f * bounds.getDimensions().magnitude() / (float)num;
+ PxVec3 p;
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glBegin(GL_LINES);
+ for (int xi = 0; xi < num; xi++) {
+ for (int yi = 0; yi < num; yi++) {
+ for (int zi = 0; zi < num; zi++) {
+ p.x = bounds.minimum.x + xi * (bounds.maximum.x - bounds.minimum.x)/num;
+ p.y = bounds.minimum.y + yi * (bounds.maximum.y - bounds.minimum.y)/num;
+ p.z = bounds.minimum.z + zi * (bounds.maximum.z - bounds.minimum.z)/num;
+ if (insideVisualMesh(p)) {
+ glVertex3f(p.x - r, p.y, p.z); glVertex3f(p.x + r, p.y, p.z);
+ glVertex3f(p.x, p.y - r, p.z); glVertex3f(p.x, p.y + r, p.z);
+ glVertex3f(p.x, p.y, p.z - r); glVertex3f(p.x, p.y, p.z + r);
+ }
+ }
+ }
+ }
+ glEnd();
+
+ }
+
+ glDisable(GL_POLYGON_OFFSET_FILL);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::createFromXml(XMLParser *p, float scale, bool ignoreVisualMesh)
+{
+ clear();
+ PxVec3 center(0.0f, 0.0f, 0.0f);
+
+ std::vector<unsigned char> buffer(10000);
+
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "isGhost") {
+ mIsGhostConvex = p->vars[i].value == "true";
+ }
+ else if (p->vars[i].name == "modelIslandNr")
+ sscanf(p->vars[i].value.c_str(), "%i", &mModelIslandNr);
+ else if (p->vars[i].name == "centerX")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.x);
+ else if (p->vars[i].name == "centerY")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.y);
+ else if (p->vars[i].name == "centerZ")
+ sscanf(p->vars[i].value.c_str(), "%f", &center.z);
+ else if (p->vars[i].name == "surfacMaterialNr")
+ sscanf(p->vars[i].value.c_str(), "%i", &mSurfaceMaterialId);
+ else if (p->vars[i].name == "indestructible")
+ mIndestructible = p->vars[i].value == "true";
+ else if (p->vars[i].name == "materialId")
+ sscanf(p->vars[i].value.c_str(), "%i", &mMaterialId);
+ }
+ center *= scale;
+ mLocalPose = PX_TRANSFORM_ID;
+ mLocalPose.p = center;
+ mMaterialOffset = center;
+
+ p->readNextTag();
+ while (!p->endOfFile() && p->tagName != "Convex") {
+ if (p->tagName == "Vertices") {
+ int numVerts = 0;
+ bool binary = false;
+ bool binDouble = false;
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "count") {
+ sscanf(p->vars[i].value.c_str(), "%i", &numVerts);
+ }
+ else if (p->vars[i].name == "binary")
+ binary = p->vars[i].value == "true";
+ else if (p->vars[i].name == "double")
+ binDouble = p->vars[i].value == "true";
+ }
+ if (binary) {
+ if (binDouble) {
+ int size = numVerts * 3 * sizeof(double);
+ buffer.resize(size);
+ p->getFileScanner().getBinaryData(&buffer[0], size);
+ double *d = (double*)&buffer[0];
+ for (int i = 0; i < numVerts; i++) {
+ PxVec3 v;
+ v.x = (float)*d++;
+ v.y = (float)*d++;
+ v.z = (float)*d++;
+ mVertices.pushBack(scale * v);
+ }
+ }
+ else {
+ int size = numVerts * 3 * sizeof(float);
+ buffer.resize(size);
+ p->getFileScanner().getBinaryData(&buffer[0], size);
+ float *f = (float*)&buffer[0];
+ for (int i = 0; i < numVerts; i++) {
+ PxVec3 v;
+ v.x = *f++;
+ v.y = *f++;
+ v.z = *f++;
+ mVertices.pushBack(scale * v);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < numVerts; i++) {
+ PxVec3 v;
+ p->getFileScanner().getFloatSymbol(v.x);
+ p->getFileScanner().getFloatSymbol(v.y);
+ p->getFileScanner().getFloatSymbol(v.z);
+ mVertices.pushBack(scale * v);
+ }
+ }
+ p->readNextTag(); // </Vertices>
+ p->readNextTag();
+ }
+ else if (p->tagName == "Faces") {
+ p->readNextTag();
+ while (!p->endOfFile() && p->tagName != "Faces") {
+ if (p->tagName == "Face") {
+ int size = 0;
+ bool hasNormals = false;
+ bool isSurface = false;
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "size") {
+ sscanf(p->vars[i].value.c_str(), "%i", &size);
+ }
+ else if (p->vars[i].name == "hasNormals") {
+ hasNormals = p->vars[i].value == "true";
+ }
+ else if (p->vars[i].name == "isSurface") {
+ isSurface = p->vars[i].value == "true";
+ }
+ }
+ Face f;
+ f.init();
+ f.firstIndex = mIndices.size();
+ f.numIndices = size;
+ f.firstNormal = mNormals.size();
+ f.flags = 0;
+ if (hasNormals)
+ f.flags |= CompoundGeometry::FF_HAS_NORMALS;
+ if (isSurface)
+ f.flags |= CompoundGeometry::FF_OBJECT_SURFACE;
+
+ for (int i = 0; i < size; i++) {
+ int id;
+ p->getFileScanner().getIntSymbol(id);
+ mIndices.pushBack(id);
+ if (hasNormals) {
+ PxVec3 n;
+ p->getFileScanner().getFloatSymbol(n.x);
+ p->getFileScanner().getFloatSymbol(n.y);
+ p->getFileScanner().getFloatSymbol(n.z);
+ mNormals.pushBack(n);
+ }
+ }
+ mFaces.pushBack(f);
+ p->readNextTag(); // </Face>
+ p->readNextTag();
+ }
+ }
+ p->readNextTag();
+ }
+ else if (p->tagName == "VisualVertices") {
+ if (!ignoreVisualMesh)
+ mHasExplicitVisMesh = true;
+
+ int numVerts = 0;
+ bool hasNormals = false;
+ bool hasTexCoords = false;
+ bool binary = false;
+ bool binDouble = false;
+
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "count") {
+ sscanf(p->vars[i].value.c_str(), "%i", &numVerts);
+ }
+ else if (p->vars[i].name == "normals") {
+ hasNormals = p->vars[i].value == "true";
+ }
+ else if (p->vars[i].name == "texCoords") {
+ hasTexCoords = p->vars[i].value == "true";
+ }
+ else if (p->vars[i].name == "binary")
+ binary = p->vars[i].value == "true";
+ else if (p->vars[i].name == "double")
+ binDouble = p->vars[i].value == "true";
+ }
+
+ PxVec3 v, n, t;
+ float tu, tv;
+
+ if (binary) {
+ int numScalars = 3;
+ if (hasNormals) numScalars += 3;
+ if (hasTexCoords) numScalars += 2;
+
+ if (binDouble) {
+ int size = numVerts * numScalars * sizeof(double);
+ buffer.resize(size);
+ p->getFileScanner().getBinaryData(&buffer[0], size);
+ if (!ignoreVisualMesh) {
+ double *d = (double*)&buffer[0];
+ for (int i = 0; i < numVerts; i++) {
+ v.x = (float)*d++;
+ v.y = (float)*d++;
+ v.z = (float)*d++;
+ n = PxVec3(0.0f, 0.0f, 0.0f);
+ if (hasNormals) {
+ n.x = (float)*d++;
+ n.y = (float)*d++;
+ n.z = (float)*d++;
+ }
+ tu = 0.0f; tv = 0.0f;
+ if (hasTexCoords) {
+ tu = (float)*d++;
+ tv = (float)*d++;
+ }
+ mVisVertices.pushBack(scale * v);
+ mVisNormals.pushBack(n);
+ mVisTexCoords.pushBack(tu);
+ mVisTexCoords.pushBack(tv);
+ mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // no bumps on the surface
+ }
+ }
+ }
+ else {
+ int size = numVerts * numScalars * sizeof(float);
+ buffer.resize(size);
+ p->getFileScanner().getBinaryData(&buffer[0], size);
+ if (!ignoreVisualMesh) {
+ float *f = (float*)&buffer[0];
+ for (int i = 0; i < numVerts; i++) {
+ v.x = *f++;
+ v.y = *f++;
+ v.z = *f++;
+ n = PxVec3(0.0f, 0.0f, 0.0f);
+ if (hasNormals) {
+ n.x = *f++;
+ n.y = *f++;
+ n.z = *f++;
+ }
+ tu = 0.0f; tv = 0.0f;
+ if (hasTexCoords) {
+ tu = *f++;
+ tv = *f++;
+ }
+ mVisVertices.pushBack(scale * v);
+ mVisNormals.pushBack(n);
+ mVisTexCoords.pushBack(tu);
+ mVisTexCoords.pushBack(tv);
+ mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // no bumps on the surface
+ }
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < numVerts; i++) {
+ PxVec3 v(0.0f, 0.0f, 0.0f);
+ PxVec3 n(0.0f, 0.0f, 0.0f);
+ PxVec3 t(0.0f, 0.0f, 0.0f);
+ float tu = 0.0f;
+ float tv = 0.0f;
+ p->getFileScanner().getFloatSymbol(v.x);
+ p->getFileScanner().getFloatSymbol(v.y);
+ p->getFileScanner().getFloatSymbol(v.z);
+
+ if (hasNormals) {
+ p->getFileScanner().getFloatSymbol(n.x);
+ p->getFileScanner().getFloatSymbol(n.y);
+ p->getFileScanner().getFloatSymbol(n.z);
+ }
+ if (hasTexCoords) {
+ p->getFileScanner().getFloatSymbol(tu);
+ p->getFileScanner().getFloatSymbol(tv);
+ }
+
+ if (!ignoreVisualMesh) {
+ mVisVertices.pushBack(scale * v);
+ mVisNormals.pushBack(n);
+ mVisTexCoords.pushBack(tu);
+ mVisTexCoords.pushBack(tv);
+ mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // no bumps on the surface
+ }
+ }
+ }
+ p->readNextTag(); // </VisualVertices>
+ p->readNextTag();
+ }
+ else if (p->tagName == "VisualFaces") {
+ int numFaces = 0;
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "count")
+ sscanf(p->vars[i].value.c_str(), "%i", &numFaces);
+ }
+ for (int i = 0; i < numFaces; i++) {
+ if (!ignoreVisualMesh)
+ mVisPolyStarts.pushBack(mVisPolyIndices.size());
+ int id;
+ while (!p->endOfFile()) {
+ p->getFileScanner().getIntSymbol(id);
+ if (id < 0)
+ break;
+ if (!ignoreVisualMesh)
+ mVisPolyIndices.pushBack(id);
+ }
+ }
+ if (!ignoreVisualMesh)
+ mVisPolyStarts.pushBack(mVisPolyIndices.size());
+ p->readNextTag(); // </VisualFaces>
+ p->readNextTag();
+ }
+ else
+ p->readNextTag();
+ }
+
+ p->readNextTag();
+
+ finalize();
+
+ if (mHasExplicitVisMesh) {
+ computeVisMeshNeighbors();
+ createVisTrisFromPolys();
+ computeVisTangentsFromPoly();
+ }
+
+ // check(); // foo
+
+ return true;
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Convex.h b/KaplaDemo/samples/sampleViewer3/Fracture/Convex.h
new file mode 100644
index 00000000..f327ae0d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Convex.h
@@ -0,0 +1,39 @@
+#ifndef CONVEX
+#define CONVEX
+
+#include <PxPhysics.h>
+#include <PxCooking.h>
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <foundation/PxBounds3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+
+#include "ConvexBase.h"
+
+using namespace physx;
+
+class physx::PxShape;
+class physx::PxActor;
+class physx::PxScene;
+class physx::PxConvexMesh;
+
+class Compound;
+class CompoundGeometry;
+class XMLParser;
+
+using namespace physx::fracture;
+
+class Convex : public base::Convex
+{
+ friend class SimScene;
+protected:
+ Convex(base::SimScene* scene): base::Convex(scene) {}
+public:
+
+ virtual void draw(bool debug = false);
+
+ bool createFromXml(XMLParser *p, float scale, bool ignoreVisualMesh = false);
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.cpp
new file mode 100644
index 00000000..4c438127
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.cpp
@@ -0,0 +1,376 @@
+#include "Shader.h"
+#include "ConvexRenderer.h"
+#include "Compound.h"
+#include <foundation/PxMat44.h>
+
+//--------------------------------------------------------
+ConvexRenderer::ConvexRenderer()
+{
+ init();
+}
+
+//--------------------------------------------------------
+ConvexRenderer::~ConvexRenderer()
+{
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::init()
+{
+ mShader = NULL;
+ mShaderMat.init();
+
+ mBumpTextureUVScale = 0.1f;
+ mExtraNoiseScale = 2.0f;
+ mRoughnessScale = 0.2f;
+
+ mDiffuseTexArray = 0;
+ mBumpTexArray = 0;
+ mSpecularTexArray = 0;
+ mEmissiveReflectSpecPowerTexArray = 0;
+
+ mActive = true;
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::add(const base::Convex* convex, Shader* shader)
+{
+ if (!mActive)
+ return;
+
+ ConvexGroup *g;
+
+ // int gnr = 0; // to search all groups
+ int gnr = 0;// !mGroups.empty() ? mGroups.size() - 1 : 0; // to search only last
+ int numNewVerts = convex->getVisVertices().size();
+
+ while (gnr < (int)mGroups.size() && (mGroups[gnr]->numVertices + numNewVerts >= maxVertsPerGroup || mGroups[gnr]->mShader != shader))
+ gnr++;
+
+ if (gnr == (int)mGroups.size()) { // create new group
+ g = new ConvexGroup();
+ g->init();
+ g->mShader = shader;
+ gnr = mGroups.size();
+ mGroups.push_back(g);
+ }
+ g = mGroups[gnr];
+ convex->setConvexRendererInfo(gnr, g->convexes.size());
+ g->convexes.push_back((Convex*)convex);
+ g->numIndices += convex->getVisTriIndices().size();
+ g->numVertices += convex->getVisVertices().size();
+ g->dirty = true;
+
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::remove(const base::Convex* convex)
+{
+ if (!mActive)
+ return;
+
+ int gnr = convex->getConvexRendererGroupNr();
+ int pos = convex->getConvexRendererGroupPos();
+ if (gnr < 0 || gnr >= (int)mGroups.size())
+ return;
+
+ ConvexGroup *g = mGroups[gnr];
+ if (pos < 0 || pos > (int)g->convexes.size())
+ return;
+
+ if (g->convexes[pos] != convex)
+ return;
+
+ g->numIndices -= convex->getVisTriIndices().size();
+ g->numVertices -= convex->getVisVertices().size();
+
+ g->convexes[pos] = g->convexes[g->convexes.size()-1];
+ g->convexes[pos]->setConvexRendererInfo(gnr, pos);
+ g->convexes.pop_back();
+ g->dirty = true;
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::updateRenderBuffers()
+{
+ /*
+ static int maxNumV = 0;
+ static int maxNumI = 0;
+ static int maxNumC = 0;
+ static int maxNumG = 0;
+ if (mGroups.size() > maxNumG) maxNumG = mGroups.size();
+ */
+
+ for (int i = 0; i < (int)mGroups.size(); i++) {
+
+
+ ConvexGroup *g = mGroups[i];
+ if (!g->dirty)
+ continue;
+
+ if (g->numIndices == 0 || g->numVertices == 0)
+ continue;
+
+ if (!g->VBO) {
+ glGenBuffersARB(1, &g->VBO);
+ }
+ if (!g->IBO) {
+ glGenBuffersARB(1, &g->IBO);
+ }
+ if (!g->matTex) {
+ glGenTextures(1, &g->matTex);
+ glBindTexture(GL_TEXTURE_2D, g->matTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ }
+ if (g->numVertices == 0 || g->numIndices == 0)
+ return;
+
+ // recalculate in case they have changed
+ g->numVertices = 0;
+ g->numIndices = 0;
+ for (int i = 0; i < (int)g->convexes.size(); i++) {
+ g->numVertices += g->convexes[i]->getVisVertices().size();
+ g->numIndices += g->convexes[i]->getVisTriIndices().size();
+ }
+
+ g->vertices.resize(g->numVertices*12);
+ g->indices.resize(g->numIndices);
+ float* vp = &g->vertices[0];
+ unsigned int* ip = &g->indices[0];
+
+ int sumV = 0;
+ // Make cpu copy of VBO and IBO
+
+ int convexNr = 0;
+ for (int j = 0; j < (int)g->convexes.size(); j++, convexNr++) {
+ const Convex* c = g->convexes[j];
+ // PxVec3 matOff = c->getMaterialOffset();
+
+ int nv = c->getVisVertices().size();
+ int ni = c->getVisTriIndices().size();
+
+ if (nv > 0) {
+ float* cvp = (float*)&c->getVisVertices()[0]; // float3
+ float* cnp = (float*)&c->getVisNormals()[0]; // float3
+ // float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
+ float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
+ float* ctanp = (float*)&c->getVisTangents()[0]; // float3
+
+ int* cip = (int*)&c->getVisTriIndices()[0];
+ for (int k = 0; k < nv; k++) {
+ *(vp++) = *(cvp++);
+ *(vp++) = *(cvp++);
+ *(vp++) = *(cvp++);
+
+ *(vp++) = *(cnp++);
+ *(vp++) = *(cnp++);
+ *(vp++) = *(cnp++);
+
+ *(vp++) = *(ctanp++);
+ *(vp++) = *(ctanp++);
+ *(vp++) = *(ctanp++);
+ *(vp++) = (float)convexNr;
+
+ *(vp++) = *(c2dtp++);
+ *(vp++) = *(c2dtp++);
+
+ }
+ for (int k = 0; k < ni; k++) {
+ *(ip++) = *(cip++) + sumV;
+ }
+ }
+ //memcpy(ip, cip, sizeof(int)*ni);
+ //ip += 3*ni;
+
+ //std::vector<PxVec3> mTriVertices;
+ //std::vector<PxVec3> mTriNormals;
+ //std::vector<int> mTriIndices;
+ //std::vector<float> mTriTexCoords; // 3d + obj nr
+ sumV += nv;
+ }
+/*
+ if (g->vertices.size() > maxNumV) maxNumV = g->vertices.size();
+ if (g->indices.size() > maxNumI) maxNumI = g->indices.size();
+ if (g->convexes.size() > maxNumC) maxNumC = g->convexes.size();
+*/
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, g->vertices.size()*sizeof(float), &g->vertices[0], GL_DYNAMIC_DRAW);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->indices.size()*sizeof(unsigned int), &g->indices[0], GL_DYNAMIC_DRAW);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+ int oldTexSize = g->texSize;
+ if (g->texSize == 0) {
+ // First time
+ oldTexSize = 1;
+ g->texSize = 32;
+ }
+
+ while (1) {
+ int convexesPerRow = g->texSize / 4;
+ if (convexesPerRow * g->texSize >= (int)g->convexes.size()) {
+ break;
+ } else {
+ g->texSize *= 2;
+ }
+ }
+ if (g->texSize != oldTexSize) {
+ g->texCoords.resize(g->texSize*g->texSize*4);
+ // Let's allocate texture
+ glBindTexture(GL_TEXTURE_2D, g->matTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, g->texSize, g->texSize, 0, GL_RGBA, GL_FLOAT, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ g->dirty = false;
+ }
+
+// printf("maxV = %d, maxI = %d, maxC = %d, maxG = %d\n", maxNumV, maxNumI, maxNumC, maxNumG);
+
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::updateTransformations()
+{
+ for (int i = 0; i < (int)mGroups.size(); i++) {
+ ConvexGroup *g = mGroups[i];
+ if (g->texCoords.empty())
+ continue;
+
+ float* tt = &g->texCoords[0];
+
+ for (int j = 0; j < (int)g->convexes.size(); j++) {
+ const Convex* c = g->convexes[j];
+
+ PxMat44 pose(c->getGlobalPose());
+ float* mp = (float*)pose.front();
+
+ float* ta = tt;
+ for (int k = 0; k < 16; k++) {
+ *(tt++) = *(mp++);
+ }
+ PxVec3 matOff = c->getMaterialOffset();
+ ta[3] = matOff.x;
+ ta[7] = matOff.y;
+ ta[11] = matOff.z;
+
+ int idFor2DTex = c->getSurfaceMaterialId();
+ int idFor3DTex = c->getMaterialId();
+ const int MAX_3D_TEX = 8;
+ ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
+
+
+ }
+
+ glBindTexture(GL_TEXTURE_2D, g->matTex);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, g->texSize, g->texSize,
+ GL_RGBA, GL_FLOAT, &g->texCoords[0]);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+}
+
+//--------------------------------------------------------
+void ConvexRenderer::render()
+{
+ if (!mActive)
+ return;
+
+ updateRenderBuffers();
+
+ updateTransformations();
+
+ for (int i = 0; i < (int)mGroups.size(); i++) {
+
+ ConvexGroup *g = mGroups[i];
+
+ Shader* shader = mShader;
+ if (g->mShader != NULL)
+ shader = g->mShader;
+
+ shader->activate(mShaderMat);
+ // Assume convex all use the same shader
+
+ glActiveTexture(GL_TEXTURE7);
+ glBindTexture(GL_TEXTURE_3D, volTex);
+
+ glActiveTexture(GL_TEXTURE8);
+ glBindTexture(GL_TEXTURE_2D, g->matTex);
+
+ glActiveTexture(GL_TEXTURE10);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mDiffuseTexArray);
+ glActiveTexture(GL_TEXTURE11);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mBumpTexArray);
+ glActiveTexture(GL_TEXTURE12);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mSpecularTexArray);
+ glActiveTexture(GL_TEXTURE13);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mEmissiveReflectSpecPowerTexArray);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ float itt = 1.0f/g->texSize;
+
+ shader->setUniform("diffuseTexArray", 10);
+ shader->setUniform("bumpTexArray", 11);
+ shader->setUniform("specularTexArray", 12);
+ shader->setUniform("emissiveReflectSpecPowerTexArray", 13);
+
+ shader->setUniform("ttt3D", 7);
+ shader->setUniform("transTex", 8);
+ shader->setUniform("transTexSize", g->texSize);
+ shader->setUniform("iTransTexSize", itt);
+ shader->setUniform("bumpTextureUVScale", mBumpTextureUVScale);
+ shader->setUniform("extraNoiseScale", mExtraNoiseScale);
+ shader->setUniform("roughnessScale", mRoughnessScale);
+
+ if (mShaderMat.color[3] < 1.0f) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST);
+ glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, g->VBO);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, g->IBO);
+
+ int stride = 12*sizeof(float);
+ glVertexPointer(3, GL_FLOAT, stride, 0);
+
+ glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
+
+ glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
+
+ glClientActiveTexture(GL_TEXTURE1);
+ glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawElements(GL_TRIANGLES, g->numIndices, GL_UNSIGNED_INT, 0);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+
+ if (mShaderMat.color[3] < 1.0f) {
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ shader->deactivate();
+ }
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.h b/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.h
new file mode 100644
index 00000000..3c931d09
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/ConvexRenderer.h
@@ -0,0 +1,77 @@
+#ifndef CONVEX_RENDERER
+#define CONVEX_RENDERER
+
+#include "Convex.h"
+#include <vector>
+
+using namespace physx;
+
+class Shader;
+
+// ----------------------------------------------------------------------------
+class ConvexRenderer
+{
+public:
+ ConvexRenderer();
+ ~ConvexRenderer();
+
+ void init();
+
+ const static int maxVertsPerGroup = 100000;
+
+ void setActive(bool active) { mActive = active; };
+
+ void add(const base::Convex* convex, Shader* shader);
+ void remove(const base::Convex* convex);
+
+ void render();
+ void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
+ void setTexArrays(unsigned int diffuse, unsigned int bump, unsigned int specular, unsigned int specPower) {
+ mDiffuseTexArray = diffuse; mBumpTexArray = bump;
+ mSpecularTexArray = specular; mEmissiveReflectSpecPowerTexArray = specPower; }
+ void setVolTex(unsigned int volTexi) { volTex = volTexi;}
+private:
+ void updateRenderBuffers();
+ void updateTransformations();
+
+ Shader* mShader;
+ ShaderMaterial mShaderMat;
+
+ struct ConvexGroup {
+ void init() {
+ numVertices = 0; numIndices = 0;
+ VBO = 0; IBO = 0; matTex = 0;
+ texSize = 0;
+ }
+ bool dirty;
+ std::vector<const Convex*> convexes;
+
+ std::vector<float> vertices;
+ std::vector<unsigned int> indices;
+ std::vector<float> texCoords;
+
+ int numVertices, numIndices;
+ unsigned int VBO;
+ unsigned int IBO;
+ unsigned int matTex;
+ int texSize;
+
+ Shader* mShader;
+ };
+
+ std::vector<ConvexGroup*> mGroups;
+
+ bool mActive;
+
+ float mBumpTextureUVScale;
+ float mExtraNoiseScale;
+ float mRoughnessScale;
+
+ unsigned int mDiffuseTexArray;
+ unsigned int mBumpTexArray;
+ unsigned int mSpecularTexArray;
+ unsigned int mEmissiveReflectSpecPowerTexArray;
+ unsigned int volTex;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.cpp
new file mode 100644
index 00000000..4504add8
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.cpp
@@ -0,0 +1,139 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "ActorBase.h"
+
+#include <foundation/PxMat44.h>
+#include "PxRigidBodyExt.h"
+
+#include "PxScene.h"
+#include "SimSceneBase.h"
+#include "CompoundBase.h"
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+Actor::Actor(SimScene* scene):
+ mScene(scene),
+ mMinConvexSize(scene->mMinConvexSize),
+ mDepthLimit(100),
+ mDestroyIfAtDepthLimit(false)
+{
+
+}
+
+Actor::~Actor()
+{
+ mScene->getScene()->lockWrite();
+ clear();
+ mScene->getScene()->unlockWrite();
+ mScene->removeActor(this);
+}
+
+void Actor::clear()
+{
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ PX_DELETE(mCompounds[i]);
+ }
+ mCompounds.clear();
+}
+
+void Actor::addCompound(Compound *c)
+{
+ mCompounds.pushBack(c);
+ PxRigidDynamic *a = c->getPxActor();
+#if 1
+ if (a) {
+// a->setContactReportFlags(Px_NOTIFY_ON_TOUCH_FORCE_THRESHOLD | Px_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD);
+ a->setContactReportThreshold(mScene->mFractureForceThreshold);
+ }
+#endif
+ c->mActor = this;
+ ++(mScene->mSceneVersion);
+}
+
+void Actor::removeCompound(Compound *c)
+{
+ int num = 0;
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ if (mCompounds[i] != c) {
+ mCompounds[num] = mCompounds[i];
+ num++;
+ }
+ }
+ if (mScene->mPickActor == c->getPxActor())
+ mScene->mPickActor = NULL;
+
+ c->clear();
+ //delCompoundList.push_back(c);
+ //delete c;
+ mScene->delCompoundList.pushBack(c);
+ mCompounds.resize(num);
+ ++mScene->mSceneVersion;
+}
+
+void Actor::preSim(float dt)
+{
+ int num = 0;
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ mCompounds[i]->step(dt);
+ if (mCompounds[i]->getLifeFrames() == 0) {
+ mCompounds[i]->clear();
+ //delCompoundList.push_back(mCompounds[i]);
+ //delete mCompounds[i];
+ mScene->delCompoundList.pushBack(mCompounds[i]);
+ }
+ else {
+ mCompounds[num] = mCompounds[i];
+ num++;
+ }
+ }
+ mCompounds.resize(num);
+}
+
+void Actor::postSim(float /*dt*/)
+{
+}
+
+bool Actor::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const
+{
+ dist = PX_MAX_F32;
+ compoundNr = -1;
+ convexNr = -1;
+
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ float d;
+ int cNr;
+ PxVec3 n;
+ if (mCompounds[i]->rayCast(orig, dir, d, cNr, n)) {
+ if (d < dist) {
+ dist = d;
+ compoundNr = i;
+ convexNr = cNr;
+ normal = n;
+ }
+ }
+ }
+ return compoundNr >= 0;
+}
+
+bool Actor::findCompound(const Compound* c, int& compoundNr)
+{
+ for(int i = 0; i < (int)mCompounds.size(); i++)
+ {
+ if(mCompounds[i] == c)
+ {
+ compoundNr = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.h
new file mode 100644
index 00000000..b268b5f9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ActorBase.h
@@ -0,0 +1,54 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef ACTOR_BASE_H
+#define ACTOR_BASE_H
+
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+class Compound;
+
+class Actor : public ::physx::shdfnd::UserAllocated
+{
+ friend class SimScene;
+ friend class Compound;
+protected:
+ Actor(SimScene* scene);
+public:
+ virtual ~Actor();
+
+ void clear();
+ void addCompound(Compound *m);
+ void removeCompound(Compound *m);
+
+ bool findCompound(const Compound* c, int& compoundNr);
+
+ void preSim(float dt);
+ void postSim(float dt);
+
+ bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &compoundNr, int &convexNr, PxVec3 &normal) const;
+
+ shdfnd::Array<Compound*> getCompounds() { return mCompounds; }
+
+protected:
+ SimScene* mScene;
+ shdfnd::Array<Compound*> mCompounds;
+
+ PxF32 mMinConvexSize;
+ PxU32 mDepthLimit;
+ bool mDestroyIfAtDepthLimit;
+};
+
+}
+}
+}
+
+#endif
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.cpp
new file mode 100644
index 00000000..ac2c4f15
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.cpp
@@ -0,0 +1,536 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "MeshBase.h"
+#include "CompoundGeometryBase.h"
+#include "CompoundCreatorBase.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxRigidBodyExt.h"
+#include "foundation/PxMat44.h"
+#include "PxScene.h"
+#include "PxShape.h"
+
+#include "SimSceneBase.h"
+#include "CompoundBase.h"
+#include "ActorBase.h"
+#include "ConvexBase.h"
+#include "foundation/PxMathUtils.h"
+
+#include <stdio.h>
+
+#include "MathUtils.h"
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+//vector<PxVec3> tmpPoints;
+void Compound::appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, shdfnd::Array<PxVec3>& samples, shdfnd::Array<PxVec3>* normals) {
+ PxVec3& p0 = vertices[0];
+ PxVec3 normal;
+ if (numV < 3) {
+ normal = PxVec3(0.0f,1.0f,0.0f);
+ } else {
+ normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
+ normal.normalize();
+ }
+ for (int i = 1; i < numV-1; i++) {
+ PxVec3& p1 = vertices[i];
+ PxVec3& p2 = vertices[i+1];
+ float tarea = 0.5f*((p1-p0).cross(p2-p0)).magnitude();
+ float aa = tarea / area;
+ int np = (int)floor(aa);
+
+ if (randRange(0.0f,1.0f) <= aa-np) np++;
+
+ for (int j = 0; j < np; j++) {
+ float r1 = randRange(0.0f,1.0f);
+ float sr1 = physx::PxSqrt(r1);
+ float r2 = randRange(0.0f, 1.0f);
+
+ PxVec3 p = (1 - sr1) * p0 + (sr1 * (1 - r2)) * p1 + (sr1 * r2) * p2;
+ samples.pushBack(p);
+ if (normals) normals->pushBack(normal);
+
+ }
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+Compound::Compound(SimScene *scene, PxReal contactOffset, PxReal restOffset)
+{
+ mScene = scene;
+ mActor = NULL;
+ mPxActor = NULL;
+ mContactOffset = contactOffset;
+ mRestOffset = restOffset;
+ mLifeFrames = -1; // live forever
+ mDepth = 0;
+ clear();
+}
+
+// --------------------------------------------------------------------------------------------
+Compound::~Compound()
+{
+ clear();
+}
+
+// --------------------------------------------------------------------------------------------
+#define SHAPE_BUFFER_SIZE 100
+
+void Compound::clear()
+{
+ if (mPxActor != NULL) {
+ // Unmap all shapes for this actor
+ const physx::PxU32 shapeCount = mPxActor->getNbShapes();
+ physx::PxShape* shapeBuffer[SHAPE_BUFFER_SIZE];
+ for (physx::PxU32 shapeStartIndex = 0; shapeStartIndex < shapeCount; shapeStartIndex += SHAPE_BUFFER_SIZE)
+ {
+ physx::PxU32 shapesRead = mPxActor->getShapes(shapeBuffer, SHAPE_BUFFER_SIZE, shapeStartIndex);
+ for (physx::PxU32 shapeBufferIndex = 0; shapeBufferIndex < shapesRead; ++shapeBufferIndex)
+ {
+ mScene->unmapShape(*shapeBuffer[shapeBufferIndex]);
+ }
+ }
+ // release the actor
+ mPxActor->release();
+ mPxActor = NULL;
+ }
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ if (mConvexes[i]->decreaseRefCounter() <= 0) {
+ convexRemoved(mConvexes[i]); //mScene->getConvexRenderer().remove(mConvexes[i]);
+ PX_DELETE(mConvexes[i]);
+ }
+ }
+
+ mConvexes.clear();
+ mEdges.clear();
+
+ //mShader = NULL;
+ //mShaderMat.init();
+
+ mKinematicVel = PxVec3(0.0f, 0.0f, 0.0f);
+ mAttachmentBounds.clear();
+
+ mAdditionalImpactNormalImpulse = 0.0f;
+ mAdditionalImpactRadialImpulse = 0.0f;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::setKinematic(const PxVec3 &vel)
+{
+ if (mPxActor == NULL)
+ return;
+
+ mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+ mKinematicVel = vel;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::step(float dt)
+{
+ //if (mPxActor == NULL)
+ // return;
+
+ if (!mKinematicVel.isZero()) {
+ PxTransform pose = mPxActor->getGlobalPose();
+ pose.p += mKinematicVel * dt;
+ mPxActor->setKinematicTarget(pose);
+ }
+
+ if (mLifeFrames > 0)
+ mLifeFrames--;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
+{
+ return createFromConvexes(&convex, 1, pose, vel, omega, copyConvexes, matID, surfMatID);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes, int matID, int surfMatID)
+{
+ if (numConvexes == 0)
+ return false;
+
+ clear();
+ PxVec3 center(0.0f, 0.0f, 0.0f);
+ for (int i = 0; i < numConvexes; i++)
+ center += convexes[i]->getCenter();
+ center /= (float)numConvexes;
+
+ shdfnd::Array<PxShape*> shapes;
+
+ for (int i = 0; i < numConvexes; i++) {
+ Convex *c;
+ if (copyConvexes) {
+ c = mScene->createConvex();
+ c->createFromConvex(convexes[i], 0, matID, surfMatID);
+ }
+ else
+ c = convexes[i];
+
+ c->increaseRefCounter();
+ mConvexes.pushBack(c);
+
+ PxVec3 off = c->centerAtZero();
+ c->setMaterialOffset(c->getMaterialOffset() + off);
+ c->setLocalPose(PxTransform(off - center));
+
+ if (convexes[i]->isGhostConvex())
+ continue;
+
+ bool reused = c->getPxConvexMesh() != NULL;
+
+ mScene->profileBegin("cook convex meshes"); //Profiler::getInstance()->begin("cook convex meshes");
+ PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
+ mScene->profileEnd("cook convex meshes"); //Profiler::getInstance()->end("cook convex meshes");
+
+ if (mesh == NULL) {
+ if (c->decreaseRefCounter() <= 0)
+ PX_DELETE(c);
+ mConvexes.popBack();
+ continue;
+ }
+
+ if (!c->hasExplicitVisMesh())
+ c->createVisMeshFromConvex();
+
+ if (!reused)
+ convexAdded(c); //mScene->getConvexRenderer().add(c);
+
+ PxShape *shape = mScene->getPxPhysics()->createShape(
+ PxConvexMeshGeometry(mesh),
+ *mScene->getPxDefaultMaterial(),
+ true
+ );
+ shape->setLocalPose(c->getLocalPose());
+
+ //shape->setContactOffset(mContactOffset);
+ //shape->setRestOffset(mRestOffset);
+
+ if (mContactOffset < mRestOffset || mContactOffset < 0.0f)
+ {
+ printf("WRONG\n");
+ }
+
+ mScene->mapShapeToConvex(*shape, *c);
+
+ shapes.pushBack(shape);
+ }
+
+ if (shapes.empty())
+ {
+ return false;
+ }
+
+ createPxActor(shapes, pose, vel, omega);
+
+
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+
+bool Compound::createFromGeometry(const CompoundGeometry &geom, PxRigidDynamic* body, Shader* myShader, int matID, int surfMatID)
+{
+ clear();
+
+ shdfnd::Array<PxShape*> shapes(body->getNbShapes());
+
+ body->getShapes(shapes.begin(), body->getNbShapes());
+
+ PX_ASSERT(geom.convexes.size() == body->getNbShapes());
+
+ for (int i = 0; i < (int)geom.convexes.size(); i++) {
+ Convex *c = mScene->createConvex();
+ c->createFromGeometry(geom, i, 0, matID, surfMatID);
+ c->increaseRefCounter();
+ mConvexes.pushBack(c);
+
+ PxVec3 off = c->centerAtZero();
+ c->setMaterialOffset(c->getMaterialOffset() + off);
+ c->createVisMeshFromConvex();
+ c->setLocalPose(PxTransform(off));
+
+ bool reused = c->getPxConvexMesh() != NULL;
+
+ if (!reused)
+ convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
+
+ mScene->mapShapeToConvex(*shapes[i], *c);
+
+ }
+
+ if (shapes.empty())
+ return false;
+
+ mPxActor = body;
+ for (int i = 0; i < (int)mConvexes.size(); i++)
+ mConvexes[i]->setPxActor(mPxActor);
+
+ //createPxActor(shapes, pose, vel, omega);
+ return true;
+
+}
+bool Compound::createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, Shader* myShader, int matID, int surfMatID)
+{
+ clear();
+
+ shdfnd::Array<PxShape*> shapes;
+
+ for (int i = 0; i < (int)geom.convexes.size(); i++) {
+ Convex *c = mScene->createConvex();
+ c->createFromGeometry(geom, i, 0, matID, surfMatID);
+ c->increaseRefCounter();
+ mConvexes.pushBack(c);
+
+ PxVec3 off = c->centerAtZero();
+ c->setMaterialOffset(c->getMaterialOffset() + off);
+ c->createVisMeshFromConvex();
+ c->setLocalPose(PxTransform(off));
+
+ bool reused = c->getPxConvexMesh() != NULL;
+
+ PxConvexMesh* mesh = c->createPxConvexMesh(this, mScene->getPxPhysics(), mScene->getPxCooking());
+ if (mesh == NULL) {
+ if (c->decreaseRefCounter() <= 0)
+ PX_DELETE(c);
+ mConvexes.popBack();
+ continue;
+ }
+
+ if (!reused)
+ convexAdded(c, myShader); //mScene->getConvexRenderer().add(c);
+
+ PxShape *shape;
+ if (geom.convexes[i].isSphere)
+ {
+ shape = mScene->getPxPhysics()->createShape(
+ PxSphereGeometry(geom.convexes[i].radius),
+ *mScene->getPxDefaultMaterial(),
+ true
+ );
+ }
+ else
+ {
+ shape = mScene->getPxPhysics()->createShape(
+ PxConvexMeshGeometry(mesh),
+ *mScene->getPxDefaultMaterial(),
+ true
+ );
+ }
+ shape->setLocalPose(c->getLocalPose());
+
+ //shape->setContactOffset(mContactOffset);
+ //shape->setRestOffset(mRestOffset);
+
+ mScene->mapShapeToConvex(*shape, *c);
+
+ shapes.pushBack(shape);
+ }
+
+ if (shapes.empty())
+ return false;
+
+ createPxActor(shapes, pose, vel, omega);
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr, const PxVec3& scale, int matID, int surfMatID)
+{
+ const shdfnd::Array<PxVec3> &verts = mesh->getVertices();
+ const shdfnd::Array<PxVec3> &normals = mesh->getNormals();
+ const shdfnd::Array<PxVec2> &texcoords = mesh->getTexCoords();
+ const shdfnd::Array<PxU32> &indices = mesh->getIndices();
+
+ if (verts.empty() || indices.empty())
+ return;
+
+ if (submeshNr >= 0 && submeshNr >= (int)mesh->getSubMeshes().size())
+ return;
+
+ PxBounds3 bounds;
+ mesh->getBounds(bounds, submeshNr);
+ PxMat33 scaleMat(PxMat33::createDiagonal(scale));
+ bounds = PxBounds3::transformSafe(scaleMat, bounds);
+
+ PxVec3 dims = bounds.getDimensions() * 1.01f;
+ PxVec3 center = bounds.getCenter();
+
+ mScene->getCompoundCreator()->createBox(dims);
+ createFromGeometry(mScene->getCompoundCreator()->getGeometry(), pose, vel, omega, NULL, matID, surfMatID);
+ PxTransform trans(-center);
+
+ if (submeshNr < 0)
+ mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], indices.size(), &indices[0], &trans, &scale);
+ else {
+ const Mesh::SubMesh &sm = mesh->getSubMeshes()[submeshNr];
+ mConvexes[0]->setExplicitVisMeshFromTriangles(verts.size(), &verts[0], &normals[0], &texcoords[0], sm.numIndices, &indices[sm.firstIndex], &trans, &scale);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::createPxActor(shdfnd::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega)
+{
+ if (shapes.empty())
+ return false;
+
+ for(int i = 0; i < (int)shapes.size(); i++)
+ {
+ applyShapeTemplate(shapes[i]);
+ }
+
+ PxRigidDynamic* body = mScene->getPxPhysics()->createRigidDynamic(pose);
+ if (body == NULL)
+ return false;
+
+ //body->setSleepThreshold(getSleepingThresholdRB());
+#if 0
+ body->setWakeCounter(100000000000.f);
+#endif
+
+ mScene->getScene()->addActor(*body);
+
+ for (int i = 0; i < (int)shapes.size(); i++)
+ body->attachShape(*shapes[i]);
+
+
+
+ //KS - we clamp the mass in the range [minMass, maxMass]. This helps to improve stability
+ PxRigidBodyExt::updateMassAndInertia(*body, 1.0f);
+
+ /*const PxReal maxMass = 50.f;
+ const PxReal minMass = 1.f;
+
+ PxReal mass = PxMax(PxMin(maxMass, body->getMass()), minMass);
+ PxRigidBodyExt::setMassAndUpdateInertia(*body, mass);*/
+
+
+
+ body->setLinearVelocity(vel);
+ body->setAngularVelocity(omega);
+
+ /*if (vel.isZero() && omega.isZero())
+ {
+ body->putToSleep();
+ }*/
+
+ mPxActor = body;
+ for (int i = 0; i < (int)mConvexes.size(); i++)
+ mConvexes[i]->setPxActor(mPxActor);
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal)
+{
+ dist = PX_MAX_F32;
+ convexNr = -1;
+
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ float d;
+ PxVec3 n;
+ if (mConvexes[i]->rayCast(orig, dir, d, n)) {
+ if (d < dist) {
+ dist = d;
+ convexNr = i;
+ normal = n;
+ }
+ }
+ }
+ return convexNr >= 0;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::getRestBounds(PxBounds3 &bounds) const
+{
+ bounds.setEmpty();
+ PxBounds3 bi;
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ Convex *c = mConvexes[i];
+ PxBounds3 bi = c->getBounds();
+ bi = PxBounds3::transformSafe(c->getLocalPose(), bi);
+ bounds.include(bi);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::getWorldBounds(PxBounds3 &bounds) const
+{
+ bounds.setEmpty();
+ PxBounds3 bi;
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ mConvexes[i]->getWorldBounds(bi);
+ bounds.include(bi);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::getLocalBounds(PxBounds3 &bounds) const
+{
+ bounds.setEmpty();
+ PxBounds3 bi;
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ mConvexes[i]->getLocalBounds(bi);
+ bounds.include(bi);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+bool Compound::isAttached()
+{
+ if (mAttachmentBounds.empty())
+ return false;
+
+ PxBounds3 b;
+ for (int i = 0; i < (int)mConvexes.size(); i++) {
+ Convex *c = mConvexes[i];
+ b = c->getBounds();
+ b.minimum += c->getMaterialOffset();
+ b.maximum += c->getMaterialOffset();
+ for (int j = 0; j < (int)mAttachmentBounds.size(); j++) {
+ if (b.intersects(mAttachmentBounds[j]))
+ return true;
+ }
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::attach(const shdfnd::Array<PxBounds3> &bounds)
+{
+ mAttachmentBounds.resize(bounds.size());
+
+ PxTransform t = getPxActor()->getGlobalPose().getInverse();
+ for (int i = 0; i < (int)bounds.size(); i++) {
+ PxVec3 a = t.transform(bounds[i].minimum);
+ PxVec3 b = t.transform(bounds[i].maximum);
+ mAttachmentBounds[i].minimum = PxVec3(PxMin(a.x,b.x),PxMin(a.y,b.y),PxMin(a.z,b.z));
+ mAttachmentBounds[i].maximum = PxVec3(PxMax(a.x,b.x),PxMax(a.y,b.y),PxMax(a.z,b.z));
+ }
+
+ if (isAttached())
+ mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+}
+
+// --------------------------------------------------------------------------------------------
+void Compound::attachLocal(const shdfnd::Array<PxBounds3> &bounds)
+{
+ mAttachmentBounds.resize(bounds.size());
+
+ for (int i = 0; i < (int)bounds.size(); i++) {
+ mAttachmentBounds[i] = bounds[i];
+ }
+
+ if (isAttached())
+ mPxActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+}
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.h
new file mode 100644
index 00000000..3ab093a5
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundBase.h
@@ -0,0 +1,136 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef COMPOUNDBASE
+#define COMPOUNDBASE
+
+#define TECHNICAL_MODE 1
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <foundation/PxBounds3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+#include <PxRigidDynamic.h>
+#include <PsUserAllocated.h>
+
+
+class Shader;
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+class Convex;
+class Mesh;
+class SimScene;
+class CompoundGeometry;
+
+// -----------------------------------------------------------------------------------
+class Compound : public ::physx::shdfnd::UserAllocated
+{
+ friend class SimScene;
+ friend class Actor;
+protected:
+ Compound(SimScene* scene, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
+public:
+ virtual ~Compound();
+
+ virtual bool createFromConvexes(Convex** convexes, int numConvexes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true, int matID = 0, int surfMatID = 0);
+ bool createFromConvex(Convex* convex, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, bool copyConvexes = true, int matID = 0, int surfMatID = 0);
+ bool createFromGeometry(const CompoundGeometry &geom, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, Shader* myShader, int matID = 0, int surfMatID = 0);
+ bool createFromGeometry(const CompoundGeometry &geom, PxRigidDynamic* body, Shader* myShader, int matID = 0, int surfMatID = 0);
+ void createFromMesh(const Mesh *mesh, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega, int submeshNr = -1, const PxVec3& scale = PxVec3(1.f), int matID = 0, int surfMatID = 0);
+ //bool createFromXml(XMLParser *p, float scale, const PxTransform &trans, bool ignoreVisualMesh = false);
+
+ virtual void applyShapeTemplate(PxShape* /*shape*/) {}
+
+ bool rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, int &convexNr, PxVec3 &normal);
+ void setLifeFrames(int frames) { mLifeFrames = frames == 0 ? 1 : frames; }
+ int getLifeFrames() { return mLifeFrames; }
+
+
+ virtual void convexAdded(Convex* /*c*/, Shader* shader = NULL) {}
+ virtual void convexRemoved(Convex* /*c*/) {}
+
+ void attach(const shdfnd::Array<PxBounds3> &bounds);
+ void attachLocal(const shdfnd::Array<PxBounds3> &bounds);
+
+ const shdfnd::Array<Convex*>& getConvexes() const { return mConvexes; }
+ const shdfnd::Array<PxBounds3>& getAttachmentBounds() const { return mAttachmentBounds; }
+
+ PxRigidDynamic* getPxActor() { return mPxActor; }
+ void getWorldBounds(PxBounds3 &bounds) const;
+ void getLocalBounds(PxBounds3 &bounds) const;
+ void getRestBounds(PxBounds3 &bounds) const;
+
+ //void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
+ //Shader* getShader() const { return mShader; }
+ //const ShaderMaterial& getShaderMat() { return mShaderMat; }
+
+ void setKinematic(const PxVec3 &vel);
+ void step(float dt);
+
+ virtual void draw(bool /*useShader*/, bool /*debug*/ = false) {}
+
+ virtual void clear();
+
+ void setAdditionalImpactImpulse(float radial, float normal) {
+ mAdditionalImpactRadialImpulse = radial; mAdditionalImpactNormalImpulse = normal;
+ }
+ float getAdditionalImpactRadialImpulse() const { return mAdditionalImpactRadialImpulse; }
+ float getAdditionalImpactNormalImpulse() const { return mAdditionalImpactNormalImpulse; }
+
+ virtual void copyShaders(Compound*) {}
+
+protected:
+
+ bool isAttached();
+
+ bool createPxActor(shdfnd::Array<PxShape*> &shapes, const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega);
+
+ static void appendUniformSamplesOfConvexPolygon(PxVec3* vertices, int numV, float area, shdfnd::Array<PxVec3>& samples, shdfnd::Array<PxVec3>* normals = NULL);
+
+ virtual float getSleepingThresholdRB() {return 0.1f;}
+
+ struct Edge {
+ void init(int c0, int c1) {
+ this->c0 = c0; this->c1 = c1;
+ restLen = 0.0f;
+ deleted = false;
+ }
+ int c0, c1;
+ float restLen;
+ bool deleted;
+ };
+
+ shdfnd::Array<Convex*> mConvexes;
+ shdfnd::Array<Edge> mEdges;
+
+ SimScene *mScene;
+ Actor *mActor;
+ PxRigidDynamic *mPxActor;
+ PxVec3 mKinematicVel;
+ shdfnd::Array<PxBounds3> mAttachmentBounds;
+
+ //Shader *mShader;
+ //ShaderMaterial mShaderMat;
+
+ PxReal mContactOffset;
+ PxReal mRestOffset;
+
+ int mLifeFrames;
+
+ float mAdditionalImpactNormalImpulse;
+ float mAdditionalImpactRadialImpulse;
+
+ PxU32 mDepth; // fracture depth
+ PxVec3 mNormal; // normal use with mSheetFracture
+};
+
+}}}
+
+#endif
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.cpp
new file mode 100644
index 00000000..f01d0701
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.cpp
@@ -0,0 +1,844 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "CompoundCreatorBase.h"
+#include <algorithm>
+#include <foundation/PxAssert.h>
+
+#include "PhysXMacros.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxConvexMesh.h"
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+int CompoundCreator::tetFaceIds[4][3] = {{0,1,3},{1,2,3},{2,0,3},{0,2,1}};
+int CompoundCreator::tetEdgeVerts[6][2] = {{0,1},{1,2},{2,0},{0,3},{1,3},{2,3}};
+int CompoundCreator::tetFaceEdges[4][3] = {{0,4,3},{1,5,4},{2,3,5},{0,2,1}};
+
+#define CONVEX_THRESHOLD (PxPi + 0.05f)
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans)
+{
+ mGeom.clear();
+ CompoundGeometry::Convex c;
+ PxVec3 nr0,nr1,nz;
+ nz = PxVec3(0.0f, 0.0f, 1.0f);
+ PxVec3 p,n;
+ PxTransform t = PX_TRANSFORM_ID;
+ if (trans)
+ t = *trans;
+
+ shdfnd::Array<PxVec3> normals;
+
+ float dphi0 = PxTwoPi / (float)numSegs0;
+ float dphi1 = PxTwoPi / (float)numSegs1;
+ for (int i = 0; i < numSegs0; i++) {
+ nr0 = PxVec3(PxCos(i*dphi0), PxSin(i*dphi0), 0.0f);
+ nr1 = PxVec3(PxCos((i+1)*dphi0), PxSin((i+1)*dphi0), 0.0f);
+ mGeom.initConvex(c);
+ c.numVerts = 2*numSegs1;
+ normals.clear();
+ for (int j = 0; j < numSegs1; j++) {
+ p = nr0 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
+ mGeom.vertices.pushBack(t.transform(p));
+ n = nr0 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
+ normals.pushBack(t.rotate(n));
+
+ p = nr1 * (r0 + r1 * PxCos(j*dphi1)) + nz * r1 * PxSin(j*dphi1);
+ mGeom.vertices.pushBack(t.transform(p));
+ n = nr1 * (PxCos(j*dphi1)) + nz * PxSin(j*dphi1);
+ normals.pushBack(t.rotate(n));
+ }
+
+ c.numFaces = 2 + numSegs1;
+ mGeom.indices.pushBack(numSegs1); // face size
+ mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
+ for (int j = 0; j < numSegs1; j++)
+ mGeom.indices.pushBack(2*j);
+ mGeom.indices.pushBack(numSegs1); // face size
+ mGeom.indices.pushBack(CompoundGeometry::FF_INVISIBLE); // face flags
+ for (int j = 0; j < numSegs1; j++) {
+ mGeom.indices.pushBack(2*(numSegs1-1-j) + 1);
+ }
+ for (int j = 0; j < numSegs1; j++) {
+ int k = (j+1)%numSegs1;
+ mGeom.indices.pushBack(4); // face size
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
+ int i0 = 2*j;
+ int i1 = 2*j+1;
+ int i2 = 2*k+1;
+ int i3 = 2*k;
+ mGeom.indices.pushBack(i0);
+ mGeom.indices.pushBack(i1);
+ mGeom.indices.pushBack(i2);
+ mGeom.indices.pushBack(i3);
+ mGeom.normals.pushBack(normals[i0]);
+ mGeom.normals.pushBack(normals[i1]);
+ mGeom.normals.pushBack(normals[i2]);
+ mGeom.normals.pushBack(normals[i3]);
+ }
+ c.numNeighbors = 2;
+ mGeom.neighbors.pushBack((i + (numSegs0-1)) % numSegs0);
+ mGeom.neighbors.pushBack((i + 1) % numSegs0);
+ mGeom.convexes.pushBack(c);
+ }
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::createCylinder(float r, float h, int numSegs, const PxTransform *trans)
+{
+ PxTransform t = PX_TRANSFORM_ID;
+ if (trans)
+ t = *trans;
+
+ mGeom.clear();
+ CompoundGeometry::Convex c;
+ mGeom.initConvex(c);
+
+ float dphi = PxTwoPi / (float)numSegs;
+ c.numVerts = 2*numSegs;
+ mGeom.vertices.resize(c.numVerts);
+
+ for (int i = 0; i < numSegs; i++) {
+ PxVec3 p0(r * PxCos(i*dphi), r * PxSin(i*dphi), -0.5f * h);
+ PxVec3 p1(r * PxCos(i*dphi), r * PxSin(i*dphi), 0.5f * h);
+ mGeom.vertices[2*i] = t.transform(p0);
+ mGeom.vertices[2*i+1] = t.transform(p1);
+ }
+
+ c.numFaces = 2 + numSegs;
+
+ mGeom.indices.pushBack(numSegs);
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
+ for (int i = 0; i < numSegs; i++)
+ mGeom.indices.pushBack(2*(numSegs-1-i));
+ mGeom.indices.pushBack(numSegs);
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
+ for (int i = 0; i < numSegs; i++)
+ mGeom.indices.pushBack(2*i+1);
+
+ for (int i = 0; i < numSegs; i++) {
+ int j = (i+1) % numSegs;
+
+ PxVec3 n0(PxCos(i*dphi),PxSin(i*dphi),0.0f);
+ PxVec3 n1(PxCos(j*dphi),PxSin(j*dphi),0.0f);
+
+ n0 = t.rotate(n0);
+ n1 = t.rotate(n1);
+ //n0*=-1;
+ //n1*=-1;
+ mGeom.indices.pushBack(4);
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE | CompoundGeometry::FF_HAS_NORMALS);
+ mGeom.indices.pushBack(2*i);
+ mGeom.indices.pushBack(2*j);
+ mGeom.indices.pushBack(2*j+1);
+ mGeom.indices.pushBack(2*i+1);
+ mGeom.normals.pushBack(n0);
+ mGeom.normals.pushBack(n1);
+ mGeom.normals.pushBack(n1);
+ mGeom.normals.pushBack(n0);
+ }
+ mGeom.convexes.pushBack(c);
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::createBox(const PxVec3 &dims, const PxTransform *trans, bool clear)
+{
+ PxTransform t = PX_TRANSFORM_ID;
+ if (trans)
+ t = *trans;
+
+ if (clear)
+ mGeom.clear();
+ CompoundGeometry::Convex c;
+ mGeom.initConvex(c);
+
+ c.numVerts = 8;
+ mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, -0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, -0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, -0.5f * dims.y, 0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3( 0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
+ mGeom.vertices.pushBack(t.transform(PxVec3(-0.5f * dims.x, 0.5f * dims.y, 0.5f * dims.z)));
+
+ static int faceIds[6][4] = {{0,1,5,4},{1,2,6,5},{2,3,7,6},{3,0,4,7},{0,3,2,1},{4,5,6,7}};
+
+ c.numFaces = 6;
+ for (int i = 0; i < 6; i++) {
+ mGeom.indices.pushBack(4);
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
+ for (int j = 0; j < 4; j++)
+ mGeom.indices.pushBack(faceIds[i][j]);
+ }
+ mGeom.convexes.pushBack(c);
+}
+
+void CompoundCreator::createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset, bool clear)
+{
+
+ if (clear)
+ {
+ mGeom.clear();
+ }
+ CompoundGeometry::Convex c;
+ mGeom.initConvex(c);
+
+ PxConvexMesh* convexMesh = convexGeom.convexMesh;
+ c.numVerts = convexMesh->getNbVertices();
+ c.numFaces = convexMesh->getNbPolygons();
+
+ const PxVec3* verts = convexMesh->getVertices();
+ const PxU8* indexBuff = convexMesh->getIndexBuffer();
+
+
+ for (PxU32 a = 0; a < c.numVerts; ++a)
+ {
+ mGeom.vertices.pushBack(offset.transform(verts[a]));
+ }
+
+
+ for (PxU32 a = 0; a < c.numFaces; ++a)
+ {
+ PxHullPolygon data;
+ convexMesh->getPolygonData(a, data);
+
+ mGeom.indices.pushBack(data.mNbVerts);
+ mGeom.indices.pushBack(CompoundGeometry::FF_OBJECT_SURFACE);
+ const PxU32 indexBase = data.mIndexBase;
+ for (PxU32 b = 0; b < data.mNbVerts; ++b)
+ {
+ PxU32 ind = indexBuff[indexBase + b];
+ mGeom.indices.pushBack(ind);
+ }
+ }
+
+ mGeom.convexes.pushBack(c);
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::createSphere(const PxVec3 &dims, int resolution, const PxTransform *trans)
+{
+ PxTransform t = PX_TRANSFORM_ID;
+ if (trans)
+ t = *trans;
+
+ if (resolution < 2) resolution = 2;
+ int numSegs0 = 2*resolution;
+ int numSegs1 = resolution;
+
+ float rx = 0.5f * dims.x;
+ float ry = 0.5f * dims.y;
+ float rz = 0.5f * dims.z;
+
+ mGeom.clear();
+ CompoundGeometry::Convex c;
+ mGeom.initConvex(c);
+
+ if (rx == ry && rx == rz)
+ {
+ c.isSphere = true;
+ c.radius = rx;
+ }
+
+ float dphi = PxTwoPi / (float)numSegs0;
+ float dteta = PxPi / (float)numSegs1;
+ PxVec3 p, n;
+
+ for (int i = 1; i < numSegs1; i++) {
+ for (int j = 0; j < numSegs0; j++) {
+ float phi = j * dphi;
+ float teta = -PxHalfPi + i * dteta;
+ p = PxVec3(PxCos(phi)*PxCos(teta), PxSin(phi)*PxCos(teta), PxSin(teta));
+ mGeom.vertices.pushBack(PxVec3(p.x * rx, p.y * ry, p.z * rz));
+ }
+ }
+ int bottomNr = mGeom.vertices.size();
+ mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, -rz));
+ int topNr = mGeom.vertices.size();
+ mGeom.vertices.pushBack(PxVec3(0.0f, 0.0f, +rz));
+
+ c.numVerts = mGeom.vertices.size();
+
+ for (int i = 0; i < numSegs1-2; i++) {
+ for (int j = 0; j < numSegs0; j++) {
+ mGeom.indices.pushBack(4); // face size
+ mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
+ int i0 = i*numSegs0 + j;
+ int i1 = i*numSegs0 + (j+1)%numSegs0;
+ int i2 = (i+1)*numSegs0 + (j+1)%numSegs0;
+ int i3 = (i+1)*numSegs0 + j;
+ mGeom.indices.pushBack(i0);
+ mGeom.indices.pushBack(i1);
+ mGeom.indices.pushBack(i2);
+ mGeom.indices.pushBack(i3);
+ n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
+ n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
+ n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
+ n = mGeom.vertices[i3]; n.normalize(); mGeom.normals.pushBack(n);
+ c.numFaces++;
+ }
+ }
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < numSegs0; j++) {
+ mGeom.indices.pushBack(3); // face size
+ mGeom.indices.pushBack(CompoundGeometry::FF_HAS_NORMALS | CompoundGeometry::FF_OBJECT_SURFACE);
+ int i0,i1,i2;
+ if (i == 0) {
+ i0 = j;
+ i1 = bottomNr;
+ i2 = (j+1)%numSegs0;
+ }
+ else {
+ i0 = (numSegs1-2)*numSegs0 + j;
+ i1 = (numSegs1-2)*numSegs0 + (j+1)%numSegs0;
+ i2 = topNr;
+ }
+ mGeom.indices.pushBack(i0);
+ mGeom.indices.pushBack(i1);
+ mGeom.indices.pushBack(i2);
+ n = mGeom.vertices[i0]; n.normalize(); mGeom.normals.pushBack(n);
+ n = mGeom.vertices[i1]; n.normalize(); mGeom.normals.pushBack(n);
+ n = mGeom.vertices[i2]; n.normalize(); mGeom.normals.pushBack(n);
+ c.numFaces++;
+ }
+ }
+ mGeom.convexes.pushBack(c);
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices)
+{
+ mTetVertices = tetVerts;
+ mTetIndices = tetIndices;
+ deleteColors();
+
+ computeTetNeighbors();
+ computeTetEdges();
+ colorTets();
+ colorsToConvexes();
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::computeTetNeighbors()
+{
+ int numTets = mTetIndices.size() / 4;
+
+ struct TetFace {
+ void init(int i0, int i1, int i2, int faceNr, int tetNr) {
+ if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
+ if (i1 > i2) { int i = i1; i1 = i2; i2 = i; }
+ if (i0 > i1) { int i = i0; i0 = i1; i1 = i; }
+ this->i0 = i0; this->i1 = i1; this->i2 = i2;
+ this->faceNr = faceNr; this->tetNr = tetNr;
+ }
+ bool operator < (const TetFace &f) const {
+ if (i0 < f.i0) return true;
+ if (i0 > f.i0) return false;
+ if (i1 < f.i1) return true;
+ if (i1 > f.i1) return false;
+ return i2 < f.i2;
+ }
+ bool operator == (const TetFace &f) const {
+ return i0 == f.i0 && i1 == f.i1 && i2 == f.i2;
+ }
+ int i0,i1,i2;
+ int faceNr, tetNr;
+ };
+ shdfnd::Array<TetFace> faces(numTets * 4);
+
+ for (int i = 0; i < numTets; i++) {
+ int ids[4];
+ ids[0] = mTetIndices[4*i];
+ ids[1] = mTetIndices[4*i+1];
+ ids[2] = mTetIndices[4*i+2];
+ ids[3] = mTetIndices[4*i+3];
+ for (int j = 0; j < 4; j++) {
+ int i0 = ids[tetFaceIds[j][0]];
+ int i1 = ids[tetFaceIds[j][1]];
+ int i2 = ids[tetFaceIds[j][2]];
+ faces[4*i+j].init(i0,i1,i2, j, i);
+ }
+ }
+ std::sort(faces.begin(), faces.end());
+
+ mTetNeighbors.clear();
+ mTetNeighbors.resize(numTets * 4, -1);
+ int i = 0;
+ while (i < (int)faces.size()) {
+ TetFace &f0 = faces[i];
+ i++;
+ if (i < (int)faces.size() && faces[i] == f0) {
+ TetFace &f1 = faces[i];
+ mTetNeighbors[4*f0.tetNr + f0.faceNr] = f1.tetNr;
+ mTetNeighbors[4*f1.tetNr + f1.faceNr] = f0.tetNr;
+ while (i < (int)faces.size() && faces[i] == f0)
+ i++;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::computeTetEdges()
+{
+ int numTets = mTetIndices.size() / 4;
+
+ struct SortEdge {
+ void init(int i0, int i1, int edgeNr, int tetNr) {
+ if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
+ else { this->i0 = i1; this->i1 = i0; }
+ this->edgeNr = edgeNr; this->tetNr = tetNr;
+ }
+ bool operator < (const SortEdge &e) const {
+ if (i0 < e.i0) return true;
+ if (i0 > e.i0) return false;
+ return i1 < e.i1;
+ }
+ bool operator == (const SortEdge &e) const {
+ return i0 == e.i0 && i1 == e.i1;
+ }
+ int i0,i1;
+ int edgeNr, tetNr;
+ };
+ shdfnd::Array<SortEdge> edges(numTets * 6);
+
+ for (int i = 0; i < numTets; i++) {
+ int ids[4];
+ ids[0] = mTetIndices[4*i];
+ ids[1] = mTetIndices[4*i+1];
+ ids[2] = mTetIndices[4*i+2];
+ ids[3] = mTetIndices[4*i+3];
+ for (int j = 0; j < 6; j++) {
+ int i0 = ids[tetEdgeVerts[j][0]];
+ int i1 = ids[tetEdgeVerts[j][1]];
+ edges[6*i + j].init(i0,i1, j, i);
+ }
+ }
+ std::sort(edges.begin(), edges.end());
+
+ mTetEdgeNrs.clear();
+ mTetEdgeNrs.resize(numTets * 6, -1);
+ mTetEdges.clear();
+ mEdgeTetNrs.clear();
+ mEdgeTetAngles.clear();
+ TetEdge te;
+
+ struct ChainVert {
+ int adjVert0;
+ int adjVert1;
+ int tet0;
+ int tet1;
+ float dihed0;
+ float dihed1;
+ int mark;
+ };
+ ChainVert cv;
+ cv.mark = 0;
+ shdfnd::Array<ChainVert> chainVerts(mTetVertices.size(), cv);
+ shdfnd::Array<int> chainVertNrs;
+
+ int mark = 1;
+
+ int i = 0;
+ while (i < (int)edges.size()) {
+ SortEdge &e0 = edges[i];
+ int edgeNr = mTetEdges.size();
+ te.init(e0.i0, e0.i1);
+ te.firstTet = mEdgeTetNrs.size();
+ te.numTets = 0;
+ mark++;
+ chainVertNrs.clear();
+ do {
+ SortEdge &e = edges[i];
+ mTetEdgeNrs[6 * e.tetNr + e.edgeNr] = edgeNr;
+ int i2 = -1;
+ int i3 = -1;
+ for (int j = 0; j < 4; j++) {
+ int id = mTetIndices[4 * e.tetNr + j];
+ if (id != e0.i0 && id != e0.i1) {
+ if (i2 < 0) i2 = id;
+ else i3 = id;
+ }
+ }
+ PX_ASSERT(i2 >= 0 && i3 >= 0);
+
+ // dihedral angle at edge
+ PxVec3 &p0 = mTetVertices[e0.i0];
+ PxVec3 &p1 = mTetVertices[e0.i1];
+ PxVec3 &p2 = mTetVertices[i2];
+ PxVec3 &p3 = mTetVertices[i3];
+ PxVec3 n2 = (p1-p0).cross(p2-p0); n2.normalize();
+ if ((p3-p0).dot(n2) > 0.0f) n2 = -n2;
+ PxVec3 n3 = (p1-p0).cross(p3-p0); n3.normalize();
+ if ((p2-p0).dot(n3) > 0.0f) n3 = -n3;
+ float dot = n2.dot(n3);
+ float dihed = PxPi - PxAcos(dot);
+
+ // chain for ordering tets of edge correctly
+ ChainVert &cv2 = chainVerts[i2];
+ ChainVert &cv3 = chainVerts[i3];
+ if (cv2.mark != mark) { cv2.adjVert0 = -1; cv2.adjVert1 = -1; cv2.mark = mark; }
+ if (cv3.mark != mark) { cv3.adjVert0 = -1; cv3.adjVert1 = -1; cv3.mark = mark; }
+
+ if (cv2.adjVert0 < 0) { cv2.adjVert0 = i3; cv2.tet0 = e.tetNr; cv2.dihed0 = dihed; }
+ else { cv2.adjVert1 = i3; cv2.tet1 = e.tetNr; cv2.dihed1 = dihed; }
+ if (cv3.adjVert0 < 0) { cv3.adjVert0 = i2; cv3.tet0 = e.tetNr; cv3.dihed0 = dihed; }
+ else { cv3.adjVert1 = i2; cv3.tet1 = e.tetNr; cv3.dihed1 = dihed; }
+
+ chainVertNrs.pushBack(i2);
+ chainVertNrs.pushBack(i3);
+ i++;
+ }
+ while (i < (int)edges.size() && edges[i] == e0);
+
+ te.numTets = chainVertNrs.size() / 2;
+ // find chain start;
+ int startVertNr = -1;
+ for (int j = 0; j < (int)chainVertNrs.size(); j++) {
+ ChainVert &cv = chainVerts[chainVertNrs[j]];
+ if (cv.adjVert0 < 0 || cv.adjVert1 < 0) {
+ startVertNr = chainVertNrs[j];
+ break;
+ }
+ }
+ te.onSurface = startVertNr >= 0;
+ mTetEdges.pushBack(te);
+
+ int curr = startVertNr;
+ if (curr < 0) curr = chainVertNrs[0];
+ int prev = -1;
+
+ // collect adjacent tetrahedra
+ for (int j = 0; j < te.numTets; j++) {
+ ChainVert &cv = chainVerts[curr];
+ int next;
+ if (cv.adjVert0 == prev) {
+ next = cv.adjVert1;
+ mEdgeTetNrs.pushBack(cv.tet1);
+ mEdgeTetAngles.pushBack(cv.dihed1);
+ }
+ else {
+ next = cv.adjVert0;
+ mEdgeTetNrs.pushBack(cv.tet0);
+ mEdgeTetAngles.pushBack(cv.dihed0);
+ }
+ prev = curr;
+ curr = next;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
+bool CompoundCreator::tetHasColor(int tetNr, int color)
+{
+ int nr = mTetFirstColor[tetNr];
+ while (nr >= 0) {
+ if (mTetColors[nr].color == color)
+ return true;
+ nr = mTetColors[nr].next;
+ }
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+bool CompoundCreator::tetAddColor(int tetNr, int color)
+{
+ if (tetHasColor(tetNr, color))
+ return false;
+ Color c;
+ c.color = color;
+ c.next = mTetFirstColor[tetNr];
+
+ if (mTetColorsFirstEmpty <= 0) { // new entry
+ mTetFirstColor[tetNr] = mTetColors.size();
+ mTetColors.pushBack(c);
+ }
+ else { // take from empty list
+ int newNr = mTetColorsFirstEmpty;
+ mTetFirstColor[tetNr] = newNr;
+ mTetColorsFirstEmpty = mTetColors[newNr].next;
+ mTetColors[newNr] = c;
+ }
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+bool CompoundCreator::tetRemoveColor(int tetNr, int color)
+{
+ int nr = mTetFirstColor[tetNr];
+ int prev = -1;
+ while (nr >= 0) {
+ if (mTetColors[nr].color == color) {
+ if (prev < 0)
+ mTetFirstColor[tetNr] = mTetColors[nr].next;
+ else
+ mTetColors[prev].next = mTetColors[nr].next;
+
+ // add to empty list
+ mTetColors[nr].next = mTetColorsFirstEmpty;
+ mTetColorsFirstEmpty = nr;
+ return true;
+ }
+ prev = nr;
+ nr = mTetColors[nr].next;
+ }
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+int CompoundCreator::tetNumColors(int tetNr)
+{
+ int num = 0;
+ int nr = mTetFirstColor[tetNr];
+ while (nr >= 0) {
+ num++;
+ nr = mTetColors[nr].next;
+ }
+ return num;
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::deleteColors()
+{
+ mTetFirstColor.resize(mTetIndices.size()/4, -1);
+ mTetColors.clear();
+ mTetColorsFirstEmpty = -1;
+}
+
+// -----------------------------------------------------------------------------
+bool CompoundCreator::tryTet(int tetNr, int color)
+{
+ if (tetNr < 0)
+ return false;
+
+ //if (mTetColors[tetNr] >= 0)
+ // return false;
+
+ if (tetHasColor(tetNr, color))
+ return false;
+
+ mTestEdges.clear();
+ mAddedTets.clear();
+
+ tetAddColor(tetNr, color);
+ mAddedTets.pushBack(tetNr);
+
+ for (int i = 0; i < 6; i++)
+ mTestEdges.pushBack(mTetEdgeNrs[6*tetNr+i]);
+
+ bool failed = false;
+
+ while (mTestEdges.size() > 0) {
+ int edgeNr = mTestEdges[mTestEdges.size()-1];
+ mTestEdges.popBack();
+
+ TetEdge &e = mTetEdges[edgeNr];
+ bool anyOtherCol = false;
+ float sumAng = 0.0f;
+ for (int i = 0; i < e.numTets; i++) {
+ int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
+ if (tetHasColor(edgeTetNr, color))
+ sumAng += mEdgeTetAngles[e.firstTet + i];
+ else if (tetNumColors(edgeTetNr) > 0)
+ anyOtherCol = true;
+ }
+ if (sumAng < CONVEX_THRESHOLD)
+ continue;
+
+// if (e.onSurface || anyOtherCol) {
+ if (e.onSurface) {
+ failed = true;
+ break;
+ }
+
+ for (int i = 0; i < e.numTets; i++) {
+ int edgeTetNr = mEdgeTetNrs[e.firstTet + i];
+ if (!tetHasColor(edgeTetNr, color)) {
+ tetAddColor(edgeTetNr, color);
+ mAddedTets.pushBack(edgeTetNr);
+ for (int j = 0; j < 6; j++)
+ mTestEdges.pushBack(mTetEdgeNrs[6*edgeTetNr+j]);
+ }
+ }
+ }
+ if (failed) {
+ for (int i = 0; i < (int)mAddedTets.size(); i++)
+ tetRemoveColor(mAddedTets[i], color);
+ mAddedTets.clear();
+ return false;
+ }
+
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::colorTets()
+{
+ int numTets = mTetIndices.size() / 4;
+ deleteColors();
+
+ int color = 0;
+ shdfnd::Array<int> edges;
+ shdfnd::Array<int> faces;
+
+ for (int i = 0; i < numTets; i++) {
+ if (tetNumColors(i) > 0)
+ continue;
+
+ tetAddColor(i, color);
+ faces.clear();
+ faces.pushBack(4*i);
+ faces.pushBack(4*i+1);
+ faces.pushBack(4*i+2);
+ faces.pushBack(4*i+3);
+
+ while (faces.size() > 0) {
+ int faceNr = faces[faces.size()-1];
+ faces.popBack();
+
+ int adjTetNr = mTetNeighbors[faceNr];
+
+ if (adjTetNr < 0)
+ continue;
+
+ //if (tetNumColors(adjTetNr) > 0)
+ // continue;
+
+ if (!tryTet(adjTetNr, color))
+ continue;
+
+ for (int j = 0; j < (int)mAddedTets.size(); j++) {
+ int addedTet = mAddedTets[j];
+ for (int k = 0; k < 4; k++) {
+ int adj = mTetNeighbors[4*addedTet+k];
+ if (adj >= 0 && !tetHasColor(adj, color))
+ faces.pushBack(4*addedTet+k);
+ }
+ }
+ }
+ color++;
+ }
+}
+
+// -----------------------------------------------------------------------------
+void CompoundCreator::colorsToConvexes()
+{
+ mGeom.clear();
+
+ int numTets = mTetIndices.size() / 4;
+ int numColors = 0;
+ for (int i = 0; i < (int)mTetColors.size(); i++) {
+ int color = mTetColors[i].color;
+ if (color >= numColors)
+ numColors = color+1;
+ }
+
+ shdfnd::Array<bool> colorVisited(numColors, false);
+ shdfnd::Array<int> queue;
+ shdfnd::Array<int> globalToLocal(mTetVertices.size(), -1);
+
+ shdfnd::Array<int> tetMarks(numTets, 0);
+ shdfnd::Array<int> vertMarks(mTetVertices.size(), 0);
+ int mark = 1;
+
+ shdfnd::Array<int> colorToConvexNr;
+
+ CompoundGeometry::Convex c;
+
+ for (int i = 0; i < numTets; i++) {
+ int nr = mTetFirstColor[i];
+ while (nr >= 0) {
+ int color = mTetColors[nr].color;
+ nr = mTetColors[nr].next;
+
+ if (colorVisited[color])
+ continue;
+ colorVisited[color] = true;
+
+ if ((int)colorToConvexNr.size() <= color)
+ colorToConvexNr.resize(color+1, -1);
+ colorToConvexNr[color] = mGeom.convexes.size();
+
+ queue.clear();
+ queue.pushBack(i);
+
+ mGeom.initConvex(c);
+ mark++;
+ c.numVerts = 0;
+
+ // flood fill
+ while (!queue.empty()) {
+ int tetNr = queue[queue.size()-1];
+ queue.popBack();
+ if (tetMarks[tetNr] == mark)
+ continue;
+ tetMarks[tetNr] = mark;
+
+ for (int j = 0; j < 4; j++) {
+ int adjNr = mTetNeighbors[4*tetNr + j];
+ if (adjNr < 0 || !tetHasColor(adjNr, color)) {
+ // create new face
+ mGeom.indices.pushBack(3); // face size
+ int flags = 0;
+ if (adjNr < 0) flags |= CompoundGeometry::FF_OBJECT_SURFACE;
+ mGeom.indices.pushBack(flags);
+
+ for (int k = 0; k < 3; k++) {
+ int id = mTetIndices[4*tetNr + tetFaceIds[j][k]];
+ if (vertMarks[id] != mark) {
+ vertMarks[id] = mark;
+ globalToLocal[id] = c.numVerts;
+ c.numVerts++;
+ mGeom.vertices.pushBack(mTetVertices[id]);
+ }
+ mGeom.indices.pushBack(globalToLocal[id]);
+ }
+ c.numFaces++;
+ }
+ if (adjNr >= 0) {
+ // add neighbors
+ int colNr = mTetFirstColor[adjNr];
+ while (colNr >= 0) {
+ int adjColor = mTetColors[colNr].color;
+ colNr = mTetColors[colNr].next;
+ if (adjColor != color) {
+ bool isNew = true;
+ for (int k = 0; k < c.numNeighbors; k++) {
+ if (mGeom.neighbors[c.firstNeighbor+k] == adjColor) {
+ isNew = false;
+ break;
+ }
+ }
+ if (isNew) {
+ mGeom.neighbors.pushBack(adjColor);
+ c.numNeighbors++;
+ }
+ }
+ }
+ }
+ if (adjNr < 0 || !tetHasColor(adjNr, color) || tetMarks[adjNr] == mark)
+ continue;
+ queue.pushBack(adjNr);
+ }
+ }
+ mGeom.convexes.pushBack(c);
+ }
+ }
+
+ for (int i = 0; i < (int)mGeom.neighbors.size(); i++) {
+ if (mGeom.neighbors[i] >= 0)
+ mGeom.neighbors[i] = colorToConvexNr[mGeom.neighbors[i]];
+ }
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.h
new file mode 100644
index 00000000..cc614672
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundCreatorBase.h
@@ -0,0 +1,103 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef COMPOUND_CREATOR_BASE_H
+#define COMPOUND_CREATOR_BASE_H
+
+// Matthias M�ller-Fischer
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+#include "CompoundGeometryBase.h"
+
+namespace physx
+{
+ class PxConvexMeshGeometry;
+namespace fracture
+{
+namespace base
+{
+
+ class SimScene;
+// ---------------------------------------------------------------------------------------
+class CompoundCreator : public ::physx::shdfnd::UserAllocated {
+ friend class SimScene;
+public:
+ // direct
+ void createTorus(float r0, float r1, int numSegs0, int numSegs1, const PxTransform *trans = NULL);
+ void createCylinder(float r, float h, int numSegs, const PxTransform *trans = NULL);
+ void createBox(const PxVec3 &dims, const PxTransform *trans = NULL, bool clearShape = true);
+ void createSphere(const PxVec3 &dims, int resolution = 5, const PxTransform *trans = NULL);
+ void fromTetraMesh(const shdfnd::Array<PxVec3> &tetVerts, const shdfnd::Array<int> &tetIndices);
+
+ void createFromConvexMesh(const PxConvexMeshGeometry& convexGeom, PxTransform offset = PxTransform(PxIdentity), bool clear = true);
+
+
+ const CompoundGeometry &getGeometry() { return mGeom; }
+
+ virtual void debugDraw() {}
+
+protected:
+ CompoundCreator(SimScene* scene): mScene(scene) {}
+ virtual ~CompoundCreator() {}
+
+ SimScene* mScene;
+
+ static int tetFaceIds[4][3];
+ static int tetEdgeVerts[6][2];
+ static int tetFaceEdges[4][3];
+
+ void computeTetNeighbors();
+ void computeTetEdges();
+ void colorTets();
+ void colorsToConvexes();
+
+ bool tetHasColor(int tetNr, int color);
+ bool tetAddColor(int tetNr, int color);
+ bool tetRemoveColor(int tetNr, int color);
+ int tetNumColors(int tetNr);
+ void deleteColors();
+
+ bool tryTet(int tetNr, int color);
+
+ // from tet mesh
+ shdfnd::Array<PxVec3> mTetVertices;
+ shdfnd::Array<int> mTetIndices;
+ shdfnd::Array<int> mTetNeighbors;
+
+ shdfnd::Array<int> mTetFirstColor;
+ struct Color {
+ int color;
+ int next;
+ };
+ int mTetColorsFirstEmpty;
+ shdfnd::Array<Color> mTetColors;
+
+ struct TetEdge {
+ void init(int i0, int i1) { this->i0 = i0; this->i1 = i1; firstTet = 0; numTets = 0; onSurface = false; }
+ int i0, i1;
+ int firstTet, numTets;
+ bool onSurface;
+ };
+ shdfnd::Array<TetEdge> mTetEdges;
+ shdfnd::Array<int> mTetEdgeNrs;
+ shdfnd::Array<int> mEdgeTetNrs;
+ shdfnd::Array<float> mEdgeTetAngles;
+
+ shdfnd::Array<int> mAddedTets;
+ shdfnd::Array<int> mTestEdges;
+
+ // input
+ shdfnd::Array<PxVec3> mVertices;
+ shdfnd::Array<int> mIndices;
+
+ // output
+ CompoundGeometry mGeom;
+};
+
+}}}
+
+#endif
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.cpp
new file mode 100644
index 00000000..7051b72a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.cpp
@@ -0,0 +1,86 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "CompoundGeometryBase.h"
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// -------------------------------------------------------------------------------
+void CompoundGeometry::clear()
+{
+ convexes.clear();
+ vertices.clear();;
+ normals.clear();
+ indices.clear();
+ neighbors.clear();
+ planes.clear();
+}
+
+// -------------------------------------------------------------------------------
+bool CompoundGeometry::loadFromFile(const char * /*filename*/)
+{
+ return true;
+}
+
+// -------------------------------------------------------------------------------
+bool CompoundGeometry::saveFromFile(const char * /*filename*/)
+{
+ return true;
+}
+
+// -------------------------------------------------------------------------------
+void CompoundGeometry::initConvex(Convex &c)
+{
+ c.firstVert = vertices.size();
+ c.numVerts = 0;
+ c.firstNormal = normals.size();
+ c.firstIndex = indices.size();
+ c.numFaces = 0;
+ c.firstPlane = 0;
+ c.firstNeighbor = neighbors.size();
+ c.numNeighbors = 0;
+ c.radius = 0.f;
+ c.isSphere = false;
+}
+
+// -------------------------------------------------------------------------------
+void CompoundGeometry::derivePlanes()
+{
+ planes.clear();
+ PxPlane p;
+
+ for (int i = 0; i < (int)convexes.size(); i++) {
+ Convex &c = convexes[i];
+ c.firstPlane = planes.size();
+ int *ids = &indices[c.firstIndex];
+ PxVec3 *verts = &vertices[c.firstVert];
+ for (int j = 0; j < c.numFaces; j++) {
+ int num = *ids++;
+ *ids++; //int flags = *ids++;
+ if (num < 3)
+ p = PxPlane(1.0f, 0.0f, 0.0f, 0.0f);
+ else {
+ p.n = PxVec3(0.0f, 0.0f, 0.0f);
+ for (int k = 1; k < num-1; k++) {
+ const PxVec3 &p0 = verts[ids[0]];
+ const PxVec3 &p1 = verts[ids[k]];
+ const PxVec3 &p2 = verts[ids[k+1]];
+ p.n += (p1-p0).cross(p2-p1);
+ }
+ p.n.normalize();
+ p.d = p.n.dot(verts[ids[0]]);
+ }
+ planes.pushBack(p);
+ ids += num;
+ }
+ }
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.h
new file mode 100644
index 00000000..e5de3787
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/CompoundGeometryBase.h
@@ -0,0 +1,68 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef COMPOUND_GEOMETRY_BASE
+#define COMPOUND_GEOMETRY_BASE
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// -----------------------------------------------------------------------------------
+class CompoundGeometry : public ::physx::shdfnd::UserAllocated
+{
+public:
+ CompoundGeometry() {}
+ virtual ~CompoundGeometry() {}
+ bool loadFromFile(const char *filename);
+ bool saveFromFile(const char *filename);
+ void clear();
+ void derivePlanes();
+
+ virtual void debugDraw(int /*maxConvexes*/ = 0) const {}
+
+ struct Convex { // init using CompoundGeometry::initConvex()
+ int firstVert;
+ int numVerts;
+ int firstNormal; // one per face index! If not provided (see face flags) face normal is used
+ int firstIndex;
+ int numFaces;
+ int firstPlane;
+ int firstNeighbor;
+ int numNeighbors;
+ float radius;
+ bool isSphere;
+ };
+
+ void initConvex(Convex &c);
+
+ shdfnd::Array<Convex> convexes;
+ shdfnd::Array<PxVec3> vertices;
+ shdfnd::Array<PxVec3> normals; // one per face and vertex!
+ // face size, face flags, id, id, .., face size, face flags, id ..
+ shdfnd::Array<int> indices;
+ shdfnd::Array<int> neighbors;
+
+ shdfnd::Array<PxPlane> planes; // derived for faster cuts
+
+ enum FaceFlags {
+ FF_OBJECT_SURFACE = 1,
+ FF_HAS_NORMALS = 2,
+ FF_INVISIBLE = 4,
+ FF_NEW = 8,
+ };
+};
+
+}
+}
+}
+
+#endif
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.cpp
new file mode 100644
index 00000000..7a6358b6
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.cpp
@@ -0,0 +1,1316 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxDefaultStreams.h"
+#include "PxShape.h"
+#include "foundation/PxMath.h"
+#include "PxRigidDynamic.h"
+#include "PxConvexMesh.h"
+#include "foundation/PxMat44.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxVec2.h"
+
+#include "CompoundGeometryBase.h"
+#include "SimSceneBase.h"
+#include "PolygonTriangulatorBase.h"
+
+#include "ConvexBase.h"
+
+#include "PhysXMacros.h"
+
+class physx::PxPhysics;
+class physx::PxCooking;
+class physx::PxActor;
+class physx::PxScene;
+class physx::PxConvexMesh;
+
+#define COOK_TRIANGLES 1
+
+#include <algorithm>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// --------------------------------------------------------------------------------------------
+Convex::Convex(SimScene* scene)
+{
+ mScene = scene;
+ mPxConvexMesh = NULL;
+ mPxActor = NULL;
+ mLocalPose = PX_TRANSFORM_ID;
+ mParent = NULL;
+ mNewConvex = NULL;
+ mRefCounter = 0;
+ mIsFarConvex = false;
+ clear();
+}
+
+// --------------------------------------------------------------------------------------------
+Convex::~Convex()
+{
+ clear();
+ if (mNewConvex != NULL)
+ PX_DELETE(mNewConvex);
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::clear()
+{
+ mFaces.clear();
+ mIndices.clear();
+ mVertices.clear();
+ mNormals.clear();
+ mPlanes.clear();
+
+ mVisVertices.clear();
+ mVisNormals.clear();
+ mVisTangents.clear();
+ mVisTexCoords.clear();
+ mVisTriIndices.clear();
+
+ mHasExplicitVisMesh = false;
+ mIsGhostConvex = false;
+ mVisPolyStarts.clear();
+ mVisPolyIndices.clear();
+ mVisPolyNeighbors.clear();
+
+ if (mPxConvexMesh != NULL)
+ mPxConvexMesh->release();
+
+ mPxConvexMesh = NULL;
+ mPxActor = NULL;
+ mLocalPose = PX_TRANSFORM_ID;
+
+ mBounds.setEmpty();
+ mMaterialOffset = PxVec3(0.0f, 0.0f, 0.0f);
+ mTexScale = 1.0f;
+
+ mUse2dTexture = false;
+ mIndestructible = false;
+ mMaterialId = 0;
+ mSurfaceMaterialId = 0;
+ mModelIslandNr = 0;
+
+ mVolume = 0.0f;
+ mVolumeDirty = true;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::createFromConvex(const Convex *convex, const PxTransform *trans, int matID, int surfMatID)
+{
+ clear();
+ mVertices = convex->mVertices;
+ mFaces = convex->mFaces;
+ clearFraceFlags(CompoundGeometry::FF_NEW);
+
+ mIndices = convex->mIndices;
+ mNormals = convex->mNormals;
+ mMaterialOffset = convex->mMaterialOffset;
+ mTexScale = convex->mTexScale;
+ mIsGhostConvex = convex->mIsGhostConvex;
+ mLocalPose = convex->mLocalPose;
+ mMaterialId = matID;
+ mSurfaceMaterialId = surfMatID;
+
+ if (trans != NULL) {
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mVertices[i] = trans->transform(mVertices[i]);
+ for (int i = 0; i < (int)mNormals.size(); i++)
+ mNormals[i] = trans->rotate(mNormals[i]);
+ mMaterialOffset -= trans->p;
+ }
+ finalize();
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::transform(const PxMat44 &trans)
+{
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mVertices[i] = trans.transform(mVertices[i]);
+ for (int i = 0; i < (int)mNormals.size(); i++)
+ mNormals[i] = trans.rotate(mNormals[i]);
+ mMaterialOffset -= trans.getPosition();
+
+ if (mHasExplicitVisMesh) {
+ for (int i = 0; i < (int)mVisVertices.size(); i++)
+ mVisVertices[i] = trans.transform(mVisVertices[i]);
+ for (int i = 0; i < (int)mVisNormals.size(); i++)
+ mVisNormals[i] = trans.rotate(mVisNormals[i]);
+ }
+ finalize();
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans, int matID, int surfMatID)
+{
+ clear();
+ const CompoundGeometry::Convex &c = geom.convexes[convexNr];
+
+ PxMat44 t = PX_MAT44_ID;
+
+ if (trans)
+ t = *trans;
+
+ mVertices.resize(c.numVerts);
+ for (int i = 0; i < c.numVerts; i++)
+ mVertices[i] = t.transform(geom.vertices[c.firstVert + i]);
+
+ mFaces.resize(c.numFaces);
+ int num = 0;
+ const int *id = &geom.indices[c.firstIndex];
+ const PxVec3 *normals = (geom.normals.size() > 0) ? &geom.normals[c.firstNormal] : NULL;
+ mMaterialId = matID;
+ mSurfaceMaterialId = surfMatID;
+
+ for (int i = 0; i < c.numFaces; i++) {
+ Face &f = mFaces[i];
+ f.init();
+ f.firstIndex = num;
+ f.numIndices = *id++;
+ f.flags = *id++;
+ for (int j = 0; j < f.numIndices; j++)
+ mIndices.pushBack(*id++);
+ if (f.flags & CompoundGeometry::FF_HAS_NORMALS) {
+ f.firstNormal = mNormals.size();
+ for (int j = 0; j < f.numIndices; j++) {
+ mNormals.pushBack(t.rotate(*normals));
+ normals++;
+ }
+ }
+ num += f.numIndices;
+ }
+ finalize();
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::setPxActor(PxRigidActor *actor)
+{
+ mPxActor = actor;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::setLocalPose(const PxTransform &pose)
+{
+ mLocalPose = pose;
+}
+
+// --------------------------------------------------------------------------------------------
+PxVec3 Convex::getCenter() const
+{
+ PxVec3 center(0.0f, 0.0f, 0.0f);
+
+ if (mVertices.empty())
+ return center;
+
+ int numVerts = mVertices.size();
+ for (int i = 0; i < numVerts; i++)
+ center += mVertices[i];
+ center /= (float)numVerts;
+
+ return center;
+}
+
+// --------------------------------------------------------------------------------------------
+PxVec3 Convex::centerAtZero()
+{
+ PxVec3 center = getCenter();
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mVertices[i] -= center;
+ finalize();
+ return center;
+}
+
+// --------------------------------------------------------------------------------------------
+PxTransform Convex::getGlobalPose() const
+{
+ if (mPxActor == NULL)
+ return mLocalPose;
+ else
+ return mPxActor->getGlobalPose() * mLocalPose;
+}
+
+// --------------------------------------------------------------------------------------------
+PxTransform Convex::getLocalPose() const
+{
+ return mLocalPose;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::rayCast(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const
+{
+ PxVec3 o,d;
+ PxTransform pose = getGlobalPose();
+ d = pose.rotateInv(dir);
+ o = pose.transformInv(orig);
+
+ if (mHasExplicitVisMesh)
+ return rayCastVisMesh(o,d, dist, normal);
+ else
+ return rayCastConvex(o,d, dist, normal);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const
+{
+ float maxEntry = -PX_MAX_F32;
+ float minExit = PX_MAX_F32;
+ normal = PxVec3(0.0f, 1.0f, 0.0f);
+
+ for (int i = 0; i < (int)mPlanes.size(); i++) {
+ const PxPlane &plane = mPlanes[i];
+ float dot = plane.n.dot(dir);
+ if (dot == 0.0f)
+ continue;
+
+ float t = (plane.d - orig.dot(plane.n)) / dot;
+ if (dot < 0.0f) {
+ if (t > maxEntry) {
+ maxEntry = t;
+ normal = plane.n;
+ }
+ }
+ else {
+ minExit = PxMin(minExit, t);
+ }
+ }
+
+ if (maxEntry > minExit) {
+ dist = PX_MAX_F32;
+ return false;
+ }
+
+ dist = maxEntry;
+ normal.normalize();
+ return dist >= 0.0f;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const
+{
+ normal = PxVec3(0.0f, 1.0f, 0.0f);
+ dist = PX_MAX_F32;
+ int minTri = -1;
+
+ for (int i = 0; i < (int)mVisTriIndices.size(); i += 3) {
+ const PxVec3 &p0 = mVisVertices[mVisTriIndices[i]];
+ const PxVec3 &p1 = mVisVertices[mVisTriIndices[i+1]];
+ const PxVec3 &p2 = mVisVertices[mVisTriIndices[i+2]];
+ PxVec3 n = (p1-p0).cross(p2-p0);
+ float t = dir.dot(n);
+ if (t >= 0.0f)
+ continue;
+ t = n.dot(p0 - orig) / t;
+ if (t < 0.0f)
+ continue;
+
+ // hit inside triangle?
+ PxVec3 hit = orig + t * dir;
+ float b2 = (p1-p0).cross(hit-p0).dot(n);
+ float b0 = (p2-p1).cross(hit-p1).dot(n);
+ float b1 = (p0-p2).cross(hit-p2).dot(n);
+ if (b0 < 0.0f || b1 < 0.0f || b2 < 0.0f)
+ continue;
+
+ float d = (orig - hit).magnitude();
+
+ if (d < dist) {
+ dist = d;
+ minTri = i / 3;
+ normal = n;
+ }
+ }
+ normal.normalize();
+ return minTri >= 0;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const
+{
+ PxVec3 p = getGlobalPose().transformInv(pos);
+
+ float minDist = PX_MAX_F32;
+ int minPlane = -1;
+
+ for (int i = 0; i < (int)mPlanes.size(); i++) {
+ const PxPlane &plane = mPlanes[i];
+ float dist = plane.d - p.dot(plane.n) + r;
+ if (dist < 0.0f)
+ return false;
+ if (dist < minDist) {
+ minDist = dist;
+ minPlane = i;
+ }
+ }
+
+ if (minPlane < 0)
+ return false;
+ else {
+ PxPlane plane = mPlanes[minPlane];
+ surfaceNormal = plane.n;
+ penetration = minDist;
+ surfaceVel = PxVec3(0.0f, 0.0f, 0.0f);
+
+ if (mPxActor != NULL)
+ {
+ PxRigidDynamic *actor = mPxActor->is<PxRigidDynamic>();
+ if (actor != NULL) {
+ surfaceNormal = getGlobalPose().rotate(surfaceNormal);
+ surfaceVel = actor->getLinearVelocity() + actor->getAngularVelocity().cross(surfaceNormal * plane.d);
+ }
+ }
+ return true;
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::finalize()
+{
+ updateBounds();
+ updatePlanes();
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::updateBounds()
+{
+ mBounds.setEmpty();
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mBounds.include(mVertices[i]);
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::updatePlanes()
+{
+ int numFaces = mFaces.size();
+ mPlanes.resize(numFaces);
+
+ for (int i = 0; i < numFaces; i++) {
+ Face &f = mFaces[i];
+ if (f.numIndices < 3) { // should not happen
+ mPlanes[i].n = PxVec3(0.0f, 1.0f, 0.0f);
+ mPlanes[i].d = 0.0f;
+ continue;
+ }
+ PxVec3 n(0.0f, 0.0f, 0.0f);
+ PxVec3 &p0 = mVertices[mIndices[f.firstIndex]];
+ for (int j = 1; j < f.numIndices-1; j++) {
+ PxVec3 &p1 = mVertices[mIndices[f.firstIndex+j]];
+ PxVec3 &p2 = mVertices[mIndices[f.firstIndex+j+1]];
+ n += (p1-p0).cross(p2-p0);
+ }
+ n.normalize();
+ mPlanes[i].n = n;
+ mPlanes[i].d = mPlanes[i].n.dot(p0);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::getWorldBounds(PxBounds3 &bounds) const
+{
+ bounds = PxBounds3::transformSafe(getGlobalPose(), mBounds);
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::getLocalBounds(PxBounds3 &bounds) const
+{
+ bounds = mBounds;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty)
+{
+ empty = false;
+
+ PxMat33 M(trans.getBasis(0), trans.getBasis(1), trans.getBasis(2));
+ PxMat33 M1 = M.getInverse();
+ PxMat33 M1T = M1.getTranspose();
+
+ for (int i = 0; i < numPlanes; i++) {
+ PxPlane p;
+ p.n = M1T.transform(planes[i].n);
+ p.d = planes[i].d + trans.getPosition().dot(p.n);
+ float len = p.n.normalize();
+ p.d /= len;
+ cut(p.n, p.d, empty);
+ if (empty)
+ return;
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag)
+{
+ float eps = 1e-4f;
+
+ //bool pos = false;
+ //bool neg = false;
+
+ PxVec3 pn = localPlaneN;
+ float pd = localPlaneD;
+
+ // does the plane pass through the convex?
+ float minD = PX_MAX_F32;
+ float maxD = -PX_MAX_F32;
+
+ for (int i = 0; i < (int)mVertices.size(); i++) {
+ float dot = mVertices[i].dot(pn);
+ if (dot < minD) minD = dot;
+ if (dot > maxD) maxD = dot;
+ }
+
+ cutEmpty = minD > pd - eps;
+ if (cutEmpty || maxD < pd + eps)
+ return false;
+
+ // new: avoid singular cases
+ for (int i = 0; i < (int)mVertices.size(); i++) {
+ float dot = mVertices[i].dot(pn);
+ if (fabs(dot - pd) < 1e-5f)
+ pd += 1e-5f;
+ }
+
+ // member so the memory does not have to be re-allocated for every cut
+ if (mNewConvex == NULL)
+ mNewConvex = mScene->createConvex();
+ mNewConvex->clear();
+
+ // create vertices
+ int numFaces = mFaces.size();
+ shdfnd::Array<int> newNr(mVertices.size(), -1);
+
+ struct Cut {
+ void set(int i0, int i1, int newId) {
+ this->i0 = i0; this->i1 = i1; this->newId = newId; next = -1;
+ }
+ bool is(int i0, int i1) {
+ return (this->i0 == i0 && this->i1 == i1) || (this->i0 == i1 && this->i1 == i0);
+ }
+ int i0, i1;
+ int newId;
+ int next;
+ };
+ shdfnd::Array<Cut> cuts;
+
+ for (int i = 0; i < numFaces; i++) {
+ Face &f = mFaces[i];
+ int *ids = &mIndices[f.firstIndex];
+ mNewConvex->mFaces.resize(mNewConvex->mFaces.size() + 1);
+ Face &newFace = mNewConvex->mFaces[mNewConvex->mFaces.size()-1];
+ newFace.init();
+ newFace.flags = f.flags;
+ newFace.firstIndex = mNewConvex->mIndices.size();
+ bool hasNormals = (f.flags & CompoundGeometry::FF_HAS_NORMALS) != 0;
+ if (hasNormals)
+ newFace.firstNormal = mNewConvex->mNormals.size();
+
+ int cutNrs[2];
+ int numCuts = 0;
+ bool winding = false;
+
+ for (int j = 0; j < f.numIndices; j++) {
+ int j1 = (j+1)%f.numIndices;
+ int i0 = ids[j];
+ int i1 = ids[j1];
+ PxVec3 &p0 = mVertices[i0];
+ PxVec3 &p1 = mVertices[i1];
+ PxVec3 n0,n1;
+ if (hasNormals) {
+ n0 = mNormals[f.firstNormal+j];
+ n1 = mNormals[f.firstNormal+j1];
+ }
+ bool sign0 = p0.dot(pn) >= pd;
+ bool sign1 = p1.dot(pn) >= pd;
+ if (!sign0) {
+ if (newNr[i0] < 0) {
+ newNr[i0] = mNewConvex->mVertices.size();
+ mNewConvex->mVertices.pushBack(p0);
+ }
+ mNewConvex->mIndices.pushBack(newNr[i0]);
+ if (hasNormals)
+ mNewConvex->mNormals.pushBack(n0);
+ if (numCuts == 1)
+ winding = true;
+ }
+
+ // cut?
+ if (sign0 != sign1) {
+ // do we have the cut vertex already?
+ int totalCuts = cuts.size();
+ int k = 0;
+ while (k < totalCuts && !cuts[k].is(i0,i1))
+ k++;
+
+ float t = (pd - p0.dot(pn)) / (p1 - p0).dot(pn);
+ // create new cut vertex
+ if (k == totalCuts) {
+ cuts.resize(totalCuts+1);
+ cuts[totalCuts].set(i0, i1, mNewConvex->mVertices.size());
+ PxVec3 p = p0 + (p1-p0) * t;
+ mNewConvex->mVertices.pushBack(p);
+ }
+ mNewConvex->mIndices.pushBack(cuts[k].newId);
+ if (hasNormals) {
+ PxVec3 n = n0 + (n1-n0) * t;
+ n.normalize();
+ mNewConvex->mNormals.pushBack(n);
+ }
+ if (numCuts >= 2) { // numerical problems!
+ cutEmpty = true;
+ return false;
+ }
+ cutNrs[numCuts] = k;
+ numCuts++;
+ }
+ }
+
+ if (numCuts == 1) { // numerical problems!
+ cutEmpty = true;
+ return false;
+ }
+
+ if (numCuts == 2) {
+ Cut &cut0 = cuts[cutNrs[0]];
+ Cut &cut1 = cuts[cutNrs[1]];
+ if (winding) {
+ cut0.next = cutNrs[1];
+ }
+ else {
+ cut1.next = cutNrs[0];
+ }
+ }
+
+ // check whether the new convex got a new face
+
+ newFace.numIndices = mNewConvex->mIndices.size() - newFace.firstIndex;
+ if (newFace.numIndices == 0)
+ mNewConvex->mFaces.popBack();
+ else if (newFace.numIndices < 3) {
+ cutEmpty = true;
+ return false;
+ }
+ }
+
+ // create closing face
+ Face closingFace;
+ closingFace.init();
+ closingFace.firstIndex = mNewConvex->mIndices.size();
+
+ int nr = 0;
+ for (int i = 0; i < (int)cuts.size(); i++) {
+ mNewConvex->mIndices.pushBack(cuts[nr].newId);
+ closingFace.numIndices++;
+ nr = cuts[nr].next;
+
+ if (nr < 0) { // numerical problems
+ cutEmpty = true;
+ return false;
+ }
+ }
+ if (closingFace.numIndices < 3) {
+ cutEmpty = true;
+ return false;
+ }
+ if (setNewFaceFlag)
+ closingFace.flags |= CompoundGeometry::FF_NEW;
+
+ mNewConvex->mFaces.pushBack(closingFace);
+
+ mVertices = mNewConvex->mVertices;
+ mIndices = mNewConvex->mIndices;
+ mFaces = mNewConvex->mFaces;
+ mNormals = mNewConvex->mNormals;
+ mVolumeDirty = true;
+ finalize();
+
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+PxConvexMesh* Convex::createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking)
+{
+ mParent = parent;
+
+ if (mVertices.empty())
+ return NULL;
+
+ if (mPxConvexMesh != NULL)
+ return mPxConvexMesh;
+
+ mPxConvexMesh = NULL;
+ mPxActor = NULL;
+
+#if COOK_TRIANGLES
+ // create tri mesh
+ // in this tri mesh vertices are shared in contrast to the tri mesh for rendering
+ shdfnd::Array<PxU32> indices;
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ Face &f = mFaces[i];
+ if (f.numIndices < 3)
+ continue;
+ int *ids = &mIndices[f.firstIndex];
+ for (int j = 1; j < f.numIndices-1; j++) {
+ indices.pushBack(ids[0]);
+ indices.pushBack(ids[j]);
+ indices.pushBack(ids[j+1]);
+ }
+ }
+
+ PxConvexMeshDesc meshDesc;
+ meshDesc.setToDefault();
+ meshDesc.points.count = mVertices.size();
+ meshDesc.points.stride = sizeof(PxVec3);
+ meshDesc.points.data = &mVertices[0];
+
+ meshDesc.flags |= PxConvexFlag::eCOMPUTE_CONVEX;
+#else
+ shdfnd::Array<PxHullPolygon> polygons;
+ polygons.reserve(mFaces.size());
+ if (mPlanes.size() != mFaces.size())
+ updatePlanes();
+
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ Face &f = mFaces[i];
+ if (f.numIndices < 3)
+ continue;
+ PxHullPolygon p;
+ p.mIndexBase = (physx::PxU16)f.firstIndex;
+ p.mNbVerts = (physx::PxU16)f.numIndices;
+ p.mPlane[0] = mPlanes[i].n.x;
+ p.mPlane[1] = mPlanes[i].n.y;
+ p.mPlane[2] = mPlanes[i].n.z;
+ p.mPlane[3] = -mPlanes[i].d;
+ polygons.pushBack(p);
+ }
+
+ PxConvexMeshDesc meshDesc;
+ meshDesc.setToDefault();
+ meshDesc.flags |= PxConvexFlag::eDISABLE_MESH_VALIDATION;
+ meshDesc.points.count = mVertices.size();
+ meshDesc.points.stride = sizeof(PxVec3);
+ meshDesc.points.data = &mVertices[0];
+ meshDesc.indices.count = mIndices.size();
+ meshDesc.indices.data = &mIndices[0];
+ meshDesc.indices.stride = sizeof(PxU32);
+ meshDesc.polygons.count = mFaces.size();
+ meshDesc.polygons.data = &polygons[0];
+ meshDesc.polygons.stride = sizeof(PxHullPolygon);
+
+#endif
+
+ // Cooking from memory
+ PxDefaultMemoryOutputStream outBuffer;
+ if (!pxCooking->cookConvexMesh(meshDesc, outBuffer))
+ return NULL;
+
+ PxDefaultMemoryInputData inBuffer(outBuffer.getData(), outBuffer.getSize());
+ mPxConvexMesh = pxPhysics->createConvexMesh(inBuffer);
+
+ return mPxConvexMesh;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::setMaterialOffset(const PxVec3 &offset)
+{
+ if (mHasExplicitVisMesh) {
+ for (int i = 0; i < (int)mVisVertices.size(); i++)
+ mVisVertices[i] += mMaterialOffset - offset;
+ }
+ mMaterialOffset = offset;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::createVisMeshFromConvex()
+{
+ // vertices are duplicated for each face to get sharp edges with multiple normals
+ mHasExplicitVisMesh = false;
+ mVisVertices.clear();
+ mVisNormals.clear();
+ mVisTangents.clear();
+ mVisTriIndices.clear();
+ mVisTexCoords.clear();
+ PxVec3 n;
+ PxVec3 t0, t1;
+
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ Face &f = mFaces[i];
+ if (f.flags & CompoundGeometry::FF_INVISIBLE)
+ continue;
+ if (f.numIndices < 3)
+ continue;
+ // normal
+ int *ids = &mIndices[f.firstIndex];
+ if (!(f.flags & CompoundGeometry::FF_HAS_NORMALS)) {
+ n = (mVertices[ids[1]] - mVertices[ids[0]]).cross(mVertices[ids[2]] - mVertices[ids[0]]);
+ n.normalize();
+ }
+ // tangents
+ if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z))
+ t0 = PxVec3(1.0f, 0.0f, 0.0f);
+ else if (fabs(n.y) < fabs(n.z))
+ t0 = PxVec3(0.0f, 1.0f, 0.0);
+ else
+ t0 = PxVec3(0.0f, 0.0f, 1.0f);
+ t1 = n.cross(t0);
+ t1.normalize();
+ t0 = t1.cross(n);
+
+ int firstVertNr = mVisVertices.size();
+ for (int j = 0; j < f.numIndices; j++) {
+ PxVec3 p = mVertices[ids[j]];
+ mVisVertices.pushBack(p);
+ if (f.flags & CompoundGeometry::FF_HAS_NORMALS) {
+ mVisNormals.pushBack(mNormals[f.firstNormal + j]);
+ mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // on surface, not bump map
+ }
+ else {
+ mVisNormals.pushBack(n);
+ mVisTangents.pushBack(t0); // internal face, bump map
+ }
+ mVisTexCoords.pushBack(p.dot(t0) * mTexScale);
+ mVisTexCoords.pushBack(p.dot(t1) * mTexScale);
+ }
+ for (int j = 1; j < f.numIndices-1; j++) {
+ mVisTriIndices.pushBack(firstVertNr);
+ mVisTriIndices.pushBack(firstVertNr+j);
+ mVisTriIndices.pushBack(firstVertNr+j+1);
+ }
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+struct Edge {
+ // not using indices for edge match but positions
+ // so duplicated vertices are handled as one vertex
+ bool smaller(const PxVec3 &v0, const PxVec3 &v1) const {
+ if (v0.x < v1.x) return true;
+ if (v0.x > v1.x) return false;
+ if (v0.y < v1.y) return true;
+ if (v0.y > v1.y) return false;
+ return (v0.z < v1.z);
+ }
+ void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) {
+ if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; }
+ else { this->v0 = v1; this->v1 = v0; }
+ this->faceNr = faceNr; this->edgeNr = edgeNr;
+ }
+ bool operator < (const Edge &e) const {
+ if (smaller(v0, e.v0)) return true;
+ if (v0 == e.v0 && smaller(v1, e.v1)) return true;
+ return false;
+ }
+ bool operator == (const Edge &e) const { return v0 == e.v0 && v1 == e.v1; }
+ PxVec3 v0,v1;
+ int faceNr, edgeNr;
+};
+
+// --------------------------------------------------------------------------------------------
+bool Convex::computeVisMeshNeighbors()
+{
+ int numIndices = mVisPolyIndices.size();
+ int numPolygons = mVisPolyStarts.size()-1;
+
+ shdfnd::Array<Edge> edges(numIndices);
+
+ for (int i = 0; i < numPolygons; i++) {
+ int first = mVisPolyStarts[i];
+ int num = mVisPolyStarts[i+1] - first;
+ for (int j = 0; j < num; j++) {
+ edges[first + j].set(
+ mVisVertices[mVisPolyIndices[first + j]],
+ mVisVertices[mVisPolyIndices[first + (j+1)%num]], i, first + j);
+ }
+ }
+ std::sort(edges.begin(), edges.end());
+
+ mVisPolyNeighbors.resize(numIndices);
+ bool manifold = true;
+ int i = 0;
+ while (i < (int)edges.size()) {
+ Edge &e0 = edges[i];
+ i++;
+ if (i < (int)edges.size() && edges[i] == e0) {
+ Edge &e1 = edges[i];
+ mVisPolyNeighbors[e0.edgeNr] = e1.faceNr;
+ mVisPolyNeighbors[e1.edgeNr] = e0.faceNr;
+ i++;
+ }
+ while (i < (int)edges.size() && edges[i] == e0) {
+ manifold = false;
+ i++;
+ }
+ }
+ return manifold;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords,
+ int numIndices, const PxU32 *indices, PxTransform *trans, const PxVec3* scale)
+{
+ mHasExplicitVisMesh = true;
+
+ // reduce to vertices referenced by indices
+ // needed if submesh is provided
+ shdfnd::Array<int> oldToNew(numVertices, -1);
+ mVisVertices.clear();
+ mVisNormals.clear();
+ mVisTangents.clear();
+ mVisTexCoords.clear();
+
+ const float scaleMagn = scale ? scale->magnitude() : 1.f;
+
+ for (int i = 0; i < numIndices; i++) {
+ int id = indices[i];
+ if (oldToNew[id] < 0) {
+ oldToNew[id] = mVisVertices.size();
+
+ PxVec3 p = vertices[id];
+ PxVec3 n = normals[id];
+ if (scale != NULL)
+ {
+ p.x = scale->x*p.x;
+ p.y = scale->y*p.y;
+ p.z = scale->z*p.z;
+ n.x = scale->x*n.x/scaleMagn;
+ n.y = scale->y*n.y/scaleMagn;
+ n.z = scale->z*n.z/scaleMagn;
+ }
+ if (trans != NULL) {
+ p = trans->transform(p);
+ n = trans->rotate(n);
+ }
+ mVisVertices.pushBack(p);
+ mVisNormals.pushBack(n);
+ mVisTangents.pushBack(PxVec3(0.0f, 0.0f, 0.0f)); // on surface, no bump map
+ mVisTexCoords.pushBack(texcoords[id].x); // to do, get as input
+ mVisTexCoords.pushBack(texcoords[id].y);
+ }
+ }
+
+ int numTris = numIndices / 3;
+ mVisPolyStarts.resize(numTris+1);
+ for (int i = 0; i < numTris+1; i++)
+ mVisPolyStarts[i] = 3*i;
+
+ mVisPolyIndices.resize(numIndices);
+ for (int i = 0; i < numIndices; i++)
+ mVisPolyIndices[i] = oldToNew[indices[i]];
+
+ mVisTriIndices.clear();
+
+ bool manifold = computeVisMeshNeighbors();
+ createVisTrisFromPolys();
+ computeVisTangentsFromPoly();
+
+ return manifold;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec3 *tangents, const float *texCoords,
+ int numPolygons, const int *polyStarts,
+ int numIndices, const int *indices, PxTransform *trans, const PxVec3* scale)
+{
+ mHasExplicitVisMesh = true;
+
+ mVisVertices.resize(numVertices);
+ mVisNormals.resize(numVertices);
+ mVisTangents.resize(numVertices);
+ mVisTexCoords.resize(2*numVertices);
+
+ const float scaleMagn = scale ? scale->magnitude() : 1.f;
+
+ for (int i = 0; i < numVertices; i++) {
+ if (trans != NULL) {
+ mVisVertices[i] = trans->transform(vertices[i]);
+ mVisNormals[i] = trans->rotate(normals[i]);
+ if (tangents != NULL)
+ mVisTangents[i] = trans->rotate(tangents[i]);
+ else
+ mVisTangents[i] = PxVec3(0.0f, 0.0f, 0.0f);
+ }
+ else {
+ mVisVertices[i] = vertices[i];
+ mVisNormals[i] = normals[i];
+ if (tangents != NULL)
+ mVisTangents[i] = tangents[i];
+ else
+ mVisTangents[i] = PxVec3(0.0f, 0.0f, 0.0f);
+ }
+ if (texCoords != NULL) {
+ mVisTexCoords[2*i] = texCoords[2*i];
+ mVisTexCoords[2*i+1] = texCoords[2*i+1];
+ }
+ if (scale != NULL)
+ {
+ mVisVertices[i].x *= scale->x;
+ mVisVertices[i].y *= scale->y;
+ mVisVertices[i].z *= scale->z;
+ mVisNormals[i].x *= scale->x/scaleMagn;
+ mVisNormals[i].y *= scale->y/scaleMagn;
+ mVisNormals[i].z *= scale->z/scaleMagn;
+ }
+ }
+
+ mVisPolyStarts.resize(numPolygons+1);
+ for (int i = 0; i < numPolygons+1; i++)
+ mVisPolyStarts[i] = polyStarts[i];
+
+ mVisPolyIndices.resize(numIndices);
+ for (int i = 0; i < numIndices; i++)
+ mVisPolyIndices[i] = indices[i];
+
+ bool manifold = computeVisMeshNeighbors();
+ createVisTrisFromPolys();
+ computeVisTangentsFromPoly();
+
+ return manifold;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::computeVisTangentsFromPoly() {
+ // Must be called after createVisTrisFromPolys
+ //Adapt from Lengyel, Eric. �Computing Tangent Space Basis Vectors for an Arbitrary Mesh�. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
+
+ int numTris = mVisTriIndices.size() / 3;
+ int* tris = &mVisTriIndices[0];
+ int numV = mVisVertices.size();
+
+ for (int i = 0; i < numTris; i++)
+ {
+ int i0 = tris[0];
+ int i1 = tris[1];
+ int i2 = tris[2];
+
+ PxVec3& v0 = mVisVertices[i0];
+ PxVec3& v1 = mVisVertices[i1];
+ PxVec3& v2 = mVisVertices[i2];
+
+
+ float* tex0 = &mVisTexCoords[2*i0];
+ float* tex1 = &mVisTexCoords[2*i1];
+ float* tex2 = &mVisTexCoords[2*i2];
+
+ float x0 = v1.x - v0.x;
+ float x1 = v2.x - v0.x;
+ float y0 = v1.y - v0.y;
+ float y1 = v2.y - v0.y;
+ float z1 = v1.z - v0.z;
+ float z2 = v2.z - v0.z;
+
+ float s0 = tex1[0] - tex0[0];
+ float s1 = tex2[0] - tex0[0];
+ float t0 = tex1[1] - tex0[1];
+ float t1 = tex2[1] - tex0[1];
+
+ float idet = 1.0f / (s0*t1 - s1*t0);
+ PxVec3 t = idet*PxVec3(t1*x0 - t0*x1,t1*y0 - t0*y1,t1*z1 - t0*z2);
+ //NxVec3 b = idet*NxVec3(s0*x1 - s1*x0,s0*y1 - s1*y0,s0*z2 - s1*z1);
+
+/* if ( (i0 == 0) || (i1 == 0) || (i2 == 0) ) {
+ cout<<t[0]<<" "<<t[1]<<" "<<t[2]<<endl;
+ ok= true;
+ }*/
+ mVisTangents[i0] += t;
+ mVisTangents[i1] += t;
+ mVisTangents[i2] += t;
+
+ tris+=3;
+ }
+ //cout<<"OK = "<<ok<<endl;
+
+ for (int i = 0; i < numV; i++)
+ {
+ PxVec3& n = mVisNormals[i];
+ PxVec3& t = mVisTangents[i];
+
+
+ // Gram-Schmidt orthogonalize
+ t = (t - n * n.dot(t));
+ t.normalize();
+
+ if (!t.isFinite()) t = PxVec3(0.0f, 0.0f, 0.0f);
+
+ mVisTexCoords[2*i] += 5.0f;
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::createVisTrisFromPolys()
+{
+ mVisTriIndices.clear();
+ for (int i = 0; i < (int)mVisPolyStarts.size()-1; i++) {
+ int first = mVisPolyStarts[i];
+ int num = mVisPolyStarts[i+1] - first;
+ if (num == 3) {
+ mVisTriIndices.pushBack(mVisPolyIndices[first]);
+ mVisTriIndices.pushBack(mVisPolyIndices[first+1]);
+ mVisTriIndices.pushBack(mVisPolyIndices[first+2]);
+ continue;
+ }
+ PolygonTriangulator *pt = mScene->getPolygonTriangulator(); //PolygonTriangulator::getInstance();
+ pt->triangulate(&mVisVertices[0], num, &mVisPolyIndices[first]);
+ const shdfnd::Array<int> indices = pt->getIndices();
+
+ int numIds = mVisTriIndices.size();
+ mVisTriIndices.resize(numIds + indices.size());
+ for (int j = 0; j < (int)indices.size(); j++)
+ mVisTriIndices[numIds+j] = indices[j];
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::transformVisualMesh(const PxTransform &trans)
+{
+ for (int i = 0; i < (int)mVisVertices.size(); i++)
+ mVisVertices[i] = trans.transform(mVisVertices[i]);
+ for (int i = 0; i < (int)mVisNormals.size(); i++)
+ mVisNormals[i] = trans.rotate(mVisNormals[i]);
+ for (int i = 0; i < (int)mVisTangents.size(); i++)
+ mVisTangents[i] = trans.rotate(mVisTangents[i]);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::insideVisualMesh(const PxVec3 &pos) const
+{
+ int num[6] = {0,0,0,0,0,0};
+ const int numAxes = 2; // max 3: the nigher the more robust but slower
+
+ for (int i = 0; i < (int)mVisTriIndices.size(); i += 3) {
+ const PxVec3 &p0 = mVisVertices[mVisTriIndices[i]];
+ const PxVec3 &p1 = mVisVertices[mVisTriIndices[i+1]];
+ const PxVec3 &p2 = mVisVertices[mVisTriIndices[i+2]];
+ PxVec3 n = (p1-p0).cross(p2-p0);
+ float d = n.dot(p0);
+ float ds = d - pos.dot(n);
+
+ // for all axes, cound the hits of the ray starting from pos with the mesh
+ for (int j = 0; j < numAxes; j++) {
+ if (n[j] == 0.0f)
+ continue;
+
+ int j0 = (j+1)%3;
+ int j1 = (j+2)%3;
+ float x0 = p0[j0];
+ float y0 = p0[j1];
+ float x1 = p1[j0];
+ float y1 = p1[j1];
+ float x2 = p2[j0];
+ float y2 = p2[j1];
+
+ float px = pos[j0];
+ float py = pos[j1];
+
+ // inside triangle?
+ float d0 = (x1-x0) * (py-y0) - (y1-y0) * (px-x0);
+ float d1 = (x2-x1) * (py-y1) - (y2-y1) * (px-x1);
+ float d2 = (x0-x2) * (py-y2) - (y0-y2) * (px-x2);
+ bool inside =
+ (d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f) ||
+ (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f);
+ if (!inside)
+ continue;
+
+ float s = ds / n[j];
+ if (s > 0.0f)
+ num[2*j] += (n[j] > 0.0f) ? +1 : -1;
+ else
+ num[2*j+1] += (n[j] < 0.0f) ? +1 : -1;
+ }
+ }
+ int numVotes = 0;
+ for (int i = 0; i < 6; i++) {
+ if (num[i] > 0)
+ numVotes++;
+ }
+ return numVotes > numAxes;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::fitToVisualMesh(bool &cutEmpty, int numFitDirections)
+{
+ cutEmpty = false;
+ if (!mHasExplicitVisMesh)
+ return;
+
+ static const int numNormals = 3 + 4;
+ static const float normals[numNormals][3] = {
+ {1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}
+ // avoid singular cases
+ // {1.0f, 1.1f, 1.2f}, {-1.3f, 1.2f, 1.0f}, {1.0f, -1.2f, 1.0f}, {1.2f, 1.3f, -1.0f}
+ };
+
+ cutEmpty = false;
+ const float eps = 1e-3f;
+
+ int num = numFitDirections;
+ if (num > numNormals)
+ num = numNormals;
+
+ for (int i = 0; i < num; i++) {
+ PxVec3 n(normals[i][0], normals[i][1], normals[i][2]);
+ n.normalize();
+ float minVD = PX_MAX_F32;
+ float maxVD = -PX_MAX_F32;
+ float minCD = PX_MAX_F32;
+ float maxCD = -PX_MAX_F32;
+ for (int j = 0; j < (int)mVisVertices.size(); j++) {
+ float d = mVisVertices[j].dot(n);
+ if (d < minVD) minVD = d;
+ if (d > maxVD) maxVD = d;
+ }
+ for (int j = 0; j < (int)mVertices.size(); j++) {
+ float d = mVertices[j].dot(n);
+ if (d < minCD) minCD = d;
+ if (d > maxCD) maxCD = d;
+ }
+ if (maxVD < maxCD - eps) {
+ cut(n, maxVD, cutEmpty, false);
+ if (cutEmpty)
+ return;
+ }
+ if (minVD > minCD + eps) {
+ cut(-n, -minVD - eps, cutEmpty, false);
+ if (cutEmpty)
+ return;
+ }
+ }
+ finalize();
+}
+
+// --------------------------------------------------------------------------------------------
+float Convex::getVolume() const
+{
+ if (!mVolumeDirty)
+ return mVolume;
+
+ mVolume = 0.0f;
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ const Face &f = mFaces[i];
+ if (f.numIndices < 3)
+ continue;
+ const int *ids = &mIndices[f.firstIndex];
+ const PxVec3 &p0 = mVertices[ids[0]];
+ for (int j = 1; j < f.numIndices-1; j++) {
+ const PxVec3 &p1 = mVertices[ids[j]];
+ const PxVec3 &p2 = mVertices[ids[j+1]];
+ mVolume += p0.cross(p1).dot(p2);
+ }
+ }
+ mVolume *= (1.0f / 6.0f);
+ mVolumeDirty = false;
+ return mVolume;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::removeInvisibleFacesFlags()
+{
+ for (int i = 0; i < (int)mFaces.size(); i++)
+ mFaces[i].flags &= ~CompoundGeometry::FF_INVISIBLE;
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::updateFaceVisibility(const float *faceCoverage)
+{
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ if (faceCoverage[i] > 0.95f)
+ mFaces[i].flags |= CompoundGeometry::FF_INVISIBLE;
+ else
+ mFaces[i].flags &= ~CompoundGeometry::FF_INVISIBLE;
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Convex::clearFraceFlags(unsigned int flag)
+{
+ for (int i = 0; i < (int)mFaces.size(); i++)
+ mFaces[i].flags &= ~flag;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::insideFattened(const PxVec3 &pos, float r) const
+{
+ // early out with bounding box
+ if (pos.x < mBounds.minimum.x - r || pos.x > mBounds.maximum.x + r)
+ return false;
+ if (pos.y < mBounds.minimum.y - r || pos.y > mBounds.maximum.y + r)
+ return false;
+ if (pos.z < mBounds.minimum.z - r || pos.z > mBounds.maximum.z + r)
+ return false;
+
+ // planes
+ for (int i = 0; i < (int)mPlanes.size(); i++) {
+ if (mPlanes[i].n.dot(pos) > mPlanes[i].d + r)
+ return false;
+ }
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Convex::check() {
+ PxVec3 center = getCenter();
+
+ for (int i = 0; i < (int)mFaces.size(); i++) {
+ Face &f = mFaces[i];
+ if (f.numIndices < 3)
+ return false;
+
+ PxVec3 &p0 = mVertices[mIndices[f.firstIndex]];
+ PxReal A = 0.0f;
+ PxVec3 n(0.0, 0.0, 0.0);
+
+ for (int j = 1; j < f.numIndices-1; j++) {
+ PxVec3 &p1 = mVertices[mIndices[f.firstIndex+j]];
+ PxVec3 &p2 = mVertices[mIndices[f.firstIndex+j+1]];
+ PxVec3 nj = (p1-p0).cross(p2-p0);
+ A += nj.magnitude();
+ n += nj;
+ }
+ if (A < 1e-6)
+ return false;
+
+ PxReal d = n.dot(p0);
+ if (n.dot(center) > d)
+ return false;
+ }
+ return true;
+}
+
+bool Convex::isOnConvexSurface(const PxVec3 pts) const {
+ const float EPSILON = 1e-6f;
+ int numF = mFaces.size();
+ for (int i = 0; i < numF; i++) {
+
+ const Face& f = mFaces[i];
+ int nv = f.numIndices;
+
+ float areaFan = 0.0f;
+ // Compute face area
+ for (int j = 1; j < nv-1; j++) {
+ const PxVec3& p0 = mVertices[mIndices[f.firstIndex]];
+ const PxVec3& p1 = mVertices[mIndices[f.firstIndex+j]];
+ const PxVec3& p2 = mVertices[mIndices[f.firstIndex+(j+1)]];
+ areaFan += 0.5f* (((p1-p0).cross(p2-p0))).magnitude();
+ }
+ float areaP = 0.0f;
+
+ for (int j = 0; j < nv; j++) {
+
+ const PxVec3& p1 = mVertices[mIndices[f.firstIndex+j]];
+ const PxVec3& p2 = mVertices[mIndices[f.firstIndex+(j+1) % nv]];
+ areaP += 0.5f*(((p1-pts).cross(p2-pts))).magnitude();
+ }
+ if ((areaP - areaFan)/areaFan < EPSILON) {
+ return true;
+ }
+ }
+ return false;
+
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.h
new file mode 100644
index 00000000..ad544867
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/ConvexBase.h
@@ -0,0 +1,213 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef CONVEX_BASE
+#define CONVEX_BASE
+
+#include <PxPhysics.h>
+#include <PxCooking.h>
+#include <foundation/PxVec3.h>
+#include <foundation/PxPlane.h>
+#include <foundation/PxBounds3.h>
+#include <foundation/PxTransform.h>
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+class physx::PxShape;
+class physx::PxActor;
+class physx::PxScene;
+class physx::PxConvexMesh;
+
+class Compound;
+class CompoundGeometry;
+class SimScene;
+
+// ----------------------------------------------------------------------------
+class Convex : public ::physx::shdfnd::UserAllocated
+{
+ friend class SimScene;
+protected:
+ Convex(SimScene* scene);
+public:
+ virtual ~Convex();
+
+ void createFromConvex(const Convex *convex, const PxTransform *trans = NULL, int matID = 0, int surfMatID = 0);
+ void createFromGeometry(const CompoundGeometry &geom, int convexNr, const PxMat44 *trans = NULL, int matID = 0, int surfMatID = 0);
+ //bool createFromXml(XMLParser *p, float scale, bool ignoreVisualMesh = false);
+
+ void transform(const PxMat44 &trans);
+ PxVec3 centerAtZero();
+ PxVec3 getCenter() const;
+ void setTexScale(float texScale) { mTexScale = texScale; }
+ void increaseRefCounter() { mRefCounter++; }
+ int decreaseRefCounter() { mRefCounter--; return mRefCounter; }
+
+ bool rayCast(const PxVec3 &ray, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
+ bool collide(const PxVec3 &pos, float r, float &penetration, PxVec3 &surfaceNormal, PxVec3 &surfaceVel) const;
+
+ void intersectWithConvex(const PxPlane *planes, int numPlanes, const PxMat44 &trans, bool &empty);
+
+ virtual void draw(bool /*debug*/ = false) {}
+
+ PxConvexMesh* createPxConvexMesh(Compound *parent, PxPhysics *pxPhysics, PxCooking *pxCooking);
+ void setPxActor(PxRigidActor *actor);
+ void setLocalPose(const PxTransform &pose);
+
+ // accessors
+ Compound *getParent() { return mParent; }
+ const Compound *getParent() const { return mParent; }
+ const PxConvexMesh *getPxConvexMesh() const { return mPxConvexMesh; }
+ PxConvexMesh *getPxConvexMesh() { return mPxConvexMesh; }
+
+ const shdfnd::Array<PxPlane> &getPlanes() const { return mPlanes; };
+ const PxBounds3 &getBounds() const { return mBounds; }
+ void getWorldBounds(PxBounds3 &bounds) const;
+ void getLocalBounds(PxBounds3 &bounds) const;
+ float getVolume() const;
+ void removeInvisibleFacesFlags();
+ void updateFaceVisibility(const float *faceCoverage);
+ void clearFraceFlags(unsigned int flag);
+
+ struct Face {
+ void init() {
+ firstIndex = 0; numIndices = 0; flags = 0; firstNormal = 0;
+ }
+ int firstIndex;
+ int numIndices;
+ int flags;
+ int firstNormal;
+
+
+ };
+
+ const shdfnd::Array<Face> &getFaces() const { return mFaces; }
+ const shdfnd::Array<int> &getIndices() const { return mIndices; }
+ const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
+
+ const shdfnd::Array<PxVec3> &getVisVertices() const { return mVisVertices; }
+ const shdfnd::Array<PxVec3> &getVisNormals() const { return mVisNormals; }
+ const shdfnd::Array<PxVec3> &getVisTangents() const { return mVisTangents; }
+ const shdfnd::Array<float> &getVisTexCoords() const { return mVisTexCoords; }
+ const shdfnd::Array<int> &getVisTriIndices() const { return mVisTriIndices; }
+
+ const shdfnd::Array<int> &getVisPolyStarts() const { return mVisPolyStarts; }
+ const shdfnd::Array<int> &getVisPolyIndices() const { return mVisPolyIndices; }
+ const shdfnd::Array<int> &getVisPolyNeighbors() const { return mVisPolyNeighbors; }
+
+ PxVec3 getMaterialOffset() const { return mMaterialOffset; }
+ void setMaterialOffset(const PxVec3 &offset);
+ PxTransform getGlobalPose() const;
+ PxTransform getLocalPose() const;
+
+ bool isGhostConvex() const { return mIsGhostConvex; }
+
+ // explicit visual mesh
+ bool hasExplicitVisMesh() const { return mHasExplicitVisMesh; }
+ bool setExplicitVisMeshFromTriangles(int numVertices, const PxVec3 *vertices, const PxVec3 *normals, const PxVec2 *texcoords,
+ int numIndices, const PxU32 *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
+ bool setExplicitVisMeshFromPolygons(int numVertices, const PxVec3 *vertices, const PxVec3 *normals,
+ const PxVec3 *tangents, const float *texCoords,
+ int numPolygons, const int *polyStarts, // numPolygons+1 entries
+ int numIndices, const int *indices, PxTransform *trans = NULL, const PxVec3* scale = NULL);
+ void createVisTrisFromPolys();
+ void createVisMeshFromConvex();
+ void transformVisualMesh(const PxTransform &trans);
+ bool insideVisualMesh(const PxVec3 &pos) const;
+
+ void fitToVisualMesh(bool &cutEmpty, int numFitDirections = 3);
+
+ bool isOnConvexSurface(const PxVec3 pts) const;
+ bool check();
+
+ PxActor* getActor();
+ bool insideFattened(const PxVec3 &pos, float r) const;
+
+ bool use2dTexture() const { return mUse2dTexture; }
+ bool isIndestructible() const { return mIndestructible; }
+ int getMaterialId() const { return mMaterialId; }
+ int getSurfaceMaterialId() const { return mSurfaceMaterialId; }
+ void setSurfaceMaterialId(int id) { mSurfaceMaterialId = id; }
+
+ void setModelIslandNr(int nr) { mModelIslandNr = nr; }
+ int getModelIslandNr() const { return mModelIslandNr; }
+
+ void setConvexRendererInfo(int groupNr, int groupPos) const { mConvexRendererGroupNr = groupNr; mConvexRendererGroupPos = groupPos; }
+ int getConvexRendererGroupNr() const { return mConvexRendererGroupNr; }
+ int getConvexRendererGroupPos() const { return mConvexRendererGroupPos; }
+
+ void setIsFarConvex(bool v) { mIsFarConvex = v; }
+ bool getIsFarConvex() { return mIsFarConvex; }
+
+protected:
+ void clear();
+ void finalize();
+ void updateBounds();
+ void updatePlanes();
+
+ bool computeVisMeshNeighbors();
+ void computeVisTangentsFromPoly();
+ bool cutVisMesh(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty);
+ bool cut(const PxVec3 &localPlaneN, float localPlaneD, bool &cutEmpty, bool setNewFaceFlag = true);
+
+ bool rayCastConvex(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
+ bool rayCastVisMesh(const PxVec3 &orig, const PxVec3 &dir, float &dist, PxVec3 &normal) const;
+
+ SimScene* mScene;
+
+ shdfnd::Array<Face> mFaces;
+ shdfnd::Array<int> mIndices;
+ shdfnd::Array<PxVec3> mVertices;
+ shdfnd::Array<PxVec3> mNormals;
+ shdfnd::Array<PxPlane> mPlanes;
+
+ shdfnd::Array<PxVec3> mVisVertices;
+ shdfnd::Array<PxVec3> mVisNormals;
+ shdfnd::Array<PxVec3> mVisTangents;
+ shdfnd::Array<float> mVisTexCoords;
+ shdfnd::Array<int> mVisTriIndices;
+
+ int mRefCounter;
+ bool mHasExplicitVisMesh;
+ bool mIsGhostConvex;
+ shdfnd::Array<int> mVisPolyStarts; // for explicit mesh only
+ shdfnd::Array<int> mVisPolyIndices;
+ shdfnd::Array<int> mVisPolyNeighbors;
+
+ Convex *mNewConvex; // temporary buffer for cut operations
+
+ Compound *mParent;
+ PxRigidActor *mPxActor;
+ PxTransform mLocalPose;
+ PxConvexMesh *mPxConvexMesh;
+
+ PxBounds3 mBounds;
+ mutable float mVolume;
+ mutable bool mVolumeDirty;
+ PxVec3 mMaterialOffset;
+ float mTexScale;
+ int mModelIslandNr;
+
+ // material
+ bool mUse2dTexture;
+ bool mIndestructible;
+ int mMaterialId;
+ int mSurfaceMaterialId;
+
+ bool mIsFarConvex;
+
+ mutable int mConvexRendererGroupNr;
+ mutable int mConvexRendererGroupPos;
+};
+
+}
+}
+}
+
+#endif
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.cpp
new file mode 100644
index 00000000..303a2d65
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.cpp
@@ -0,0 +1,212 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include <foundation/PxBounds3.h>
+
+#include "MeshBase.h"
+#include <algorithm>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// ----------------------------------------------------------------------
+void Mesh::updateNormals()
+{
+ if (mVertices.empty())
+ return;
+
+ PxVec3 zero(0.0f, 0.0f, 0.0f);
+
+ mNormals.resize(mVertices.size());
+ for (int i = 0; i < (int)mNormals.size(); i++)
+ mNormals[i] = zero;
+ PxVec3 n;
+
+ PxU32 *idx = &mIndices[0];
+ int numTriangles = mIndices.size() / 3;
+ for (int i = 0; i < numTriangles; i++) {
+ PxU32 i0 = *idx++;
+ PxU32 i1 = *idx++;
+ PxU32 i2 = *idx++;
+ n = (mVertices[i1] - mVertices[i0]).cross(mVertices[i2] - mVertices[i0]);
+ mNormals[i0] += n;
+ mNormals[i1] += n;
+ mNormals[i2] += n;
+ }
+ for (int i = 0; i < (int)mNormals.size(); i++) {
+ if (!mNormals[i].isZero())
+ mNormals[i].normalize();
+ }
+}
+
+// ------------------------------------------------------------------------------
+void Mesh::getBounds(PxBounds3 &bounds, int subMeshNr) const
+{
+ bounds.setEmpty();
+ if (subMeshNr < 0 || subMeshNr >= (int)mSubMeshes.size()) {
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ bounds.include(mVertices[i]);
+ }
+ else {
+ const SubMesh &sm = mSubMeshes[subMeshNr];
+ for (int i = 0; i < sm.numIndices; i++) {
+ bounds.include(mVertices[mIndices[sm.firstIndex + i]]);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------
+void Mesh::normalize(const PxVec3 &center, float diagonal)
+{
+ if (mVertices.size() < 3)
+ return;
+
+ PxBounds3 bounds;
+ getBounds(bounds);
+
+ float s = diagonal / bounds.getDimensions().magnitude();
+ PxVec3 c = 0.5f * (bounds.minimum + bounds.maximum);
+
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mVertices[i] = center + (mVertices[i] - c) * s;
+}
+
+// ------------------------------------------------------------------------------
+void Mesh::scale(float diagonal)
+{
+ if (mVertices.size() < 3)
+ return;
+
+ PxBounds3 bounds;
+ getBounds(bounds);
+
+ float s = diagonal / bounds.getDimensions().magnitude();
+ for (int i = 0; i < (int)mVertices.size(); i++)
+ mVertices[i] *= s;
+}
+
+// --------------------------------------------------------------------------------------------
+struct IdEdge {
+ void set(PxU32 &i0, PxU32 &i1, int faceNr, int edgeNr) {
+ if (i0 < i1) { this->i0 = i0; this->i1 = i1; }
+ else { this->i0 = i1; this->i1 = i0; }
+ this->faceNr = faceNr; this->edgeNr = edgeNr;
+ }
+ bool operator < (const IdEdge &e) const {
+ if (i0 < e.i0) return true;
+ if (i0 == e.i0 && i1 < e.i1) return true;
+ return false;
+ }
+ bool operator == (const IdEdge &e) const { return i0 == e.i0 && i1 == e.i1; }
+ PxU32 i0,i1;
+ int faceNr, edgeNr;
+};
+
+// ------------------------------------------------------------------------------
+bool Mesh::computeNeighbors()
+{
+ int numTris = mIndices.size() / 3;
+
+ shdfnd::Array<IdEdge> edges(3*numTris);
+
+ for (int i = 0; i < numTris; i++) {
+ for (int j = 0; j < 3; j++)
+ edges[3*i+j].set(mIndices[3*i+j], mIndices[3*i + (j+1)%3], i, j);
+ }
+ std::sort(edges.begin(), edges.end());
+
+ mNeighbors.clear();
+ mNeighbors.resize(mIndices.size(), -1);
+ bool manifold = true;
+ int i = 0;
+ while (i < (int)edges.size()) {
+ IdEdge &e0 = edges[i];
+ i++;
+ if (i < (int)edges.size() && edges[i] == e0) {
+ IdEdge &e1 = edges[i];
+ mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
+ mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
+ i++;
+ }
+ while (i < (int)edges.size() && edges[i] == e0) {
+ manifold = false;
+ i++;
+ }
+ }
+ return manifold;
+}
+
+// --------------------------------------------------------------------------------------------
+struct PosEdge {
+ // not using indices for edge match but positions
+ // so duplicated vertices are handled as one vertex
+ static bool smaller(const PxVec3 &v0, const PxVec3 &v1) {
+ if (v0.x < v1.x) return true;
+ if (v0.x > v1.x) return false;
+ if (v0.y < v1.y) return true;
+ if (v0.y > v1.y) return false;
+ return (v0.z < v1.z);
+ }
+ void set(const PxVec3 &v0, const PxVec3 &v1, int faceNr, int edgeNr) {
+ if (smaller(v0,v1)) { this->v0 = v0; this->v1 = v1; }
+ else { this->v0 = v1; this->v1 = v0; }
+ this->faceNr = faceNr; this->edgeNr = edgeNr;
+ }
+ bool operator < (const PosEdge &e) const {
+ if (smaller(v0, e.v0)) return true;
+ if (v0 == e.v0 && smaller(v1, e.v1)) return true;
+ return false;
+ }
+ bool operator == (const PosEdge &e) const { return v0 == e.v0 && v1 == e.v1; }
+ PxVec3 v0,v1;
+ int faceNr, edgeNr;
+};
+
+// ------------------------------------------------------------------------------
+bool Mesh::computeWeldedNeighbors()
+{
+ int numTris = mIndices.size() / 3;
+ shdfnd::Array<PosEdge> edges(3*numTris);
+
+ for (int i = 0; i < numTris; i++) {
+ for (int j = 0; j < 3; j++)
+ edges[3*i+j].set(mVertices[mIndices[3*i+j]], mVertices[mIndices[3*i + (j+1)%3]], i, j);
+ }
+ std::sort(edges.begin(), edges.end());
+
+ mNeighbors.clear();
+ mNeighbors.resize(mIndices.size(), -1);
+ bool manifold = true;
+ int i = 0;
+ while (i < (int)edges.size()) {
+ PosEdge &e0 = edges[i];
+ i++;
+ if (i < (int)edges.size() && edges[i] == e0) {
+ PosEdge &e1 = edges[i];
+ mNeighbors[3* e0.faceNr + e0.edgeNr] = e1.faceNr;
+ mNeighbors[3* e1.faceNr + e1.edgeNr] = e0.faceNr;
+ i++;
+ }
+ while (i < (int)edges.size() && edges[i] == e0) {
+ manifold = false;
+ i++;
+ }
+ }
+ return manifold;
+}
+
+void Mesh::flipV()
+{
+ for(PxU32 i = 0; i < mTexCoords.size(); i++)
+ {
+ mTexCoords[i].y = 1.0f - mTexCoords[i].y;
+ }
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.h
new file mode 100644
index 00000000..5cde7f17
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/MeshBase.h
@@ -0,0 +1,67 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef MESH_BASE
+#define MESH_BASE
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxVec2.h>
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// -----------------------------------------------------------------------------------
+class Mesh : public ::physx::shdfnd::UserAllocated
+{
+public:
+ Mesh() {};
+ virtual ~Mesh() {};
+
+ const shdfnd::Array<PxVec3> &getVertices() const { return mVertices; }
+ const shdfnd::Array<PxVec3> &getNormals() const { return mNormals; }
+ const shdfnd::Array<PxVec2> &getTexCoords() const { return mTexCoords; }
+ const shdfnd::Array<PxU32> &getIndices() const { return mIndices; }
+ const shdfnd::Array<int> &getNeighbors() const { return mNeighbors; }
+
+ struct SubMesh {
+ void init() { /*name = "";*/ firstIndex = -1; numIndices = 0; }
+ //std::string name;
+ int firstIndex;
+ int numIndices;
+ };
+
+ const shdfnd::Array<SubMesh> &getSubMeshes() const { return mSubMeshes; }
+
+ void normalize(const PxVec3 &center, float diagonal);
+ void scale(float diagonal);
+ void getBounds(PxBounds3 &bounds, int subMeshNr = -1) const;
+
+ void flipV(); // flips v values to hand coordinate system change (Assumes normalized coordinates)
+
+ bool computeNeighbors();
+ bool computeWeldedNeighbors();
+
+protected:
+ void clear();
+ void updateNormals();
+
+ shdfnd::Array<PxVec3> mVertices;
+ shdfnd::Array<PxVec3> mNormals;
+ shdfnd::Array<PxVec2> mTexCoords;
+
+ shdfnd::Array<SubMesh> mSubMeshes;
+ shdfnd::Array<PxU32> mIndices;
+ shdfnd::Array<int> mNeighbors;
+};
+
+}
+}
+}
+
+#endif
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.cpp
new file mode 100644
index 00000000..9b7f82b3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.cpp
@@ -0,0 +1,272 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "PolygonTriangulatorBase.h"
+#include <foundation/PxAssert.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// ------ singleton pattern -----------------------------------------------------------
+
+//static PolygonTriangulator *gPolygonTriangulator = NULL;
+//
+//PolygonTriangulator* PolygonTriangulator::getInstance()
+//{
+// if (gPolygonTriangulator == NULL) {
+// gPolygonTriangulator = PX_NEW(PolygonTriangulator)();
+// }
+// return gPolygonTriangulator;
+//}
+//
+//void PolygonTriangulator::destroyInstance()
+//{
+// if (gPolygonTriangulator != NULL) {
+// PX_DELETE(gPolygonTriangulator);
+// }
+// gPolygonTriangulator = NULL;
+//}
+
+// -------------------------------------------------------------------------------------
+PolygonTriangulator::PolygonTriangulator(SimScene* scene):
+ mScene(scene)
+{
+}
+
+// -------------------------------------------------------------------------------------
+PolygonTriangulator::~PolygonTriangulator()
+{
+}
+
+// -------------------------------------------------------------------------------------
+float PolygonTriangulator::cross(const PxVec3 &p0, const PxVec3 &p1)
+{
+ return p0.x * p1.y - p0.y * p1.x;
+}
+
+// -------------------------------------------------------------------------------------
+bool PolygonTriangulator::inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2)
+{
+ float d0 = cross(p1 - p0, p - p0);
+ float d1 = cross(p2 - p1, p - p1);
+ float d2 = cross(p0 - p2, p - p2);
+ return (d0 >= 0.0f && d1 >= 0.0f && d2 >= 0.0f) ||
+ (d0 <= 0.0f && d1 <= 0.0f && d2 <= 0.0f);
+}
+
+// -------------------------------------------------------------------------------------
+void PolygonTriangulator::triangulate(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal)
+{
+ mIndices.clear();
+
+ if (numPoints < 3)
+ return;
+ if (numPoints == 3) {
+ if (indices == NULL) {
+ mIndices.pushBack(0);
+ mIndices.pushBack(1);
+ mIndices.pushBack(2);
+ }
+ else {
+ mIndices.pushBack(indices[0]);
+ mIndices.pushBack(indices[1]);
+ mIndices.pushBack(indices[2]);
+ }
+ return;
+ }
+
+ bool isConvex;
+ importPoints(points, numPoints, indices, planeNormal, isConvex);
+
+ if (isConvex) { // fast path
+ mIndices.resize(3*(numPoints-2));
+ for (int i = 0; i < numPoints-2; i++) {
+ mIndices[3*i] = 0;
+ mIndices[3*i+1] = i+1;
+ mIndices[3*i+2] = i+2;
+ }
+ }
+ else
+ clipEars();
+
+ if (indices != NULL) {
+ for (int i = 0; i < (int)mIndices.size(); i++) {
+ mIndices[i] = indices[mIndices[i]];
+ }
+ }
+}
+
+// -------------------------------------------------------------------------------------
+void PolygonTriangulator::importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex)
+{
+ // find projection 3d -> 2d;
+ PxVec3 n;
+
+ isConvex = true;
+
+ if (planeNormal)
+ n = *planeNormal;
+ else {
+ PX_ASSERT(numPoints >= 3);
+ n = PxVec3(0.0f, 0.0f, 0.0f);
+
+ for (int i = 1; i < numPoints-1; i++) {
+ int i0 = 0;
+ int i1 = i;
+ int i2 = i+1;
+ if (indices) {
+ i0 = indices[i0];
+ i1 = indices[i1];
+ i2 = indices[i2];
+ }
+ const PxVec3 &p0 = points[i0];
+ const PxVec3 &p1 = points[i1];
+ const PxVec3 &p2 = points[i2];
+ PxVec3 ni = (p1-p0).cross(p2-p0);
+ if (i > 1 && ni.dot(n) < 0.0f)
+ isConvex = false;
+ n += ni;
+ }
+ }
+
+ n.normalize();
+ PxVec3 t0,t1;
+
+ if (fabs(n.x) < fabs(n.y) && fabs(n.x) < fabs(n.z))
+ t0 = PxVec3(1.0f, 0.0f, 0.0f);
+ else if (fabs(n.y) < fabs(n.z))
+ t0 = PxVec3(0.0f, 1.0f, 0.0f);
+ else
+ t0 = PxVec3(0.0f, 0.0f, 1.0f);
+ t1 = n.cross(t0);
+ t1.normalize();
+ t0 = t1.cross(n);
+
+ mPoints.resize(numPoints);
+ if (indices == NULL) {
+ for (int i = 0; i < numPoints; i++)
+ mPoints[i] = PxVec3(points[i].dot(t0), points[i].dot(t1), 0.0f);
+ }
+ else {
+ for (int i = 0; i < numPoints; i++) {
+ const PxVec3 &p = points[indices[i]];
+ mPoints[i] = PxVec3(p.dot(t0), p.dot(t1), 0.0f);
+ }
+ }
+}
+
+// -------------------------------------------------------------------------------------
+void PolygonTriangulator::clipEars()
+{
+ // init
+ int num = mPoints.size();
+
+ mCorners.resize(num);
+
+ for (int i = 0; i < num; i++) {
+ Corner &c = mCorners[i];
+ c.prev = (i > 0) ? i-1 : num-1;
+ c.next = (i < num-1) ? i + 1 : 0;
+ c.isEar = false;
+ c.angle = 0.0f;
+ PxVec3 &p0 = mPoints[c.prev];
+ PxVec3 &p1 = mPoints[i];
+ PxVec3 &p2 = mPoints[c.next];
+ PxVec3 n1 = p1-p0;
+ PxVec3 n2 = p2-p1;
+ if (cross(n1, n2) > 0.0f) {
+ n1.normalize();
+ n2.normalize();
+ c.angle = n1.dot(n2);
+
+ c.isEar = true;
+ int nr = (i+2) % num;
+ for (int j = 0; j < num-3; j++) {
+ if (inTriangle(mPoints[nr], p0,p1,p2)) {
+ c.isEar = false;
+ break;
+ }
+ nr = (nr+1) % num;
+ }
+ }
+ }
+
+ int firstCorner = 0;
+ int numCorners = num;
+
+ while (numCorners > 3) {
+
+ // find best ear
+ float minAng = FLT_MAX;
+ int minNr = -1;
+
+ int nr = firstCorner;
+ for (int i = 0; i < numCorners; i++) {
+ Corner &c = mCorners[nr];
+ if (c.isEar && c.angle < minAng) {
+ minAng = c.angle;
+ minNr = nr;
+ }
+ nr = c.next;
+ }
+
+ // cut ear
+// assert(minNr >= 0);
+if (minNr < 0)
+break;
+ Corner &cmin = mCorners[minNr];
+ mIndices.pushBack(cmin.prev);
+ mIndices.pushBack(minNr);
+ mIndices.pushBack(cmin.next);
+ mCorners[cmin.prev].next = cmin.next;
+ mCorners[cmin.next].prev = cmin.prev;
+
+ if (firstCorner == minNr)
+ firstCorner = cmin.next;
+ numCorners--;
+ if (numCorners == 3)
+ break;
+
+ // new ears?
+ for (int i = 0; i < 2; i++) {
+ int i1 = (i == 0) ? cmin.prev : cmin.next;
+ int i0 = mCorners[i1].prev;
+ int i2 = mCorners[i1].next;
+
+ PxVec3 &p0 = mPoints[i0];
+ PxVec3 &p1 = mPoints[i1];
+ PxVec3 &p2 = mPoints[i2];
+ PxVec3 n1 = p1-p0;
+ PxVec3 n2 = p2-p1;
+ if (cross(n1, n2) > 0.0f) {
+ n1.normalize();
+ n2.normalize();
+ mCorners[i1].angle = n1.dot(n2);
+
+ mCorners[i1].isEar = true;
+ int nr = mCorners[i2].next;
+ for (int j = 0; j < numCorners-3; j++) {
+ if (inTriangle(mPoints[nr], p0,p1,p2)) {
+ mCorners[i1].isEar = false;
+ break;
+ }
+ nr = mCorners[nr].next;
+ }
+ }
+ }
+ }
+ int id = firstCorner;
+ mIndices.pushBack(id);
+ id = mCorners[id].next;
+ mIndices.pushBack(id);
+ id = mCorners[id].next;
+ mIndices.pushBack(id);
+}
+
+}
+}
+}
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.h
new file mode 100644
index 00000000..3b1c08be
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/PolygonTriangulatorBase.h
@@ -0,0 +1,59 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef POLYGON_TRIANGULATOR_BASE_H
+#define POLYGON_TRIANGULATOR_BASE_H
+
+#include <foundation/PxVec3.h>
+#include <foundation/PxMath.h>
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+// ------------------------------------------------------------------------------
+
+class PolygonTriangulator : public ::physx::shdfnd::UserAllocated {
+ friend class SimScene;
+public:
+ // singleton pattern
+ //static PolygonTriangulator* getInstance();
+ //static void destroyInstance();
+
+ void triangulate(const PxVec3 *points, int numPoints, const int *indices = NULL, PxVec3 *planeNormal = NULL);
+ const shdfnd::Array<int> &getIndices() const { return mIndices; }
+
+protected:
+ void importPoints(const PxVec3 *points, int numPoints, const int *indices, PxVec3 *planeNormal, bool &isConvex);
+ void clipEars();
+
+ inline float cross(const PxVec3 &p0, const PxVec3 &p1);
+ bool inTriangle(const PxVec3 &p, const PxVec3 &p0, const PxVec3 &p1, const PxVec3 &p2);
+
+ PolygonTriangulator(SimScene* scene);
+ virtual ~PolygonTriangulator();
+
+ SimScene* mScene;
+
+ shdfnd::Array<PxVec3> mPoints;
+ shdfnd::Array<int> mIndices;
+
+ struct Corner {
+ int prev;
+ int next;
+ bool isEar;
+ float angle;
+ };
+ shdfnd::Array<Corner> mCorners;
+};
+
+}
+}
+}
+
+#endif
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.cpp
new file mode 100644
index 00000000..6a1d2931
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.cpp
@@ -0,0 +1,337 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#include "PsHashMap.h"
+#include "SimSceneBase.h"
+#include <foundation/PxMat44.h>
+#include "PxRigidBodyExt.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxShape.h"
+
+#include "ActorBase.h"
+#include "CompoundBase.h"
+#include "ConvexBase.h"
+#include "CompoundCreatorBase.h"
+#include "PolygonTriangulatorBase.h"
+
+#include "RTdef.h"
+
+#include "PhysXMacros.h"
+#include "PxScene.h"
+#include "PxD6Joint.h"
+
+#define USE_CONVEX_RENDERER 1
+#define NUM_NO_SOUND_FRAMES 1
+
+#define REL_VEL_FRACTURE_THRESHOLD 5.0f
+//#define REL_VEL_FRACTURE_THRESHOLD 0.1f
+
+namespace physx
+{
+namespace fracture
+{
+namespace base
+{
+
+SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
+{
+ SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking, isGrbScene,minConvexSize,defaultMat,resourcePath);
+ s->createSingletons();
+ return s;
+}
+
+void SimScene::createSingletons()
+{
+ mCompoundCreator = PX_NEW(CompoundCreator)(this);
+ mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this);
+ addActor(createActor()); // make default actor
+}
+
+Convex* SimScene::createConvex()
+{
+ return PX_NEW(Convex)(this);
+}
+
+Compound* SimScene::createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern, PxReal contactOffset, PxReal restOffset)
+{
+ return PX_NEW(Compound)(this,contactOffset,restOffset);
+}
+
+Actor* SimScene::createActor()
+{
+ return PX_NEW(Actor)(this);
+}
+
+shdfnd::Array<Compound*> SimScene::getCompounds()
+{
+ return mActors[0]->getCompounds();
+}
+
+///*extern*/ std::vector<Compound*> delCompoundList;
+
+// --------------------------------------------------------------------------------------------
+SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
+{
+ mPxPhysics = pxPhysics; // used for cooking
+ mPxCooking = pxCooking;
+ mPxDefaultMaterial = defaultMat;
+ mResourcePath = resourcePath;
+
+ clear();
+ mRenderBuffers.init();
+ mSceneVersion = 1;
+ mRenderBufferVersion = 0;
+ mOptixBufferVersion = 0;
+
+ //create3dTexture();
+
+ mFractureForceThreshold = 500.0f;
+ mContactImpactRadius = 0.5f;
+
+ mNoFractureFrames = 0;
+ mNoSoundFrames = 0;
+ mFrameNr = 0;
+ mDebugDraw = false;
+// mDebugDraw = true; // foo
+
+ mPickDepth = 0.0f;
+ mPickActor = NULL;
+ mPickJoint = NULL;
+ mPickPos = mPickLocalPos = PxVec3(0.0f, 0.0f, 0.0f);
+
+ mMinConvexSize = minConvexSize;
+ mNumNoFractureFrames = 2;
+
+ bumpTextureUVScale = 0.1f;
+ roughnessScale = 0.2f;
+ extraNoiseScale = 2.0f;
+
+ particleBumpTextureUVScale = 0.2f;
+ particleRoughnessScale = 0.8f;
+ particleExtraNoiseScale = 2.0f;
+
+
+ mPlaySounds = false;
+ mRenderDebris = true;
+
+ mCompoundCreator = NULL;
+ mPolygonTriangulator = NULL;
+
+ mAppNotify = NULL;
+}
+
+// --------------------------------------------------------------------------------------------
+SimScene::~SimScene()
+{
+ clear();
+
+ // Delete actors if not already deleted
+ for(int i = ((int)mActors.size() - 1) ; i >= 0; i--)
+ {
+ PX_DELETE(mActors[i]);
+ }
+
+ PX_DELETE(mCompoundCreator);
+ PX_DELETE(mPolygonTriangulator);
+
+ mCompoundCreator = NULL;
+ mPolygonTriangulator = NULL;
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::clear()
+{
+ for(int i = 0 ; i < (int)mActors.size(); i++)
+ {
+ mActors[i]->clear();
+ }
+ deleteCompounds();
+ mPickActor = NULL;
+
+ ++mSceneVersion;
+}
+
+void SimScene::addActor(Actor* a)
+{
+ mActors.pushBack(a);
+}
+
+void SimScene::removeActor(Actor* a)
+{
+ for(int i = 0; i < (int)mActors.size(); i++)
+ {
+ if( a == mActors[i] )
+ {
+ mActors[i] = mActors[mActors.size()-1];
+ mActors.popBack();
+ }
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::addCompound(Compound *c)
+{
+ mActors[0]->addCompound(c);
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::removeCompound(Compound *c)
+{
+ mActors[0]->removeCompound(c);
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::deleteCompounds()
+{
+ for (int i = 0; i < (int)delCompoundList.size(); i++)
+ {
+ PX_DELETE(delCompoundList[i]);
+ }
+ delCompoundList.clear();
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::preSim(float dt)
+{
+ for(int i = 0 ; i < (int)mActors.size(); i++)
+ {
+ mActors[i]->preSim(dt);
+ }
+
+
+ // make sure we use the apex user notify... if the application
+ // changes their custom one make sure we map to it.
+ mScene->lockWrite();
+ PxSimulationEventCallback* userNotify = mScene->getSimulationEventCallback();
+ if (userNotify != this)
+ {
+ mAppNotify = userNotify;
+ mScene->setSimulationEventCallback(this);
+ }
+ mScene->unlockWrite();
+}
+
+//float4* posVelG = 0;
+//int numPosVelG = 0;
+// --------------------------------------------------------------------------------------------
+void SimScene::postSim(float dt)
+{
+ for(int i = 0 ; i < (int)mActors.size(); i++)
+ {
+ mActors[i]->postSim(dt);
+ }
+
+ mFrameNr++;
+ mNoFractureFrames--;
+ mNoSoundFrames--;
+}
+
+
+//-----------------------------------------------------------------------------
+bool SimScene::pickStart(const PxVec3 &orig, const PxVec3 &dir)
+{
+ PX_ASSERT(mPickActor == NULL);
+
+ float dist = 1000.f;
+
+ PxRaycastBuffer buffer;
+ if (!getScene()->raycast(orig, dir, dist, buffer, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlag::eDYNAMIC)))
+ return false;
+
+ PxRigidDynamic* pickedActor = buffer.getAnyHit(0).actor->is<PxRigidDynamic>();
+
+ dist = buffer.getAnyHit(0).distance;
+
+
+
+ //mPickActor = mActors[actorNr]->mCompounds[compoundNr]->getPxActor();
+ mPickPos = orig + dir * dist;
+
+ mPickActor = PxGetPhysics().createRigidDynamic(PxTransform(mPickPos));
+ mPickActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+
+ getScene()->addActor(*mPickActor);
+
+ mPickLocalPos = PxVec3(0.f);
+
+ mPickJoint = PxD6JointCreate(PxGetPhysics(), mPickActor, PxTransform(PxIdentity), pickedActor, PxTransform(pickedActor->getGlobalPose().transformInv(mPickPos)));
+ mPickJoint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+ mPickJoint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+ mPickJoint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+ mPickDepth = dist;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+void SimScene::pickMove(const PxVec3 &orig, const PxVec3 &dir)
+{
+ if (mPickActor == NULL)
+ return;
+
+ mPickPos = orig + dir * mPickDepth;
+ mPickActor->setKinematicTarget(PxTransform(mPickPos));
+}
+
+//-----------------------------------------------------------------------------
+void SimScene::pickRelease()
+{
+ if (mPickJoint)
+ mPickJoint->release();
+ mPickJoint = NULL;
+ if (mPickActor)
+ mPickActor->release();
+ mPickActor = NULL;
+}
+
+bool SimScene::findCompound(const Compound* c, int& actorNr, int& compoundNr)
+{
+ actorNr = -1;
+ compoundNr = -1;
+ for(int i = 0; i < (int)mActors.size(); i++)
+ {
+ if (mActors[i]->findCompound(c,compoundNr))
+ {
+ actorNr = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+// CPU
+void SimScene::onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs)
+{
+ // Pass along to application's callback, if defined
+ if (mAppNotify != NULL)
+ {
+ mAppNotify->onContact(pairHeader, pairs, nbPairs);
+ }
+}
+
+shdfnd::Array<PxVec3>& SimScene::getDebugPoints() {
+ return debugPoints;
+}
+
+bool SimScene::mapShapeToConvex(const PxShape& shape, Convex& convex)
+{
+ return mShapeMap.insert(&shape, &convex);
+}
+
+bool SimScene::unmapShape(const PxShape& shape)
+{
+ return mShapeMap.erase(&shape);
+}
+
+Convex* SimScene::findConvexForShape(const PxShape& shape)
+{
+ const physx::shdfnd::HashMap<const PxShape*, Convex*>::Entry* entry = mShapeMap.find(&shape);
+ return entry != NULL ? entry->second : NULL; // Since we don't expect *entry to be NULL, we shouldn't lose information here
+}
+
+}
+}
+}
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.h b/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.h
new file mode 100644
index 00000000..60bd732d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Core/SimSceneBase.h
@@ -0,0 +1,248 @@
+#include "RTdef.h"
+#if RT_COMPILE
+#ifndef SIM_SCENE_BASE
+#define SIM_SCENE_BASE
+
+#include "PxSimulationEventCallback.h"
+#include <PsArray.h>
+#include <PsUserAllocated.h>
+#include "PsHashMap.h"
+
+#include "RTdef.h"
+
+namespace physx
+{
+class PxPhysics;
+class PxCooking;
+class PxScene;
+class PxRigidDynamic;
+class PxD6Joint;
+namespace fracture
+{
+namespace base
+{
+
+class Actor;
+class Compound;
+class Convex;
+class FracturePattern;
+class CompoundCreator;
+class Delaunay2d;
+class Delaunay3d;
+class PolygonTriangulator;
+
+// -----------------------------------------------------------------------------------
+class SimScene :
+ public PxSimulationEventCallback, public ::physx::shdfnd::UserAllocated
+{
+ friend class Actor;
+public:
+ static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
+protected:
+ SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
+public:
+ virtual ~SimScene();
+
+ // Creates Scene Level Singletons
+ virtual void createSingletons();
+ // Access singletons
+ CompoundCreator* getCompoundCreator() {return mCompoundCreator;}
+ PolygonTriangulator* getPolygonTriangulator() {return mPolygonTriangulator;}
+
+ // Create non-Singletons
+ virtual Actor* createActor();
+ virtual Convex* createConvex();
+ virtual Compound* createCompound(const FracturePattern *pattern, const FracturePattern *secondaryPattern = NULL, PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
+ virtual void clear();
+ void addCompound(Compound *m);
+ void removeCompound(Compound *m);
+ // perform deferred deletion
+ void deleteCompounds();
+
+ void setScene(PxScene* scene) { mScene = scene; }
+ //
+ bool findCompound(const Compound* c, int& actorNr, int& compoundNr);
+
+ void removeActor(Actor* a);
+
+ // Profiler hooks
+ virtual void profileBegin(const char* /*name*/) {}
+ virtual void profileEnd(const char* /*name*/) {}
+
+ virtual void playSound(const char * /*name*/, int /*nr*/ = -1) {}
+
+ // accessors
+ shdfnd::Array<Compound*> getCompounds(); //{ return mCompounds; }
+ shdfnd::Array<Actor*> getActors() { return mActors; }
+ PxPhysics* getPxPhysics() { return mPxPhysics; }
+ PxCooking* getPxCooking() { return mPxCooking; }
+ PxScene* getScene() { return mScene; }
+
+ //ConvexRenderer &getConvexRenderer() { return mConvexRenderer; }
+
+ void preSim(float dt);
+ void postSim(float dt); //, RegularCell3D* fluidSim);
+
+ void setPlaySounds(bool play) { mPlaySounds = play; }
+ void setContactImpactRadius(float radius) { mContactImpactRadius = radius; }
+ void setNumNoFractureFrames(int num) { mNumNoFractureFrames = num; }
+
+ void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) {
+ mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov;
+ }
+
+ //void draw(bool useShader, Shader* particleShader = NULL) {}
+ //void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
+ //void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; }
+
+ PxMaterial *getPxDefaultMaterial() { return mPxDefaultMaterial; }
+
+ void toggleDebugDrawing() { mDebugDraw = !mDebugDraw; }
+
+ virtual bool pickStart(const PxVec3 &orig, const PxVec3 &dir);
+ virtual void pickMove(const PxVec3 &orig, const PxVec3 &dir);
+ virtual void pickRelease();
+ PxRigidDynamic* getPickActor() { return mPickActor; }
+ const PxVec3 &getPickPos() { return mPickPos; }
+ const PxVec3 &getPickLocalPos() { return mPickLocalPos; }
+
+ // callback interface
+
+ void onContactNotify(unsigned int arraySizes, void ** shape0Array, void ** shape1Array, void ** actor0Array, void ** actor1Array, float * positionArray, float * normalArray);
+ void onConstraintBreak(PxConstraintInfo* constraints, PxU32 count) { PX_UNUSED((constraints, count)); }
+ void onWake(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
+ void onSleep(PxActor** actors, PxU32 count) { PX_UNUSED((actors, count)); }
+ void onTrigger(PxTriggerPair* pairs, PxU32 count) { PX_UNUSED((pairs, count)); }
+ void onContact(const PxContactPairHeader& pairHeader, const PxContactPair* pairs, PxU32 nbPairs);
+ void onAdvance(const PxRigidBody*const* bodyBuffer, const PxTransform* poseBuffer, const PxU32 count) { PX_UNUSED(bodyBuffer); PX_UNUSED(poseBuffer); PX_UNUSED(count); }
+
+ void toggleRenderDebris() {mRenderDebris = !mRenderDebris;}
+ bool getRenderDebrs() {return mRenderDebris;}
+ //virtual void dumpSceneGeometry() {}
+ shdfnd::Array<PxVec3>& getDebugPoints();
+ //virtual void createRenderBuffers() {}
+ //void loadAndCreateTextureArrays();
+
+ shdfnd::Array<PxVec3>& getCrackNormals() {return crackNormals;}
+ shdfnd::Array<PxVec3>& getTmpPoints() {return tmpPoints;}
+
+ bool mapShapeToConvex(const PxShape& shape, Convex& convex);
+ bool unmapShape(const PxShape& shape);
+ Convex* findConvexForShape(const PxShape& shape);
+ bool owns(const PxShape& shape) {return NULL != findConvexForShape(shape);}
+
+protected:
+ //virtual void create3dTexture() {}
+ //virtual void updateConvexesTex() {}
+ //void playShatterSound(float objectSize);
+
+ void addActor(Actor* a); // done internally upon creation
+
+ PxPhysics *mPxPhysics;
+ PxCooking *mPxCooking;
+ PxScene *mScene;
+ const char *mResourcePath;
+ bool mPlaySounds;
+
+ //shdfnd::Array<Compound*> mCompounds;
+ shdfnd::Array<Actor*> mActors;
+
+ float mFractureForceThreshold;
+ float mContactImpactRadius;
+
+ shdfnd::Array<PxContactPairPoint> mContactPoints;
+ struct FractureEvent {
+ void init() {
+ compound = NULL;
+ pos = normal = PxVec3(0.0f, 0.0f, 0.0f);
+ additionalRadialImpulse = additionalNormalImpulse = 0.0f;
+ withStatic = false;
+ }
+ Compound *compound;
+ PxVec3 pos;
+ PxVec3 normal;
+ float additionalRadialImpulse;
+ float additionalNormalImpulse;
+ bool withStatic;
+ };
+
+ struct RenderBuffers {
+ void init() {
+ numVertices = 0; numIndices = 0;
+ VBO = 0; IBO = 0; matTex = 0; volTex = 0;
+ texSize = 0; numConvexes = -1;
+ }
+ shdfnd::Array<float> tmpVertices;
+ shdfnd::Array<unsigned int> tmpIndices;
+ shdfnd::Array<float> tmpTexCoords;
+ int numVertices, numIndices;
+ unsigned int VBO;
+ unsigned int IBO;
+ unsigned int volTex;
+ unsigned int matTex;
+ int texSize;
+ int numConvexes;
+ };
+ RenderBuffers mRenderBuffers;
+ unsigned int mSceneVersion; // changed on each update
+ unsigned int mRenderBufferVersion; // to handle updates
+ unsigned int mOptixBufferVersion; // to handle updates
+
+ PxMaterial *mPxDefaultMaterial;
+
+ //ConvexRenderer mConvexRenderer;
+
+ int mNoFractureFrames;
+ int mNoSoundFrames;
+ int mFrameNr;
+ bool mDebugDraw;
+
+ float mPickDepth;
+ PxRigidDynamic *mPickActor;
+ PxD6Joint* mPickJoint;
+ PxVec3 mPickPos;
+ PxVec3 mPickLocalPos;
+
+ float mMinConvexSize;
+ int mNumNoFractureFrames; // > 1 to prevent a slow down by too many fracture events
+
+ PxVec3 mCameraPos, mCameraDir, mCameraUp;
+ float mCameraFov;
+
+ float bumpTextureUVScale;
+ float extraNoiseScale;
+ float roughnessScale;
+
+ float particleBumpTextureUVScale;
+ float particleRoughnessScale;
+ float particleExtraNoiseScale;
+ shdfnd::Array<PxVec3> debugPoints;
+ bool mRenderDebris;
+
+ PxSimulationEventCallback* mAppNotify;
+
+ //GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray;
+
+ //GLuint loadTextureArray(std::vector<std::string>& names);
+
+ //Singletons
+ CompoundCreator* mCompoundCreator;
+ PolygonTriangulator* mPolygonTriangulator;
+
+ //Array for use by Compound (effectively static)
+ shdfnd::Array<PxVec3> crackNormals;
+ shdfnd::Array<PxVec3> tmpPoints;
+
+ // Deferred Deletion list
+ shdfnd::Array<Compound*> delCompoundList;
+
+ // Map used to determine SimScene ownership of shape
+ shdfnd::HashMap<const PxShape*,Convex*> mShapeMap;
+};
+
+}
+}
+}
+
+#endif
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.cpp
new file mode 100644
index 00000000..5296e79c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.cpp
@@ -0,0 +1,165 @@
+#include <foundation/PxBounds3.h>
+
+#include "Mesh.h"
+#include <algorithm>
+#include <iostream>
+
+// -------------------------------------------------------------------
+struct SimpleVertexRef {
+ int vert, normal, texCoord;
+ int indexNr, subMeshNr;
+ bool operator < (const SimpleVertexRef &r) const {
+ if (vert < r.vert) return true;
+ if (vert > r.vert) return false;
+ if (normal < r.normal) return true;
+ if (normal > r.normal) return false;
+ return texCoord < r.texCoord;
+ }
+ bool operator == (const SimpleVertexRef &r) const {
+ return vert == r.vert && normal == r.normal && texCoord == r.texCoord;
+ }
+ void parse(char *s, int indexNr) {
+ int nr[3] = {0,0,0};
+ char *p = s;
+ for (int i = 0; i < 3; i++) {
+ while (*p != 0 && *p != '/') p++;
+ bool end = (*p == 0);
+ *p = 0;
+ sscanf_s(s, "%i", &nr[i]);
+ if (end) break;
+ p++; s = p;
+ }
+ vert = nr[0]-1; texCoord = nr[1]-1; normal = nr[2]-1;
+ this->indexNr = indexNr;
+ }
+};
+
+#define OBJ_STR_LEN 256
+// -------------------------------------------------------------------
+bool Mesh::loadFromObjFile(const std::string &filename)
+{
+ const int maxVertsPerFace = 8;
+
+ char s[OBJ_STR_LEN], ps[maxVertsPerFace][OBJ_STR_LEN], sub[OBJ_STR_LEN];
+ int matNr = -1;
+ PxVec3 p;
+ float u,v;
+ shdfnd::Array<SimpleVertexRef> refs;
+ SimpleVertexRef ref[maxVertsPerFace];
+
+ shdfnd::Array<PxVec3> vertices;
+ shdfnd::Array<PxVec3> normals;
+ shdfnd::Array<float> texCoords;
+ int numIndices = 0;
+
+ mSubMeshes.resize(1);
+ mNames.resize(1);
+ mSubMeshes[0].init();
+ mNames[0] = "";
+ mSubMeshes[0].firstIndex = 0;
+
+ FILE *f;
+
+ if (fopen_s(&f, filename.c_str(), "r") != 0) {
+ std::cerr << "Could not load OBJ file: " << filename << std::endl;
+ return false;
+ }
+
+ // first a vertex ref is generated for each v/n/t combination
+ while (!feof(f)) {
+ if (fgets(s, OBJ_STR_LEN, f) == NULL) break;
+
+ if (strncmp(s, "usemtl", 6) == 0 || strncmp(s, "g ", 2) == 0) { // new group
+ bool isGroup = strncmp(s, "g ", 2) == 0;
+ if (isGroup)
+ strcpy(sub, &s[2]);
+ else
+ strcpy(sub, &s[6]);
+ int numSubs = mSubMeshes.size();
+ if (mSubMeshes[numSubs-1].numIndices > 0) {
+ mSubMeshes.resize(numSubs+1);
+ mNames.resize(numSubs+1);
+ mSubMeshes[numSubs].init();
+ mNames[numSubs] = "";
+ mSubMeshes[numSubs].firstIndex = mIndices.size();
+ }
+ int subNr = mSubMeshes.size() - 1;
+ if (mNames[subNr] == "" || isGroup)
+ mNames[subNr] = std::string(sub);
+ }
+ else if (strncmp(s, "v ", 2) == 0) { // vertex
+ sscanf_s(s, "v %f %f %f", &p.x, &p.y, &p.z);
+ vertices.pushBack(p);
+ }
+ else if (strncmp(s, "vn ", 3) == 0) { // normal
+ sscanf_s(s, "vn %f %f %f", &p.x, &p.y, &p.z);
+ normals.pushBack(p);
+ }
+ else if (strncmp(s, "vt ", 3) == 0) { // texture coords
+ sscanf_s(s, "vt %f %f", &u, &v);
+ texCoords.pushBack(u);
+ texCoords.pushBack(v);
+ }
+ else if (strncmp(s, "f ", 2) == 0) { // face, tri or quad
+ int nr;
+ nr = sscanf_s(s, "f %s %s %s %s %s %s",
+ ps[0], OBJ_STR_LEN, ps[1], OBJ_STR_LEN, ps[2], OBJ_STR_LEN, ps[3], OBJ_STR_LEN,
+ ps[4], OBJ_STR_LEN, ps[5], OBJ_STR_LEN, ps[6], OBJ_STR_LEN, ps[7], OBJ_STR_LEN);
+
+ if (nr >= 3) {
+ for (int i = 0; i < nr; i++)
+ ref[i].parse(ps[i], 0);
+ for (int i = 1; i < nr-1; i++) {
+ ref[0].indexNr = numIndices++; refs.pushBack(ref[0]); mIndices.pushBack(0);
+ ref[i].indexNr = numIndices++; refs.pushBack(ref[i]); mIndices.pushBack(0);
+ ref[i+1].indexNr = numIndices++; refs.pushBack(ref[i+1]); mIndices.pushBack(0);
+ mSubMeshes[mSubMeshes.size()-1].numIndices += 3;
+ }
+ }
+ }
+ }
+ fclose(f);
+
+ // now we merge multiple v/n/t triplets
+ std::sort(refs.begin(), refs.end());
+
+ int i = 0;
+ PxVec3 defNormal(1.0f, 0.0f, 0.0f);
+ bool normalsOK = true;
+ bool mTextured = true;
+ int numTexCoords = texCoords.size();
+
+ int baseVertNr = 0;
+
+ while (i < (int)refs.size()) {
+ int vertNr = mVertices.size();
+ SimpleVertexRef &r = refs[i];
+ mVertices.pushBack(vertices[r.vert]);
+
+ if (r.normal >= 0) mNormals.pushBack(normals[r.normal]);
+ else { mNormals.pushBack(defNormal); normalsOK = false; }
+
+ if (r.texCoord >= 0 && r.texCoord < numTexCoords) {
+ //mTexCoords.pushBack(texCoords[2*r.texCoord]);
+ //mTexCoords.pushBack(texCoords[2*r.texCoord+1]);
+ mTexCoords.pushBack(PxVec2(texCoords[2*r.texCoord],texCoords[2*r.texCoord+1]));
+ }
+ else {
+ //mTexCoords.pushBack(0.0f);
+ //mTexCoords.pushBack(0.0f);
+ mTexCoords.pushBack(PxVec2(0.0f,0.0f));
+ }
+
+ mIndices[r.indexNr] = vertNr;
+ i++;
+ while (i < (int)refs.size() && r == refs[i]) {
+ mIndices[refs[i].indexNr] = vertNr;
+ i++;
+ }
+ }
+
+ if (!normalsOK)
+ updateNormals();
+
+ return true;
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.h b/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.h
new file mode 100644
index 00000000..a1f15544
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/Mesh.h
@@ -0,0 +1,32 @@
+#ifndef MESH
+#define MESH
+
+#include <foundation/PxVec3.h>
+#include <PsArray.h>
+#include <PsAllocator.h>
+
+#include "Shader.h"
+
+#include "MeshBase.h"
+
+using namespace physx::fracture;
+
+class Mesh : public base::Mesh
+{
+public:
+ bool loadFromObjFile(const std::string &filename);
+
+ void setShader(Shader* shader, const ShaderMaterial &mat) { mShader = shader; mShaderMat = mat; }
+ Shader* getShader() const { return mShader; }
+ const ShaderMaterial& getShaderMat() { return mShaderMat; }
+ void draw(bool useShader);
+protected:
+ // shading
+ Shader *mShader;
+ ShaderMaterial mShaderMat;
+ Shader *mWrinkleShader;
+
+ shdfnd::Array<std::string> mNames;
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.cpp
new file mode 100644
index 00000000..e2dcdf67
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.cpp
@@ -0,0 +1,4 @@
+#include "PolygonTriangulator.h"
+#include <assert.h>
+
+// Empty until base has code proven to be non-portable \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.h b/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.h
new file mode 100644
index 00000000..ae669d31
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/PolygonTriangulator.h
@@ -0,0 +1,22 @@
+#ifndef POLYGON_TRIANGULATOR_H
+#define POLYGON_TRIANGULATOR_H
+
+#include <foundation/PxVec3.h>
+#include <PsArray.h>
+
+using namespace physx;
+
+#include <math.h>
+
+#include "PolygonTriangulatorBase.h"
+
+using namespace physx::fracture;
+
+class PolygonTriangulator : public base::PolygonTriangulator
+{
+ friend class SimScene;
+protected:
+ PolygonTriangulator(SimScene* scene): base::PolygonTriangulator((base::SimScene*)scene) {}
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/RTdef.h b/KaplaDemo/samples/sampleViewer3/Fracture/RTdef.h
new file mode 100644
index 00000000..b9d08ac6
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/RTdef.h
@@ -0,0 +1,8 @@
+// This file exists primarily for APEX integration
+#ifndef RT_DEF_H
+#define RT_DEF_H
+
+#define RT_COMPILE 1
+#define NO_IMPACT_FRACTURE 0
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.cpp b/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.cpp
new file mode 100644
index 00000000..a94e02e1
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.cpp
@@ -0,0 +1,778 @@
+#include "SimScene.h"
+#include <foundation/PxMat44.h>
+#include "PxRigidBodyExt.h"
+
+#include "Actor.h"
+#include "Compound.h"
+#include "Convex.h"
+#include "CompoundCreator.h"
+#include "PolygonTriangulator.h"
+
+#include "SampleViewerScene.h"
+#include "XMLParser.h"
+
+#include <windows.h>
+
+#include <iostream>
+
+using namespace std;
+
+#include <vector>
+#include "TerrainMesh.h"
+#include "IJGWin32/CPPJPEGWrapper.h"
+
+#define USE_CONVEX_RENDERER 1
+#define NUM_NO_SOUND_FRAMES 1
+
+//#define REL_VEL_FRACTURE_THRESHOLD 5.0f
+#define REL_VEL_FRACTURE_THRESHOLD 0.1f
+
+//extern std::vector<Compound*> delCompoundList;
+
+SimScene* SimScene::createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath)
+{
+ SimScene* s = PX_NEW(SimScene)(pxPhysics,pxCooking,isGrbScene,minConvexSize,defaultMat,resourcePath);
+ s->createSingletons();
+ return s;
+}
+
+void SimScene::createSingletons()
+{
+ mCompoundCreator = PX_NEW(CompoundCreator)(this);
+ mPolygonTriangulator = PX_NEW(PolygonTriangulator)(this);
+ addActor(createActor());
+}
+
+base::Actor* SimScene::createActor()
+{
+ return (base::Actor*)PX_NEW(Actor)(this);
+}
+
+base::Convex* SimScene::createConvex()
+{
+ return (base::Convex*)PX_NEW(Convex)(this);
+}
+
+base::Compound* SimScene::createCompound(PxReal contactOffset, PxReal restOffset)
+{
+ return (base::Compound*)PX_NEW(Compound)(this, contactOffset, restOffset);
+}
+
+SimScene::SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath):
+ base::SimScene(pxPhysics,pxCooking,isGrbScene,minConvexSize,defaultMat,resourcePath)
+{
+ //mParticles = NULL;
+
+ diffuseTexArray = 0;
+ bumpTexArray = 0;
+ specularTexArray = 0;
+ emissiveReflectSpecPowerTexArray = 0;
+
+ create3dTexture();
+}
+
+// --------------------------------------------------------------------------------------------
+SimScene::~SimScene()
+{
+ mShader = NULL;
+ mShaderMat.init();
+
+ if (mRenderBuffers.volTex) glDeleteTextures(1, &mRenderBuffers.volTex);
+ if (mRenderBuffers.VBO) glDeleteBuffersARB(1, &mRenderBuffers.VBO);
+ if (mRenderBuffers.IBO) glDeleteBuffersARB(1, &mRenderBuffers.IBO);
+ if (mRenderBuffers.matTex) glDeleteTextures(1, &mRenderBuffers.matTex);
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::clear()
+{
+ base::SimScene::clear();
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::postSim(float dt, RegularCell3D* fluidSim)
+{
+ for (int i = 0; i < mActors.size(); i++)
+ {
+ mActors[i]->postSim(dt);
+ }
+
+ mFrameNr++;
+ mNoFractureFrames--;
+ mNoSoundFrames--;
+}
+
+void SimScene::profileBegin(const char* name)
+{
+}
+
+void SimScene::profileEnd(const char* name)
+{
+}
+
+// --------------------------------------------------------------------------------------------
+bool SimScene::addXml(const std::string &path, const std::string &filename, bool ignoreVisualMesh,
+ float scale, const PxTransform &trans,
+ Shader* defaultShader, const ShaderMaterial &defaultMat)
+{
+ XMLParser *p = XMLParser::getInstance();
+ if (!p->open(path + "\\" + filename))
+ return false;
+
+ diffuseTexNames.clear();
+
+ bumpTexNames.clear();
+ specularTexNames.clear();
+ emissiveReflectSpecPowerTexNames.clear();
+
+
+ while (!p->endOfFile()) {
+ if (!p->endOfFile() && p->tagName == "SurfaceMaterials") {
+ p->readNextTag();
+ while (!p->endOfFile() && p->tagName != "SurfaceMaterials") {
+ if (p->tagName == "SurfaceMaterial") {
+ for (int i = 0; i < (int)p->vars.size(); i++) {
+ if (p->vars[i].name == "name") {
+ }
+ else if (p->vars[i].name == "map_Kd") {
+ diffuseTexNames.push_back(path + "\\" + p->vars[i].value);
+
+ string suffix = p->vars[i].value.substr(p->vars[i].value.size()-4);
+ string prefix = p->vars[i].value.substr(0, p->vars[i].value.size()-5);
+
+ bumpTexNames.push_back(path + "\\" + prefix + "n" + suffix);
+ specularTexNames.push_back(path + "\\" + prefix + "s" + suffix);
+ emissiveReflectSpecPowerTexNames.push_back(path + "\\" + prefix + "e" + suffix);
+ }
+ }
+ }
+ p->readNextTag();
+ }
+ p->readNextTag();
+ }
+ else if (!p->endOfFile() && p->tagName == "Compound") {
+ Compound *c = (Compound*)createCompound();
+ if (!c->createFromXml(p, scale, trans, ignoreVisualMesh)) {
+ delete c;
+ return false;
+ }
+
+ addCompound(c);
+ c->setShader(defaultShader, defaultMat);
+ }
+ else
+ p->readNextTag();
+ }
+
+ p->close();
+ loadAndCreateTextureArrays();
+ return true;
+}
+
+// ------------------------- Renderering --------------------------------
+
+GLuint SimScene::loadTextureArray(std::vector<std::string>& names) {
+
+ GLuint texid;
+ glGenTextures(1, &texid);
+ glBindTexture( GL_TEXTURE_2D_ARRAY_EXT, texid);
+
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+
+ class BmpLoaderBuffer : public ::BmpLoaderBuffer, public ::physx::shdfnd::UserAllocated {};
+ class CPPJPEGWrapper : public ::CPPJPEGWrapper, public ::physx::shdfnd::UserAllocated {};
+ BmpLoaderBuffer *bmps;
+ CPPJPEGWrapper *jpgs;
+ bmps = PX_NEW(BmpLoaderBuffer)[names.size()];
+ jpgs = PX_NEW(CPPJPEGWrapper)[names.size()];
+
+ char path[512];
+
+ int w = 0, h = 0, d = 0;
+ for (int i = 0; i < (int)names.size(); i++) {
+
+ if (names[i].size() > 0) {
+ sprintf_s(path, 512, "%s", names[i].c_str());
+ int len = strlen(path);
+
+ int mw = 0, mh = 0;
+ if (strcmp(&path[len-4], ".jpg") == 0) {
+ jpgs[i].LoadJPEG(path, "false");
+
+ mw = jpgs[i].GetWidth();
+ mh = jpgs[i].GetHeight();
+ } else {
+ bmps[i].loadFile(path);
+ mw = bmps[i].mWidth;
+ mh = bmps[i].mHeight;
+ }
+
+ if ((mw != 0) && (mh != 0)) {
+ if ( ((w != 0) && (w != mw)) ||
+ ((h != 0) && (h != mh)) ) {
+ printf("Textures in array need to be same size!\n");
+ }
+ w = mw;
+ h = mh;
+ }
+ }
+ }
+ d = names.size();
+ if (w == 0) {
+ w=h=128;
+
+ }
+ unsigned char* tmpBlack = (unsigned char*)PX_ALLOC(sizeof(unsigned char)*w*h*3,PX_DEBUG_EXP("RT_FRACTURE"));
+ memset(tmpBlack, 0, w*h*3);
+
+ glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGB8, w, h, d, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ for (int i = 0; i < (int)names.size(); i++) {
+ glTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, 0, 0, i, w, h, 1, GL_RGB, GL_UNSIGNED_BYTE, (bmps[i].mRGB) ? bmps[i].mRGB : (
+ jpgs[i].GetData() ? jpgs[i].GetData() : tmpBlack)
+ );
+
+ }
+
+
+ glGenerateMipmapEXT(GL_TEXTURE_2D_ARRAY_EXT);
+
+ PX_FREE(tmpBlack);
+ PX_DELETE_ARRAY(bmps);
+ PX_DELETE_ARRAY(jpgs);
+
+/* names
+ // 2D Texture arrays a loaded just like 3D textures
+ glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGBA8, images[0].getWidth(), images[0].getHeight(), NIMAGES, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ for (int i = 0; i < NIMAGES; i++) {
+ glTexSubImage3D( GL_TEXTURE_2D_ARRAY_EXT, 0, 0, 0, i, images[i].getWidth(), images[i].getHeight(), 1, images[i].getFormat(), images[i].getType(), images[i].getLevel(0));
+ }
+*/
+ return texid;
+
+}
+
+void SimScene::loadAndCreateTextureArrays() {
+ diffuseTexArray = loadTextureArray(diffuseTexNames);
+ bumpTexArray = loadTextureArray(bumpTexNames);
+ specularTexArray = loadTextureArray(specularTexNames);
+ emissiveReflectSpecPowerTexArray = loadTextureArray(emissiveReflectSpecPowerTexNames);
+
+}
+
+// --------------------------------------------------------------------------------------------
+#define WIDTH 128
+#define HEIGHT 128
+#define DEPTH 128
+#define BYTES_PER_TEXEL 3
+#define LAYER(r) (WIDTH * HEIGHT * r * BYTES_PER_TEXEL)
+// 2->1 dimension mapping function
+#define TEXEL2(s, t) (BYTES_PER_TEXEL * (s * WIDTH + t))
+// 3->1 dimension mapping function
+#define TEXEL3(s, t, r) (TEXEL2(s, t) + LAYER(r))
+
+// --------------------------------------------------------------------------------------------
+void SimScene::create3dTexture()
+{
+ unsigned char *texels = (unsigned char *)malloc(WIDTH * HEIGHT * DEPTH * BYTES_PER_TEXEL);
+ memset(texels, 0, WIDTH*HEIGHT*DEPTH);
+
+ // each of the following loops defines one layer of our 3d texture, there are 3 unsigned bytes (red, green, blue) for each texel so each iteration sets 3 bytes
+ // the memory pointed to by texels is technically a single dimension (C++ won't allow more than one dimension to be of variable length), the
+ // work around is to use a mapping function like the one above that maps the 3 coordinates onto one dimension
+ // layer 0 occupies the first (width * height * bytes per texel) bytes, followed by layer 1, etc...
+ // define layer 0 as red
+
+// Perlin perlin(8,4,1,91114);
+ unsigned char* tt = texels;
+ float idx = 1.0f / DEPTH;
+ for (int i = 0; i < DEPTH; i++) {
+ for (int j = 0; j < HEIGHT; j++) {
+ for (int k = 0; k < WIDTH; k++) {
+ //float v[3] = {i*idx, j*idx, k*idx};
+ //float val = (perlin.noise3(v)*0.5f + 0.5f)*255.0f;//cos( (perlin.Noise3(i*0.01f,j*0.01f,k*0.01f)*255000 + i*0.)*5.0f)*0.5f+0.5f;//perlin.Noise3(k,j,i)*255.0f;
+ //(cos(perlin.Noise3(k,j,i) + j*0.01f) + 1.0f)*0.5f*255;
+ unsigned char val = rand() % 255;
+ tt[0] = val;
+ tt[1] = val;
+ tt[2] = val;
+ tt+=3;
+ }
+ }
+ }
+
+ // request 1 texture name from OpenGL
+ glGenTextures(1, &mRenderBuffers.volTex);
+ // tell OpenGL we're going to be setting up the texture name it gave us
+ glBindTexture(GL_TEXTURE_3D, mRenderBuffers.volTex);
+ // when this texture needs to be shrunk to fit on small polygons, use linear interpolation of the texels to determine the color
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ // when this texture needs to be magnified to fit on a big polygon, use linear interpolation of the texels to determine the color
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ // we want the texture to repeat over the S axis, so if we specify coordinates out of range we still get textured.
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ // same as above for T axis
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ // same as above for R axis
+ glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
+ // this is a 3d texture, level 0 (max detail), GL should store it in RGB8 format, its WIDTHxHEIGHTxDEPTH in size,
+ // it doesnt have a border, we're giving it to GL in RGB format as a series of unsigned bytes, and texels is where the texel data is.
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB8, WIDTH, HEIGHT, DEPTH, 0, GL_RGB, GL_UNSIGNED_BYTE, texels);
+
+ glBindTexture(GL_TEXTURE_3D, 0);
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::createRenderBuffers()
+{
+ if (!mRenderBuffers.VBO) {
+ glGenBuffersARB(1, &mRenderBuffers.VBO);
+ }
+ if (!mRenderBuffers.IBO) {
+ glGenBuffersARB(1, &mRenderBuffers.IBO);
+ }
+ if (!mRenderBuffers.matTex) {
+ glGenTextures(1, &mRenderBuffers.matTex);
+ glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ }
+
+ // Count number of vertices and indices in convexes
+ // Count number of indices in convexes
+ mRenderBuffers.numConvexes = 0;
+ mRenderBuffers.numVertices = 0;
+ mRenderBuffers.numIndices = 0;
+
+ for (int k = 0; k < (int)mActors.size(); k++)
+ {
+ const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ if (((Compound*)mCompounds[i])->getShader() != mShader)
+ continue;
+ const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
+ mRenderBuffers.numConvexes += convexes.size();
+ for (int j = 0; j < (int)convexes.size(); j++) {
+ mRenderBuffers.numVertices += convexes[j]->getVisVertices().size();
+ mRenderBuffers.numIndices += convexes[j]->getVisTriIndices().size();
+ }
+ }
+ }
+
+ if (mRenderBuffers.numVertices == 0 || mRenderBuffers.numIndices == 0)
+ return;
+
+ mRenderBuffers.tmpVertices.resize(mRenderBuffers.numVertices*12);
+ mRenderBuffers.tmpIndices.resize(mRenderBuffers.numIndices);
+ float* vp = &mRenderBuffers.tmpVertices[0];
+ unsigned int* ip = &mRenderBuffers.tmpIndices[0];
+
+ int sumV = 0;
+ // Make cpu copy of VBO and IBO
+
+ int convexNr = 0;
+
+ for (int k = 0; k < (int)mActors.size(); k++)
+ {
+ const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ if (((Compound*)mCompounds[i])->getShader() != mShader)
+ continue;
+
+ const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
+ for (int j = 0; j < (int)convexes.size(); j++, convexNr++) {
+ Convex* c = (Convex*)convexes[j];
+ // PxVec3 matOff = c->getMaterialOffset();
+
+ int nv = c->getVisVertices().size();
+ int ni = c->getVisTriIndices().size();
+
+ if (nv > 0) {
+ float* cvp = (float*)&c->getVisVertices()[0]; // float3
+ float* cnp = (float*)&c->getVisNormals()[0]; // float3
+ // float* c3dtp = (float*)&c->getVisVertices()[0]; // float3
+ float* c2dtp = (float*)&c->getVisTexCoords()[0]; // float2
+ float* ctanp = (float*)&c->getVisTangents()[0]; // float3
+
+ int* cip = (int*)&c->getVisTriIndices()[0];
+ for (int k = 0; k < nv; k++) {
+ *(vp++) = *(cvp++);
+ *(vp++) = *(cvp++);
+ *(vp++) = *(cvp++);
+
+ *(vp++) = *(cnp++);
+ *(vp++) = *(cnp++);
+ *(vp++) = *(cnp++);
+
+ *(vp++) = *(ctanp++);
+ *(vp++) = *(ctanp++);
+ *(vp++) = *(ctanp++);
+ *(vp++) = (float)convexNr;
+
+ *(vp++) = *(c2dtp++);
+ *(vp++) = *(c2dtp++);
+
+ }
+ for (int k = 0; k < ni; k++) {
+ *(ip++) = *(cip++) + sumV;
+ }
+ }
+ //memcpy(ip, cip, sizeof(int)*ni);
+ //ip += 3*ni;
+
+ //std::vector<PxVec3> mTriVertices;
+ //std::vector<PxVec3> mTriNormals;
+ //std::vector<int> mTriIndices;
+ //std::vector<float> mTriTexCoords; // 3d + obj nr
+ sumV += nv;
+ }
+ }
+ }
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.VBO);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.tmpVertices.size()*sizeof(float), &mRenderBuffers.tmpVertices[0], GL_STATIC_DRAW);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.IBO);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.tmpIndices.size()*sizeof(unsigned int), &mRenderBuffers.tmpIndices[0], GL_STATIC_DRAW);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+ int oldTexSize = mRenderBuffers.texSize;
+ if (mRenderBuffers.texSize == 0) {
+ // First time
+ oldTexSize = 1;
+ mRenderBuffers.texSize = 32;
+ }
+
+ while (1) {
+ int convexesPerRow = mRenderBuffers.texSize / 4;
+ if (convexesPerRow * mRenderBuffers.texSize >= mRenderBuffers.numConvexes) {
+ break;
+ } else {
+ mRenderBuffers.texSize *= 2;
+ }
+ }
+ if (mRenderBuffers.texSize != oldTexSize) {
+ mRenderBuffers.tmpTexCoords.resize(mRenderBuffers.texSize*mRenderBuffers.texSize*4);
+ // Let's allocate texture
+ glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_ARB, mRenderBuffers.texSize, mRenderBuffers.texSize, 0, GL_RGBA, GL_FLOAT, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ mRenderBufferVersion = mSceneVersion;
+
+ //instanceVBOCPU.resize( newSize * 16);
+}
+
+// --------------------------------------------------------------------------------------------
+void SimScene::updateConvexesTex()
+{
+ float* tt = &mRenderBuffers.tmpTexCoords[0];
+
+ for (int k = 0; k < (int)mActors.size(); k++)
+ {
+ const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
+ for (int i = 0; i < (int)mCompounds.size(); i++) {
+ if ( ((Compound*)mCompounds[i])->getShader() != mShader)
+ continue;
+
+ const shdfnd::Array<base::Convex*> &convexes = mCompounds[i]->getConvexes();
+ for (int j = 0; j < (int)convexes.size(); j++) {
+ Convex* c = (Convex*)convexes[j];
+
+ PxMat44 pose(convexes[j]->getGlobalPose());
+ float* mp = (float*)pose.front();
+
+ float* ta = tt;
+ for (int k = 0; k < 16; k++) {
+ *(tt++) = *(mp++);
+ }
+ PxVec3 matOff = c->getMaterialOffset();
+ ta[3] = matOff.x;
+ ta[7] = matOff.y;
+ ta[11] = matOff.z;
+ int idFor2DTex = c->getSurfaceMaterialId();
+ int idFor3DTex = 0;
+ const int MAX_3D_TEX = 8;
+ ta[15] = (float)(idFor2DTex*MAX_3D_TEX + idFor3DTex);
+ }
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mRenderBuffers.texSize, mRenderBuffers.texSize,
+ GL_RGBA, GL_FLOAT, &mRenderBuffers.tmpTexCoords[0]);
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+// --------------------------------------------------------------------------------------------
+#ifdef USE_OPTIX
+
+// Updater class for Optix renderer.
+class FractureModelUpdate : public optix_demo::IModelUpdate
+{
+public:
+
+ FractureModelUpdate( shdfnd::Array< Compound* > const& compounds, bool complete_update )
+ : m_compounds(compounds), m_is_complete_update( complete_update )
+ {}
+
+ bool isCompleteUpdate() const {return m_is_complete_update;}
+ void to_first();
+ void to_next();
+ bool at_end() const;
+
+ size_t num_vertices() const {return (*m_iconvex)->getVisVertices().size();}
+ size_t num_indices() const {return (*m_iconvex)->getVisTriIndices().size();}
+ float const* vertices() const {return &(*m_iconvex)->getVisVertices()[0].x;}
+ float const* normals() const {return &(*m_iconvex)->getVisNormals()[0].x;}
+ int const* indices() const {return &(*m_iconvex)->getVisTriIndices()[0];}
+
+ void global_transform( float* rmat3x3, float* translation );
+
+private:
+ void advance();
+ bool is_valid_convex( Convex const* c ) const
+ {
+ return !c->getVisVertices().empty();
+ }
+
+ shdfnd::Array< Compound* > const& m_compounds;
+ bool m_is_complete_update;
+ shdfnd::Array< Compound* >::ConstIterator m_icompound;
+ shdfnd::Array< Convex* >::ConstIterator m_iconvex;
+};
+
+void FractureModelUpdate::to_first()
+{
+ m_icompound = m_compounds.begin();
+ if (m_icompound == m_compounds.end()) return;
+
+ while ((*m_icompound)->getConvexes().empty()) {
+ ++m_icompound;
+ if (m_icompound == m_compounds.end()) return;
+ }
+ m_iconvex = (*m_icompound)->getConvexes().begin();
+ while (!is_valid_convex(*m_iconvex)) {
+ advance();
+ if (m_icompound == m_compounds.end()) return;
+ }
+}
+
+void FractureModelUpdate::to_next()
+{
+ if (m_icompound != m_compounds.end()) {
+ do {
+ advance();
+ } while (m_icompound != m_compounds.end() && !is_valid_convex(*m_iconvex));
+ }
+}
+
+void FractureModelUpdate::advance()
+{
+ if (m_iconvex != (*m_icompound)->getConvexes().end()) {
+ ++m_iconvex;
+ }
+ if (m_iconvex == (*m_icompound)->getConvexes().end()) {
+ // End of convexes of this compound.
+ do {
+ ++m_icompound;
+ if (m_icompound == m_compounds.end()) return;
+ } while ((*m_icompound)->getConvexes().empty());
+ m_iconvex = (*m_icompound)->getConvexes().begin();
+ }
+}
+
+bool FractureModelUpdate::at_end() const
+{
+ return m_icompound == m_compounds.end();
+}
+
+void FractureModelUpdate::global_transform( float* rmat3x3, float* translation )
+{
+ PxTransform pose = (*m_iconvex)->getGlobalPose();
+ PxMat33 rot(pose.q);
+ rmat3x3[0] = rot.column0.x; rmat3x3[1] = rot.column1.x; rmat3x3[2] = rot.column2.x;
+ rmat3x3[3] = rot.column0.y; rmat3x3[4] = rot.column1.y; rmat3x3[5] = rot.column2.y;
+ rmat3x3[6] = rot.column0.z; rmat3x3[7] = rot.column1.z; rmat3x3[8] = rot.column2.z;
+ translation[0] = pose.p.x;
+ translation[1] = pose.p.y;
+ translation[2] = pose.p.z;
+}
+
+#endif //USE_OPTIX
+
+extern bool gConvexTexOutdate;
+
+// --------------------------------------------------------------------------------------------
+void SimScene::draw(bool useShader)
+{
+ if (mDebugDraw) {
+ for (int k = 0; k < (int)mActors.size(); k++)
+ {
+ const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
+ for (int i = 0; i < (int)mCompounds.size(); i++)
+ mCompounds[i]->draw(false, true);
+ }
+ return;
+ }
+
+ int numCompounds = 0;
+ for (int k = 0; k < (int)mActors.size(); k++)
+ {
+ const shdfnd::Array<base::Compound*>& mCompounds = mActors[k]->getCompounds();
+ numCompounds += mCompounds.size();
+ }
+ if (numCompounds == 0) return;
+
+
+ if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPENGL) {
+#if USE_CONVEX_RENDERER
+ mConvexRenderer.setShaderMaterial(mShader, mShaderMat);
+ mConvexRenderer.setTexArrays(diffuseTexArray, bumpTexArray,
+ specularTexArray, emissiveReflectSpecPowerTexArray);
+ mConvexRenderer.setVolTex(mRenderBuffers.volTex);
+ mConvexRenderer.render();
+#else
+ mConvexRenderer.setActive(false);
+
+ if (mRenderBufferVersion != mSceneVersion)
+ createRenderBuffers();
+
+ if (mRenderBuffers.numIndices > 0) {
+
+ if (gConvexTexOutdate) {
+ updateConvexesTex();
+ gConvexTexOutdate = false;
+ }
+
+ mShader->activate(mShaderMat);
+ // Assume convex all use the same shader
+
+ glActiveTexture(GL_TEXTURE7);
+ glBindTexture(GL_TEXTURE_3D, mRenderBuffers.volTex);
+
+ glActiveTexture(GL_TEXTURE8);
+ glBindTexture(GL_TEXTURE_2D, mRenderBuffers.matTex);
+
+
+
+ glActiveTexture(GL_TEXTURE10);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, diffuseTexArray);
+ glActiveTexture(GL_TEXTURE11);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, bumpTexArray);
+ glActiveTexture(GL_TEXTURE12);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, specularTexArray);
+ glActiveTexture(GL_TEXTURE13);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, emissiveReflectSpecPowerTexArray);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ float itt = 1.0f/mRenderBuffers.texSize;
+
+ mShader->setUniform("diffuseTexArray", 10);
+ mShader->setUniform("bumpTexArray", 11);
+ mShader->setUniform("specularTexArray", 12);
+ mShader->setUniform("emissiveReflectSpecPowerTexArray", 13);
+
+ mShader->setUniform("ttt3D", 7);
+ mShader->setUniform("transTex", 8);
+ mShader->setUniform("transTexSize", mRenderBuffers.texSize);
+ mShader->setUniform("iTransTexSize", itt);
+ mShader->setUniform("bumpTextureUVScale", bumpTextureUVScale);
+ mShader->setUniform("extraNoiseScale",extraNoiseScale);
+ mShader->setUniform("roughnessScale", roughnessScale);
+ if (mShaderMat.color[3] < 1.0f) {
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST);
+ glColor4f(mShaderMat.color[0], mShaderMat.color[1], mShaderMat.color[2], mShaderMat.color[3]);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, mRenderBuffers.VBO);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mRenderBuffers.IBO);
+
+ int stride = 12*sizeof(float);
+ glVertexPointer(3, GL_FLOAT, stride, 0);
+
+ glNormalPointer(GL_FLOAT, stride, (void*)(3*sizeof(float)));
+
+ glTexCoordPointer(4, GL_FLOAT, stride, (void*)(6*sizeof(float)));
+
+ glClientActiveTexture(GL_TEXTURE1);
+ glTexCoordPointer(2, GL_FLOAT, stride, (void*)(10*sizeof(float)));
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDrawElements(GL_TRIANGLES, mRenderBuffers.numIndices, GL_UNSIGNED_INT, 0);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTexture(GL_TEXTURE0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+
+ if (mShaderMat.color[3] < 1.0f) {
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ }
+
+ mShader->deactivate();
+ }
+#endif
+ }
+#ifdef USE_OPTIX
+ else if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) {
+
+ FractureModelUpdate update( mCompounds, mOptixBufferVersion != mSceneVersion );
+
+ if (mOptixBufferVersion != mSceneVersion) {
+ // Complete buffer update.
+ mOptixBufferVersion = mSceneVersion;
+ }
+
+ Profiler::getInstance()->begin("Optix data update");
+
+ SampleViewerScene::getOptixRenderer()->update( update );
+
+ OptixRenderer::Camera cam;
+ const size_t size_of_float3 = sizeof(float) * 3;
+ PxVec3 lookat = mCameraPos + mCameraDir;
+ memcpy( cam.eye, &mCameraPos.x, size_of_float3);
+ memcpy( cam.lookat, &lookat.x, size_of_float3);
+ memcpy( cam.up, &mCameraUp.x, size_of_float3);
+ cam.fov = mCameraFov;
+ Profiler::getInstance()->end("Optix data update");
+
+ Profiler::getInstance()->begin("Optix render");
+ SampleViewerScene::getOptixRenderer()->render( cam );
+ Profiler::getInstance()->end("Optix render");
+ }
+#endif // USE_OPTIX
+
+}
+
+
+// --------------------------------------------------------------------------------------------
+void SimScene::dumpSceneGeometry()
+{
+#ifdef USE_OPTIX
+ if( SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX && SampleViewerScene::getOptixRenderer()) {
+ SampleViewerScene::getOptixRenderer()->dump_geometry();
+ }
+#endif
+}
diff --git a/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.h b/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.h
new file mode 100644
index 00000000..9befd850
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Fracture/SimScene.h
@@ -0,0 +1,80 @@
+#ifndef SIM_SCENE
+#define SIM_SCENE
+
+#include "Shader.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxSimulationEventCallback.h"
+#include <PsArray.h>
+#include "ConvexRenderer.h"
+
+#include "SimSceneBase.h"
+
+using namespace physx::fracture;
+
+class TerrainMesh;
+struct ParticlesDesc;
+class Particles;
+class RegularCell3D;
+class Actor;
+
+class SimScene : public base::SimScene
+{
+public:
+ static SimScene* createSimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
+protected:
+ SimScene(PxPhysics *pxPhysics, PxCooking *pxCooking, bool isGrbScene, float minConvexSize, PxMaterial* defaultMat, const char *resourcePath);
+public:
+ virtual ~SimScene();
+
+ virtual void createSingletons();
+
+ virtual base::Actor* createActor();
+ virtual base::Convex* createConvex();
+ virtual base::Compound* createCompound(PxReal contactOffset = 0.005f, PxReal restOffset = -0.001f);
+
+ virtual void clear();
+
+ virtual void profileBegin(const char* name);
+ virtual void profileEnd(const char* name);
+
+ bool addXml(const std::string &path, const std::string &filename, bool ignoreVisualMesh, float scale, const PxTransform &trans,
+ Shader* defaultShader, const ShaderMaterial &defaultMat);
+
+ void postSim(float dt, RegularCell3D* fluidSim);
+
+ //Particles* getParticles() { return mParticles; }
+
+ ConvexRenderer &getConvexRenderer() { return mConvexRenderer; }
+
+ void draw(bool useShader);
+ void setShaderMaterial(Shader* shader, const ShaderMaterial& mat) {this->mShader = shader; this->mShaderMat = mat;}
+ void setFractureForceThreshold(float threshold) { mFractureForceThreshold = threshold; }
+ void createRenderBuffers();
+ void dumpSceneGeometry();
+
+ void loadAndCreateTextureArrays();
+
+ std::vector<std::string> diffuseTexNames;
+ std::vector<std::string> bumpTexNames;
+ std::vector<std::string> specularTexNames;
+ std::vector<std::string> emissiveReflectSpecPowerTexNames;
+
+protected:
+
+ virtual void create3dTexture();
+ virtual void updateConvexesTex();
+
+ GLuint diffuseTexArray, bumpTexArray, specularTexArray, emissiveReflectSpecPowerTexArray;
+
+ GLuint loadTextureArray(std::vector<std::string>& names);
+
+ //Particles *mParticles;
+
+ ConvexRenderer mConvexRenderer;
+
+ Shader* mShader;
+ ShaderMaterial mShaderMat;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/FrameBufferObject.cpp b/KaplaDemo/samples/sampleViewer3/FrameBufferObject.cpp
new file mode 100644
index 00000000..103c9c5a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FrameBufferObject.cpp
@@ -0,0 +1,405 @@
+//glew uses iostreams which uses exceptions, so we need to turn off the following warning
+//warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
+#pragma warning( disable : 4530 )
+
+/*
+ Copyright (c) 2005,
+ Aaron Lefohn ([email protected])
+ Robert Strzodka ([email protected])
+ Adam Moerschell ([email protected])
+ All rights reserved.
+
+ This software is licensed under the BSD open-source license. See
+ http://www.opensource.org/licenses/bsd-license.php for more detail.
+
+ *************************************************************
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ Neither the name of the University of Californa, Davis nor the names of
+ the contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGE.
+*/
+
+#include "FrameBufferObject.h"
+#include <iostream>
+using namespace std;
+
+#define LOG_FBO_CALLS 0
+
+FrameBufferObject::FrameBufferObject()
+ : m_fboId(_GenerateFboId()),
+ m_savedFboId(0)
+{
+ // Bind this FBO so that it actually gets created now
+ _GuardedBind();
+ _GuardedUnbind();
+}
+
+FrameBufferObject::~FrameBufferObject()
+{
+#if LOG_FBO_CALLS
+ printf("deleting FBO %d\n",m_fboId);
+#endif
+
+ glDeleteFramebuffersEXT(1, &m_fboId);
+}
+
+void FrameBufferObject::Bind()
+{
+#if LOG_FBO_CALLS
+ printf("binding framebuffer %d\n",m_fboId);
+#endif
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
+}
+
+void FrameBufferObject::Disable()
+{
+#if LOG_FBO_CALLS
+ printf("binding window framebuffer \n");
+#endif
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+}
+
+void
+FrameBufferObject::AttachTexture( GLenum texTarget, GLuint texId,
+ GLenum attachment, int mipLevel, int zSlice )
+{
+ _GuardedBind();
+
+ /*
+#ifndef NDEBUG
+ if( GetAttachedId(attachment) != texId ) {
+#endif
+ */
+
+ _FramebufferTextureND( attachment, texTarget,
+ texId, mipLevel, zSlice );
+
+/*
+#ifndef NDEBUG
+ }
+ else {
+ cerr << "FrameBufferObject::AttachTexture PERFORMANCE WARNING:\n"
+ << "\tRedundant bind of texture (id = " << texId << ").\n"
+ << "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
+ }
+#endif
+*/
+
+ _GuardedUnbind();
+}
+
+void
+FrameBufferObject::AttachTextures( int numTextures, GLenum texTarget[], GLuint texId[],
+ GLenum attachment[], int mipLevel[], int zSlice[] )
+{
+ for(int i = 0; i < numTextures; ++i) {
+ AttachTexture( texTarget[i], texId[i],
+ attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i),
+ mipLevel ? mipLevel[i] : 0,
+ zSlice ? zSlice[i] : 0 );
+ }
+}
+
+void
+FrameBufferObject::AttachRenderBuffer( GLuint buffId, GLenum attachment )
+{
+ _GuardedBind();
+
+#ifndef NDEBUG
+ if( GetAttachedId(attachment) != buffId ) {
+#endif
+
+#if LOG_FBO_CALLS
+ printf("fbo %d: attaching renderbuffer to attachment point %d\n",m_fboId,attachment);
+#endif
+
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_RENDERBUFFER_EXT, buffId);
+
+#ifndef NDEBUG
+ }
+ else {
+ cerr << "FrameBufferObject::AttachRenderBuffer PERFORMANCE WARNING:\n"
+ << "\tRedundant bind of Renderbuffer (id = " << buffId << ")\n"
+ << "\tHINT : Compile with -DNDEBUG to remove this warning.\n";
+ }
+#endif
+
+ _GuardedUnbind();
+}
+
+void
+FrameBufferObject::AttachRenderBuffers( int numBuffers, GLuint buffId[], GLenum attachment[] )
+{
+ for(int i = 0; i < numBuffers; ++i) {
+ AttachRenderBuffer( buffId[i],
+ attachment ? attachment[i] : (GL_COLOR_ATTACHMENT0_EXT + i) );
+ }
+}
+
+void
+FrameBufferObject::Unattach( GLenum attachment )
+{
+ _GuardedBind();
+ GLenum type = GetAttachedType(attachment);
+
+#if LOG_FBO_CALLS
+ printf("fbo %d: detatching from attachment point %d\n",m_fboId,attachment);
+#endif
+
+ switch(type) {
+ case GL_NONE:
+ break;
+ case GL_RENDERBUFFER_EXT:
+ AttachRenderBuffer( 0, attachment );
+ break;
+ case GL_TEXTURE:
+ AttachTexture( GL_TEXTURE_2D, 0, attachment );
+ break;
+ default:
+ cerr << "FrameBufferObject::unbind_attachment ERROR: Unknown attached resource type\n";
+ }
+ _GuardedUnbind();
+}
+
+void
+FrameBufferObject::UnattachAll()
+{
+ int numAttachments = GetMaxColorAttachments();
+ for(int i = 0; i < numAttachments; ++i) {
+ Unattach( GL_COLOR_ATTACHMENT0_EXT + i );
+ }
+}
+
+GLint FrameBufferObject::GetMaxColorAttachments()
+{
+ GLint maxAttach = 0;
+ glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach );
+ return maxAttach;
+}
+
+GLuint FrameBufferObject::_GenerateFboId()
+{
+ GLuint id = 0;
+ glGenFramebuffersEXT(1, &id);
+
+#if LOG_FBO_CALLS
+ printf("created FBO %d\n",id);
+#endif
+
+ return id;
+}
+
+void FrameBufferObject::_GuardedBind()
+{
+ // Only binds if m_fboId is different than the currently bound FBO
+ glGetIntegerv( GL_FRAMEBUFFER_BINDING_EXT, &m_savedFboId );
+ if (m_fboId != (GLuint)m_savedFboId) {
+
+#if LOG_FBO_CALLS
+ printf("binding framebuffer %d\n",m_fboId);
+#endif
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fboId);
+ }
+}
+
+void FrameBufferObject::_GuardedUnbind()
+{
+ // Returns FBO binding to the previously enabled FBO
+ if (m_fboId != (GLuint)m_savedFboId) {
+#if LOG_FBO_CALLS
+ printf("binding framebuffer %d\n",m_savedFboId);
+#endif
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)m_savedFboId);
+ }
+}
+
+void
+FrameBufferObject::_FramebufferTextureND( GLenum attachment, GLenum texTarget,
+ GLuint texId, int mipLevel,
+ int zSlice )
+{
+#if LOG_FBO_CALLS
+ printf("fbo %d: attaching texture %d to attachment point %d\n",m_fboId,texId,attachment);
+#endif
+
+ if (texTarget == GL_TEXTURE_1D) {
+ glFramebufferTexture1DEXT( GL_FRAMEBUFFER_EXT, attachment,
+ GL_TEXTURE_1D, texId, mipLevel );
+ }
+ else if (texTarget == GL_TEXTURE_3D) {
+ glFramebufferTexture3DEXT( GL_FRAMEBUFFER_EXT, attachment,
+ GL_TEXTURE_3D, texId, mipLevel, zSlice );
+ }
+ else {
+ // Default is GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, or cube faces
+ glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, attachment,
+ texTarget, texId, mipLevel );
+ }
+}
+
+#ifndef NDEBUG
+bool FrameBufferObject::IsValid( ostream& ostr )
+{
+ _GuardedBind();
+
+#if LOG_FBO_CALLS
+ printf("fbo %d: checking for FBO errors\n",m_fboId);
+#endif
+
+ bool isOK = false;
+
+ GLenum status;
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ switch(status) {
+ case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
+ isOK = true;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
+ isOK = false;
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
+ isOK = false;
+ break;
+ default:
+ ostr << "glift::CheckFramebufferStatus() ERROR:\n\t"
+ << "Unknown ERROR\n";
+ isOK = false;
+ }
+
+ _GuardedUnbind();
+ return isOK;
+}
+#endif // NDEBUG
+
+/// Accessors
+GLenum FrameBufferObject::GetAttachedType( GLenum attachment )
+{
+#if LOG_FBO_CALLS
+ printf("querying type of attachment at %d\n",attachment);
+#endif
+
+ // Returns GL_RENDERBUFFER_EXT or GL_TEXTURE
+ _GuardedBind();
+ GLint type = 0;
+ glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT,
+ &type);
+ _GuardedUnbind();
+ return GLenum(type);
+}
+
+GLuint FrameBufferObject::GetAttachedId( GLenum attachment )
+{
+#if LOG_FBO_CALLS
+ printf("getting id of attachment at %d\n",attachment);
+#endif
+
+ _GuardedBind();
+ GLint id = 0;
+ glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT,
+ &id);
+ _GuardedUnbind();
+ return GLuint(id);
+}
+
+GLint FrameBufferObject::GetAttachedMipLevel( GLenum attachment )
+{
+#if LOG_FBO_CALLS
+ printf("getting mip level of attachment at %d\n",attachment);
+#endif
+
+ _GuardedBind();
+ GLint level = 0;
+ glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT,
+ &level);
+ _GuardedUnbind();
+ return level;
+}
+
+GLint FrameBufferObject::GetAttachedCubeFace( GLenum attachment )
+{
+#if LOG_FBO_CALLS
+ printf("getting cube face id of attachment at %d\n",attachment);
+#endif
+
+ _GuardedBind();
+ GLint level = 0;
+ glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT,
+ &level);
+ _GuardedUnbind();
+ return level;
+}
+
+GLint FrameBufferObject::GetAttachedZSlice( GLenum attachment )
+{
+#if LOG_FBO_CALLS
+ printf("querying z slice of attachment at %d\n",attachment);
+#endif
+ _GuardedBind();
+ GLint slice = 0;
+ glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER_EXT, attachment,
+ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT,
+ &slice);
+ _GuardedUnbind();
+ return slice;
+}
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/FrameBufferObject.h b/KaplaDemo/samples/sampleViewer3/FrameBufferObject.h
new file mode 100644
index 00000000..c74c68bc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/FrameBufferObject.h
@@ -0,0 +1,210 @@
+/*
+ Copyright (c) 2005,
+ Aaron Lefohn ([email protected])
+ Robert Strzodka ([email protected])
+ Adam Moerschell ([email protected])
+ All rights reserved.
+
+ This software is licensed under the BSD open-source license. See
+ http://www.opensource.org/licenses/bsd-license.php for more detail.
+
+ *************************************************************
+ Redistribution and use in source and binary forms, with or
+ without modification, are permitted provided that the following
+ conditions are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ Neither the name of the University of Californa, Davis nor the names of
+ the contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ OF SUCH DAMAGE.
+*/
+
+#ifndef UCDAVIS_FRAMEBUFFER_OBJECT_H
+#define UCDAVIS_FRAMEBUFFER_OBJECT_H
+
+#include <GL/glew.h>
+#include <iostream>
+
+/*!
+FramebufferObject Class. This class encapsulates the FramebufferObject
+(FBO) OpenGL spec. See the official spec at:
+ http://oss.sgi.com/projects/ogl-sample/registry/EXT/framebuffer_object.txt
+
+for details.
+
+A framebuffer object (FBO) is conceptually a structure containing pointers
+to GPU memory. The memory pointed to is either an OpenGL texture or an
+OpenGL RenderBuffer. FBOs can be used to render to one or more textures,
+share depth buffers between multiple sets of color buffers/textures and
+are a complete replacement for pbuffers.
+
+Performance Notes:
+ 1) It is more efficient (but not required) to call Bind()
+ on an FBO before making multiple method calls. For example:
+
+ FramebufferObject fbo;
+ fbo.Bind();
+ fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
+ fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
+ fbo.IsValid();
+
+ To provide a complete encapsulation, the following usage
+ pattern works correctly but is less efficient:
+
+ FramebufferObject fbo;
+ // NOTE : No Bind() call
+ fbo.AttachTexture(GL_TEXTURE_2D, texId0, GL_COLOR_ATTACHMENT0_EXT);
+ fbo.AttachTexture(GL_TEXTURE_2D, texId1, GL_COLOR_ATTACHMENT1_EXT);
+ fbo.IsValid();
+
+ The first usage pattern binds the FBO only once, whereas
+ the second usage binds/unbinds the FBO for each method call.
+
+ 2) Use FramebufferObject::Disable() sparingly. We have intentionally
+ left out an "Unbind()" method because it is largely unnecessary
+ and encourages rendundant Bind/Unbind coding. Binding an FBO is
+ usually much faster than enabling/disabling a pbuffer, but is
+ still a costly operation. When switching between multiple FBOs
+ and a visible OpenGL framebuffer, the following usage pattern
+ is recommended:
+
+ FramebufferObject fbo1, fbo2;
+ fbo1.Bind();
+ ... Render ...
+ // NOTE : No Unbind/Disable here...
+
+ fbo2.Bind();
+ ... Render ...
+
+ // Disable FBO rendering and return to visible window
+ // OpenGL framebuffer.
+ FramebufferObject::Disable();
+*/
+class FrameBufferObject
+{
+public:
+ /// Ctor/Dtor
+ FrameBufferObject();
+ virtual ~FrameBufferObject();
+
+ /// Bind this FBO as current render target
+ void Bind();
+
+ /// Bind a texture to the "attachment" point of this FBO
+ virtual void AttachTexture( GLenum texTarget,
+ GLuint texId,
+ GLenum attachment = GL_COLOR_ATTACHMENT0_EXT,
+ int mipLevel = 0,
+ int zSlice = 0 );
+
+ /// Bind an array of textures to multiple "attachment" points of this FBO
+ /// - By default, the first 'numTextures' attachments are used,
+ /// starting with GL_COLOR_ATTACHMENT0_EXT
+ virtual void AttachTextures( int numTextures,
+ GLenum texTarget[],
+ GLuint texId[],
+ GLenum attachment[] = NULL,
+ int mipLevel[] = NULL,
+ int zSlice[] = NULL );
+
+ /// Bind a render buffer to the "attachment" point of this FBO
+ virtual void AttachRenderBuffer( GLuint buffId,
+ GLenum attachment = GL_COLOR_ATTACHMENT0_EXT );
+
+ /// Bind an array of render buffers to corresponding "attachment" points
+ /// of this FBO.
+ /// - By default, the first 'numBuffers' attachments are used,
+ /// starting with GL_COLOR_ATTACHMENT0_EXT
+ virtual void AttachRenderBuffers( int numBuffers, GLuint buffId[],
+ GLenum attachment[] = NULL );
+
+ /// Free any resource bound to the "attachment" point of this FBO
+ void Unattach( GLenum attachment );
+
+ /// Free any resources bound to any attachment points of this FBO
+ void UnattachAll();
+
+ /// Is this FBO currently a valid render target?
+ /// - Sends output to std::cerr by default but can
+ /// be a user-defined C++ stream
+ ///
+ /// NOTE : This function works correctly in debug build
+ /// mode but always returns "true" if NDEBUG is
+ /// is defined (optimized builds)
+#ifndef NDEBUG
+ bool IsValid( std::ostream& ostr = std::cerr );
+#else
+ bool IsValid( std::ostream& ostr = std::cerr ) {
+ return true;
+ }
+#endif
+
+ /// BEGIN : Accessors
+ /// Is attached type GL_RENDERBUFFER_EXT or GL_TEXTURE?
+ GLenum GetAttachedType( GLenum attachment );
+
+ /// What is the Id of Renderbuffer/texture currently
+ /// attached to "attachement?"
+ GLuint GetAttachedId( GLenum attachment );
+
+ /// Which mipmap level is currently attached to "attachement?"
+ GLint GetAttachedMipLevel( GLenum attachment );
+
+ /// Which cube face is currently attached to "attachment?"
+ GLint GetAttachedCubeFace( GLenum attachment );
+
+ /// Which z-slice is currently attached to "attachment?"
+ GLint GetAttachedZSlice( GLenum attachment );
+ /// END : Accessors
+
+
+ /// BEGIN : Static methods global to all FBOs
+ /// Return number of color attachments permitted
+ static int GetMaxColorAttachments();
+
+ /// Disable all FBO rendering and return to traditional,
+ /// windowing-system controlled framebuffer
+ /// NOTE:
+ /// This is NOT an "unbind" for this specific FBO, but rather
+ /// disables all FBO rendering. This call is intentionally "static"
+ /// and named "Disable" instead of "Unbind" for this reason. The
+ /// motivation for this strange semantic is performance. Providing
+ /// "Unbind" would likely lead to a large number of unnecessary
+ /// FBO enablings/disabling.
+ static void Disable();
+ /// END : Static methods global to all FBOs
+
+protected:
+ void _GuardedBind();
+ void _GuardedUnbind();
+ void _FramebufferTextureND( GLenum attachment, GLenum texTarget,
+ GLuint texId, int mipLevel, int zSlice );
+ static GLuint _GenerateFboId();
+
+private:
+ GLuint m_fboId;
+ GLint m_savedFboId;
+};
+
+#endif
+
diff --git a/KaplaDemo/samples/sampleViewer3/GLFontData.h b/KaplaDemo/samples/sampleViewer3/GLFontData.h
new file mode 100644
index 00000000..b7242137
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/GLFontData.h
@@ -0,0 +1,1047 @@
+// auto generated don't touch
+
+static const int OGL_FONT_TEXTURE_WIDTH=256;
+static const int OGL_FONT_TEXTURE_HEIGHT=128;
+
+static const int OGL_FONT_CHARS_PER_ROW=16;
+static const int OGL_FONT_CHARS_PER_COL=8;
+
+static const int OGL_FONT_CHAR_BASE=32;
+
+int GLFontGlyphWidth[OGL_FONT_CHARS_PER_ROW*OGL_FONT_CHARS_PER_COL] = {
+6,7,8,11,10,10,11,7,10,8,10,10,8,9,8,10,
+11,11,11,11,11,11,11,11,11,11,8,8,10,10,10,10,
+11,10,10,10,11,10,10,10,10,10,9,11,10,10,10,10,
+10,11,11,10,10,10,10,10,10,10,10,10,10,7,10,10,
+8,10,10,10,9,9,10,9,10,8,8,11,8,10,10,10,
+10,9,10,10,9,10,10,10,10,10,9,9,6,9,10,10,
+10,10,9,10,10,10,10,10,9,9,9,9,9,8,10,10,
+10,11,10,10,10,10,10,10,10,10,10,10,9,10,10,10
+};
+
+unsigned char OGLFontData[OGL_FONT_TEXTURE_WIDTH * OGL_FONT_TEXTURE_HEIGHT] = {
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,117,68,0,101,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,85,68,0,0,0,0,0,0,0,0,117,32,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,101,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,101,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,68,117,0,117,85,0,0,0,
+0,0,0,0,0,0,0,68,169,254,185,136,48,0,0,0,0,0,0,0,16,152,185,85,0,0,0,117,169,0,0,0,
+0,0,0,0,0,0,0,48,221,254,152,16,0,0,0,0,0,0,0,0,0,0,0,0,237,237,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,221,205,68,0,0,0,0,0,0,0,0,152,237,136,16,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,101,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,
+0,0,0,0,0,0,221,101,0,152,152,0,0,0,0,0,0,0,0,0,0,0,0,0,152,101,0,221,32,0,0,0,
+0,0,0,0,0,0,85,254,117,254,68,117,101,0,0,0,0,0,0,0,169,117,16,221,48,0,48,221,16,0,0,0,
+0,0,0,0,0,0,0,221,169,48,254,117,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,101,0,0,0,0,0,0,0,0,0,0,0,16,205,205,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,101,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,221,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,
+0,0,0,0,0,0,185,68,0,117,117,0,0,0,0,0,0,0,0,0,0,0,0,0,221,32,32,221,0,0,0,0,
+0,0,0,0,0,0,169,205,0,254,0,0,0,0,0,0,0,0,0,0,254,0,0,117,117,0,205,68,0,0,0,0,
+0,0,0,0,0,0,0,254,117,16,254,117,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,237,117,0,0,0,0,0,0,0,0,0,0,0,0,0,16,237,117,0,0,0,0,0,0,
+0,0,0,0,0,0,185,117,68,101,101,221,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,
+0,0,0,0,0,0,101,32,0,68,68,0,0,0,0,0,0,0,0,0,0,32,117,117,254,117,169,205,117,32,0,0,
+0,0,0,0,0,0,169,221,16,254,0,0,0,0,0,0,0,0,0,0,221,32,0,152,101,136,136,0,0,0,0,0,
+0,0,0,0,0,0,0,205,205,117,237,32,0,0,0,0,0,0,0,0,0,0,0,0,117,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,237,0,0,0,0,0,0,
+0,0,0,0,0,0,32,85,68,32,101,48,0,0,0,0,0,0,0,0,0,0,0,0,101,32,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,221,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,117,185,185,117,221,152,117,0,0,0,
+0,0,0,0,0,0,48,237,205,254,0,0,0,0,0,0,0,0,0,0,101,205,136,205,85,205,0,0,0,0,0,0,
+0,0,0,0,0,0,16,169,254,221,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,101,205,136,152,0,0,0,0,0,0,0,0,0,0,0,0,0,185,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,85,0,237,16,0,0,0,0,
+0,0,0,0,0,0,0,48,221,254,152,16,0,0,0,0,0,0,0,0,0,32,68,16,221,48,0,0,0,0,0,0,
+0,0,0,0,0,48,221,169,221,185,0,0,136,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,237,101,32,254,48,0,0,0,0,0,0,0,0,0,0,0,0,185,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,221,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,68,254,68,117,205,68,32,0,0,0,
+0,0,0,0,0,0,0,0,0,254,237,237,48,0,0,0,0,0,0,0,0,0,0,169,117,136,205,205,48,0,0,0,
+0,0,0,0,0,185,185,0,101,254,68,0,185,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,32,0,0,32,0,0,0,0,0,0,0,0,0,0,68,68,68,205,117,68,68,32,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,48,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,205,237,185,237,205,185,85,0,0,0,
+0,0,0,0,0,0,0,0,0,254,48,237,152,0,0,0,0,0,0,0,0,0,101,185,85,185,0,68,205,0,0,0,
+0,0,0,0,0,254,117,0,0,185,237,16,221,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,237,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,185,237,205,185,185,101,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,221,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,117,0,205,48,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,0,185,185,0,0,0,0,0,0,0,0,32,221,16,117,117,0,0,254,0,0,0,
+0,0,0,0,0,221,185,0,0,16,237,205,237,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,169,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,254,48,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,101,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,205,48,16,237,0,0,0,0,0,0,
+0,0,0,0,0,0,136,68,0,254,48,254,101,0,0,0,0,0,0,0,0,185,85,0,85,185,0,68,205,0,0,0,
+0,0,0,0,0,117,254,117,0,32,185,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,101,254,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,221,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,68,221,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,221,0,101,152,0,0,0,0,0,0,
+0,0,0,0,0,0,152,221,254,254,237,117,0,0,0,0,0,0,0,0,117,152,0,0,0,136,205,205,48,0,0,0,
+0,0,0,0,0,0,117,221,254,221,117,136,254,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,205,169,0,0,0,0,0,0,0,0,0,0,0,0,0,48,254,85,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,68,16,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,32,237,152,16,0,0,0,0,0,0,0,0,0,0,68,237,136,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,16,254,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,221,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,16,152,254,101,0,0,0,0,0,0,0,0,221,221,85,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,169,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,101,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,16,32,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,48,205,254,221,101,0,0,0,0,0,0,0,0,0,0,0,0,48,117,169,117,0,0,0,0,0,
+0,0,0,0,0,0,117,205,254,254,169,32,0,0,0,0,0,0,0,0,0,0,185,254,254,237,136,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,136,185,0,0,0,0,0,0,0,0,0,0,0,136,185,185,185,185,48,0,0,0,0,
+0,0,0,0,0,0,16,117,237,254,221,101,0,0,0,0,0,0,0,0,0,0,185,185,185,185,185,185,101,0,0,0,
+0,0,0,0,0,0,85,221,254,254,169,16,0,0,0,0,0,0,0,0,0,0,101,221,254,205,85,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,221,254,254,221,117,16,0,0,0,
+0,0,0,0,0,16,237,117,0,68,254,68,0,0,0,0,0,0,0,0,0,0,221,221,152,254,117,0,0,0,0,0,
+0,0,0,0,0,0,117,48,0,32,205,221,0,0,0,0,0,0,0,0,0,0,101,32,0,68,254,117,0,0,0,0,
+0,0,0,0,0,0,0,0,101,254,254,0,0,0,0,0,0,0,0,0,0,0,185,185,117,117,117,32,0,0,0,0,
+0,0,0,0,0,0,185,152,32,0,48,68,0,0,0,0,0,0,0,0,0,0,117,117,117,117,136,254,117,0,0,0,
+0,0,0,0,0,32,254,101,0,68,254,152,0,0,0,0,0,0,0,0,0,85,254,68,0,117,254,32,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,32,0,0,101,254,136,0,0,0,
+0,0,0,0,0,117,221,0,0,0,152,169,0,0,0,0,0,0,0,0,0,0,32,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,85,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,
+0,0,0,0,0,0,0,32,221,152,254,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,101,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,205,0,0,0,0,
+0,0,0,0,0,117,254,0,0,0,185,185,0,0,0,0,0,0,0,0,0,205,152,0,0,0,169,152,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,0,0,0,0,185,185,0,0,0,
+0,0,0,0,0,185,152,0,0,0,101,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,85,254,48,0,0,0,0,0,0,0,0,0,0,0,0,16,221,117,0,0,0,0,
+0,0,0,0,0,0,0,185,117,117,254,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,169,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,237,68,0,0,0,0,
+0,0,0,0,0,101,254,117,0,32,254,101,0,0,0,0,0,0,0,0,0,254,117,0,0,0,117,205,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,32,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,254,85,0,0,0,
+0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,185,205,0,0,0,0,0,0,0,0,0,0,16,68,85,185,169,0,0,0,0,0,
+0,0,0,0,0,0,117,185,0,117,254,0,0,0,0,0,0,0,0,0,0,0,185,185,117,32,0,0,0,0,0,0,
+0,0,0,0,0,237,85,169,254,237,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,152,0,0,0,0,0,
+0,0,0,0,0,0,152,254,152,205,117,0,0,0,0,0,0,0,0,0,0,237,152,0,0,0,136,254,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,32,152,237,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,185,221,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,237,117,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,152,237,48,0,0,0,0,0,0,0,0,0,0,48,185,205,237,117,0,0,0,0,0,
+0,0,0,0,0,48,237,16,0,117,254,0,0,0,0,0,0,0,0,0,0,0,101,117,185,254,101,0,0,0,0,0,
+0,0,0,0,0,254,221,68,0,117,254,117,0,0,0,0,0,0,0,0,0,0,0,0,68,254,32,0,0,0,0,0,
+0,0,0,0,0,0,101,237,254,237,85,0,0,0,0,0,0,0,0,0,0,152,237,48,0,16,221,254,0,0,0,0,
+0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,
+0,0,0,0,0,0,0,32,152,237,117,16,0,0,0,0,0,0,0,0,0,117,117,117,117,117,117,117,101,0,0,0,
+0,0,0,0,0,0,68,185,221,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,254,85,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,152,237,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,237,136,0,0,0,0,
+0,0,0,0,0,205,85,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,48,0,0,0,0,
+0,0,0,0,0,254,152,0,0,0,169,221,0,0,0,0,0,0,0,0,0,0,0,0,185,152,0,0,0,0,0,0,
+0,0,0,0,0,85,237,48,32,205,254,101,0,0,0,0,0,0,0,0,0,16,185,254,185,221,117,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,32,152,237,117,16,0,0,0,0,0,0,0,0,0,0,0,117,117,117,117,117,117,117,101,0,0,0,
+0,0,0,0,0,0,0,0,68,185,221,101,0,0,0,0,0,0,0,0,0,0,0,0,205,152,0,0,0,0,0,0,
+0,0,0,0,0,205,136,0,0,0,101,254,16,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,117,237,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,237,0,0,0,0,
+0,0,0,0,0,254,254,254,254,254,254,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,
+0,0,0,0,0,221,117,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,68,254,32,0,0,0,0,0,0,
+0,0,0,0,0,221,152,0,0,0,221,237,0,0,0,0,0,0,0,0,0,0,0,48,68,0,117,185,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,101,221,185,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,16,117,237,152,32,0,0,0,0,0,0,0,0,0,0,0,185,101,0,0,0,0,0,0,
+0,0,0,0,0,136,205,0,0,0,136,205,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,254,117,0,0,0,0,
+0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,0,0,0,0,0,0,0,185,152,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,117,0,0,0,0,
+0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,
+0,0,0,0,0,0,0,101,221,185,68,0,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,254,185,0,0,0,
+0,0,0,0,0,0,16,117,237,152,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,32,254,68,0,16,237,101,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,221,221,68,68,68,68,16,0,0,0,0,0,0,0,0,0,32,0,0,16,237,152,0,0,0,0,
+0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,16,0,0,152,254,32,0,0,0,0,
+0,0,0,0,0,68,237,48,0,16,237,117,0,0,0,0,0,0,0,0,0,0,48,254,85,0,0,0,0,0,0,0,
+0,0,0,0,0,169,221,16,0,16,205,152,0,0,0,0,0,0,0,0,0,32,0,0,0,101,221,16,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,101,221,185,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,117,237,152,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,117,68,0,0,0,0,0,0,
+0,0,0,0,0,0,101,237,185,237,136,0,0,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,254,117,0,0,
+0,0,0,0,0,0,254,254,254,254,254,254,68,0,0,0,0,0,0,0,0,0,254,205,185,254,185,16,0,0,0,0,
+0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,254,185,205,237,85,0,0,0,0,0,
+0,0,0,0,0,0,117,254,185,237,152,0,0,0,0,0,0,0,0,0,0,0,117,254,16,0,0,0,0,0,0,0,
+0,0,0,0,0,16,205,237,185,237,185,16,0,0,0,0,0,0,0,0,0,117,237,185,221,185,48,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,101,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,152,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,68,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,68,32,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,68,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,68,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,48,68,32,0,0,0,0,0,0,0,0,0,0,0,0,32,68,48,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,254,32,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,136,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,221,254,221,85,0,0,0,0,0,0,0,0,0,0,0,85,185,85,0,0,0,0,0,0,
+0,0,0,0,0,0,185,185,185,185,169,68,0,0,0,0,0,0,0,0,0,0,0,101,185,254,254,221,136,0,0,0,
+0,0,0,0,0,0,185,185,185,185,117,32,0,0,0,0,0,0,0,0,0,0,185,185,185,185,185,185,101,0,0,0,
+0,0,0,0,0,0,185,185,185,185,185,185,136,0,0,0,0,0,0,0,0,0,0,101,185,254,254,221,136,0,0,0,
+0,0,0,0,0,0,185,101,0,0,0,185,101,0,0,0,0,0,0,0,0,0,185,185,185,185,185,185,101,0,0,0,
+0,0,0,0,0,0,48,185,185,185,185,48,0,0,0,0,0,0,0,0,0,0,185,101,0,0,16,169,101,0,0,0,
+0,0,0,0,0,0,185,101,0,0,0,0,0,0,0,0,0,0,0,0,0,185,169,0,0,0,32,185,136,0,0,0,
+0,0,0,0,0,0,185,117,0,0,0,101,136,0,0,0,0,0,0,0,0,0,16,169,254,254,169,16,0,0,0,0,
+0,0,0,0,0,0,152,205,32,0,68,237,0,0,0,0,0,0,0,0,0,0,0,169,254,169,0,0,0,0,0,0,
+0,0,0,0,0,0,254,152,68,85,205,254,32,0,0,0,0,0,0,0,0,0,152,237,101,0,0,68,117,0,0,0,
+0,0,0,0,0,0,254,152,68,101,185,237,48,0,0,0,0,0,0,0,0,0,254,152,68,68,68,68,32,0,0,0,
+0,0,0,0,0,0,254,152,68,68,68,68,48,0,0,0,0,0,0,0,0,0,152,237,101,0,0,48,101,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,68,68,152,254,68,68,32,0,0,0,
+0,0,0,0,0,0,16,68,68,117,254,68,0,0,0,0,0,0,0,0,0,0,254,117,0,0,152,205,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,48,0,0,117,254,185,0,0,0,
+0,0,0,0,0,0,254,254,32,0,0,117,185,0,0,0,0,0,0,0,0,16,205,152,16,16,152,205,16,0,0,0,
+0,0,0,0,0,68,221,16,0,117,185,221,68,0,0,0,0,0,0,0,0,0,16,254,205,254,16,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,254,117,0,0,0,0,0,0,0,0,68,254,85,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,221,169,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,85,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,0,85,237,48,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,205,136,0,0,205,205,185,0,0,0,
+0,0,0,0,0,0,254,254,152,0,0,117,185,0,0,0,0,0,0,0,0,117,237,16,0,0,16,237,117,0,0,0,
+0,0,0,0,0,152,117,0,136,117,0,205,68,0,0,0,0,0,0,0,0,0,101,237,48,254,101,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,32,254,101,0,0,0,0,0,0,0,0,169,221,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,117,254,16,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,169,221,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,32,237,117,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,221,0,32,237,117,185,0,0,0,
+0,0,0,0,0,0,254,221,254,32,0,117,185,0,0,0,0,0,0,0,0,185,169,0,0,0,0,169,185,0,0,0,
+0,0,0,0,0,221,32,16,221,0,0,205,68,0,0,0,0,0,0,0,0,0,169,136,0,221,169,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,48,205,185,0,0,0,0,0,0,0,0,0,237,152,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,254,152,68,68,68,48,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,237,152,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,185,169,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,16,254,68,117,169,117,185,0,0,0,
+0,0,0,0,0,0,254,101,237,152,0,117,185,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,254,0,68,185,0,32,254,68,0,0,0,0,0,0,0,0,32,254,48,0,117,254,32,0,0,0,0,
+0,0,0,0,0,0,254,254,254,254,205,16,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,254,221,185,185,185,136,0,0,0,0,
+0,0,0,0,0,0,254,221,185,185,185,185,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,254,254,254,254,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,221,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,169,152,221,101,117,185,0,0,0,
+0,0,0,0,0,0,254,68,117,254,68,117,185,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,254,0,68,205,0,152,221,68,0,0,0,0,0,0,0,0,117,221,0,0,32,254,117,0,0,0,0,
+0,0,0,0,0,0,254,117,0,48,185,237,32,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,152,68,68,68,68,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,136,136,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,185,237,48,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,101,237,254,16,117,185,0,0,0,
+0,0,0,0,0,0,254,68,16,237,185,117,185,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,205,68,0,237,152,152,185,152,32,0,0,0,0,0,0,0,205,254,254,254,254,254,205,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,237,152,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,185,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,16,237,205,16,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,16,237,169,0,117,185,0,0,0,
+0,0,0,0,0,0,254,68,0,117,254,185,185,0,0,0,0,0,0,0,0,205,152,0,0,0,0,152,205,0,0,0,
+0,0,0,0,0,117,169,0,48,117,16,101,117,32,0,0,0,0,0,0,32,254,48,0,0,0,117,254,32,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,185,0,0,0,0,0,0,0,0,117,254,48,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,221,169,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,101,254,48,0,0,0,185,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,48,0,0,0,0,0,0,0,0,0,0,254,117,0,68,254,152,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,0,0,0,0,117,185,0,0,0,
+0,0,0,0,0,0,254,68,0,16,237,254,185,0,0,0,0,0,0,0,0,136,221,0,0,0,0,221,136,0,0,0,
+0,0,0,0,0,16,205,152,16,0,85,32,0,0,0,0,0,0,0,0,117,221,0,0,0,0,32,254,117,0,0,0,
+0,0,0,0,0,0,254,117,0,0,68,254,117,0,0,0,0,0,0,0,0,0,205,237,68,0,0,0,32,0,0,0,
+0,0,0,0,0,0,254,117,0,32,169,237,32,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,205,237,68,0,0,185,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,16,0,0,117,237,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,117,254,101,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,0,0,0,0,0,117,185,0,0,0,
+0,0,0,0,0,0,254,68,0,0,117,254,185,0,0,0,0,0,0,0,0,32,237,117,0,0,117,237,32,0,0,0,
+0,0,0,0,0,0,16,152,254,254,169,32,0,0,0,0,0,0,0,0,205,117,0,0,0,0,0,185,205,0,0,0,
+0,0,0,0,0,0,254,254,254,254,237,117,0,0,0,0,0,0,0,0,0,0,16,152,254,221,185,221,169,0,0,0,
+0,0,0,0,0,0,254,254,254,237,152,32,0,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,152,254,205,185,237,152,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,117,0,0,0,
+0,0,0,0,0,0,254,205,205,237,85,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,237,48,0,0,
+0,0,0,0,0,0,254,254,254,254,254,254,117,0,0,0,0,0,0,0,0,254,0,0,0,0,0,117,185,0,0,0,
+0,0,0,0,0,0,254,68,0,0,0,221,185,0,0,0,0,0,0,0,0,0,48,237,205,205,237,48,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,68,32,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,68,32,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,68,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,117,117,101,0,0,0,
+0,0,0,0,0,117,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,117,117,101,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,185,185,185,185,169,101,0,0,0,0,0,0,0,0,0,0,16,169,254,254,169,16,0,0,0,0,
+0,0,0,0,0,0,185,185,185,185,152,48,0,0,0,0,0,0,0,0,0,0,16,152,254,254,237,169,0,0,0,0,
+0,0,0,0,185,185,185,185,185,185,185,185,101,0,0,0,0,0,0,0,0,0,185,101,0,0,0,136,101,0,0,0,
+0,0,0,0,152,117,0,0,0,0,0,85,152,0,0,0,0,0,0,0,185,48,0,0,0,0,0,48,136,0,0,0,
+0,0,0,0,85,185,68,0,0,0,48,185,32,0,0,0,0,0,0,0,117,185,16,0,0,0,0,136,117,0,0,0,
+0,0,0,0,0,136,185,185,185,185,185,185,101,0,0,0,0,0,0,0,0,0,0,0,254,185,117,117,101,0,0,0,
+0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,117,221,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,152,68,68,117,254,136,0,0,0,0,0,0,0,0,16,205,152,16,16,152,205,16,0,0,0,
+0,0,0,0,0,0,254,152,68,85,169,237,32,0,0,0,0,0,0,0,0,0,152,169,16,0,48,117,0,0,0,0,
+0,0,0,0,68,68,68,152,254,68,68,68,32,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,136,254,16,0,0,0,0,169,136,0,0,0,0,0,0,0,205,117,0,0,0,0,0,117,136,0,0,0,
+0,0,0,0,0,221,205,0,0,0,205,169,0,0,0,0,0,0,0,0,32,254,117,0,0,0,68,254,32,0,0,0,
+0,0,0,0,0,48,68,68,68,68,152,254,85,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,136,254,0,0,0,0,0,0,0,0,117,237,16,0,0,16,237,117,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,254,117,0,0,0,0,0,0,0,0,0,254,68,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,48,254,101,0,0,0,32,254,48,0,0,0,0,0,0,0,185,136,0,0,0,0,0,117,117,0,0,0,
+0,0,0,0,0,68,254,117,0,117,237,16,0,0,0,0,0,0,0,0,0,136,254,32,0,0,205,136,0,0,0,0,
+0,0,0,0,0,0,0,0,0,32,237,169,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,185,237,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,136,254,0,0,0,0,0,0,0,0,185,169,0,0,0,0,169,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,254,117,0,0,0,0,0,0,0,0,0,237,169,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,0,221,169,0,0,0,117,221,0,0,0,0,0,0,0,0,117,185,0,68,185,48,0,185,68,0,0,0,
+0,0,0,0,0,0,169,237,48,237,85,0,0,0,0,0,0,0,0,0,0,16,237,185,0,117,237,16,0,0,0,0,
+0,0,0,0,0,0,0,0,0,185,237,16,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,68,221,152,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,16,221,169,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,117,0,0,152,237,16,0,0,0,0,0,0,0,0,0,101,254,205,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,0,136,254,16,0,0,205,136,0,0,0,0,0,0,0,0,117,205,0,117,254,117,0,205,48,0,0,0,
+0,0,0,0,0,0,32,237,254,185,0,0,0,0,0,0,0,0,0,0,0,0,101,254,85,237,101,0,0,0,0,0,
+0,0,0,0,0,0,0,0,117,254,85,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,152,101,32,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,185,117,136,221,205,16,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,221,185,237,185,32,0,0,0,0,0,0,0,0,0,0,0,68,221,254,185,48,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,0,48,254,101,0,32,254,48,0,0,0,0,0,0,0,0,68,254,0,185,205,152,0,254,0,0,0,0,
+0,0,0,0,0,0,0,136,254,85,0,0,0,0,0,0,0,0,0,0,0,0,0,205,254,205,0,0,0,0,0,0,
+0,0,0,0,0,0,0,32,237,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,32,221,0,0,152,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,185,117,117,48,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,152,68,237,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,237,237,68,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,0,0,205,185,0,117,205,0,0,0,0,0,0,0,0,0,32,254,32,221,117,205,32,221,0,0,0,0,
+0,0,0,0,0,0,16,237,237,221,0,0,0,0,0,0,0,0,0,0,0,0,0,85,254,85,0,0,0,0,0,0,
+0,0,0,0,0,0,0,169,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,152,101,0,0,32,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,205,152,0,0,0,0,152,205,0,0,0,
+0,0,0,0,0,0,254,117,0,85,254,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,237,169,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,
+0,0,0,0,0,0,117,254,32,221,117,0,0,0,0,0,0,0,0,0,0,254,85,237,48,254,68,185,0,0,0,0,
+0,0,0,0,0,0,169,205,68,254,117,0,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,85,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,32,221,0,0,0,0,152,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,136,221,0,0,0,0,221,136,0,0,0,
+0,0,0,0,0,0,254,117,0,0,185,237,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,237,117,0,0,0,205,117,0,0,0,
+0,0,0,0,0,0,32,254,152,254,32,0,0,0,0,0,0,0,0,0,0,205,169,185,0,254,169,136,0,0,0,0,
+0,0,0,0,0,68,254,48,0,152,237,32,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,
+0,0,0,0,0,16,237,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,152,117,0,0,0,0,68,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,32,237,117,0,0,117,237,32,0,0,0,
+0,0,0,0,0,0,254,117,0,0,32,237,169,0,0,0,0,0,0,0,0,0,101,16,0,0,48,254,101,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,152,221,16,0,48,254,32,0,0,0,
+0,0,0,0,0,0,0,205,254,205,0,0,0,0,0,0,0,0,0,0,0,185,254,117,0,185,237,117,0,0,0,0,
+0,0,0,0,16,221,117,0,0,16,237,185,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,
+0,0,0,0,0,169,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,237,205,205,237,85,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,117,254,85,0,0,0,0,0,0,0,0,221,254,185,185,254,136,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,0,16,205,237,185,254,101,0,0,0,0,
+0,0,0,0,0,0,0,117,254,117,0,0,0,0,0,0,0,0,0,0,0,117,254,85,0,136,254,68,0,0,0,0,
+0,0,0,0,136,221,16,0,0,0,101,254,85,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,
+0,0,0,0,0,254,254,254,254,254,254,254,117,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,85,237,152,48,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,68,68,16,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,68,16,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,16,237,32,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,254,254,254,254,254,254,254,254,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,185,254,101,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,221,185,185,136,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,117,152,0,0,0,0,0,0,0,0,185,185,185,237,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,68,68,48,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,16,68,0,0,0,0,0,0,0,0,68,68,68,68,48,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,136,169,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,117,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,101,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,32,117,117,117,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,117,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,185,48,0,0,0,0,0,
+0,0,0,0,0,0,0,0,101,185,48,0,0,0,0,0,0,0,0,0,0,0,117,68,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,117,117,117,117,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,205,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,85,254,185,117,117,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,117,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,117,117,117,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,32,117,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,169,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,169,237,254,237,117,0,0,0,0,0,
+0,0,0,0,0,254,117,85,221,254,185,16,0,0,0,0,0,0,0,0,0,0,0,85,205,254,254,221,101,0,0,0,
+0,0,0,0,0,0,117,237,254,136,185,185,0,0,0,0,0,0,0,0,0,0,68,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,254,254,254,254,254,254,254,117,0,0,0,0,0,0,0,0,0,101,237,254,152,136,185,0,0,0,0,
+0,0,0,0,0,0,254,117,85,221,254,136,0,0,0,0,0,0,0,0,0,0,254,254,254,254,68,0,0,0,0,0,
+0,0,0,0,0,117,254,254,254,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,117,237,48,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,185,237,32,152,254,85,0,0,0,
+0,0,0,0,0,0,254,117,85,221,254,136,0,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,101,16,0,136,254,32,0,0,0,0,
+0,0,0,0,0,254,185,185,85,101,237,185,0,0,0,0,0,0,0,0,0,0,68,254,152,16,0,48,48,0,0,0,
+0,0,0,0,0,85,254,101,0,117,254,185,0,0,0,0,0,0,0,0,0,48,254,117,0,48,237,152,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,85,254,68,0,117,254,185,0,0,0,0,
+0,0,0,0,0,0,254,185,185,68,136,254,101,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,0,101,237,48,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,185,101,221,185,152,169,185,0,0,0,
+0,0,0,0,0,0,254,185,185,68,136,254,101,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,254,169,0,0,0,117,254,32,0,0,0,0,0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,
+0,0,0,0,0,185,169,0,0,0,185,185,0,0,0,0,0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,169,169,0,0,0,185,185,0,0,0,0,
+0,0,0,0,0,0,254,185,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,85,254,101,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,117,0,185,185,0,117,185,0,0,0,
+0,0,0,0,0,0,254,185,0,0,0,254,117,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,152,185,205,254,68,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,185,185,0,0,0,0,0,0,0,0,0,254,221,185,185,185,221,254,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,185,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,169,237,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,0,185,117,0,117,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,237,85,0,68,254,68,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,185,185,0,0,0,0,0,0,0,0,0,254,152,68,68,68,68,68,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,185,185,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,136,205,237,48,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,0,185,117,0,117,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,117,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,117,237,0,0,0,0,0,0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,
+0,0,0,0,0,221,169,0,0,16,221,185,0,0,0,0,0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,221,169,0,0,16,221,185,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,16,205,237,16,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,0,185,117,0,117,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,221,185,16,32,169,254,85,0,0,0,0,
+0,0,0,0,0,254,237,85,0,68,237,117,0,0,0,0,0,0,0,0,0,0,68,254,152,32,0,32,68,0,0,0,
+0,0,0,0,0,117,254,117,85,185,205,185,0,0,0,0,0,0,0,0,0,85,254,152,32,0,32,101,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,117,254,117,85,205,185,185,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,0,32,237,205,16,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,0,185,117,0,117,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,221,254,205,85,169,254,117,0,0,0,
+0,0,0,0,0,254,117,169,254,237,117,0,0,0,0,0,0,0,0,0,0,0,0,68,185,254,254,221,136,0,0,0,
+0,0,0,0,0,16,152,254,221,48,185,185,0,0,0,0,0,0,0,0,0,0,85,185,254,254,237,169,0,0,0,0,
+0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,0,0,0,0,0,136,254,237,101,185,185,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,48,237,205,16,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,254,68,0,185,117,0,117,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,221,136,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,0,0,117,254,68,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,85,0,0,169,237,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,185,254,254,205,85,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,185,254,254,205,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,117,117,0,0,0,0,
+0,0,0,0,0,0,0,0,117,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,85,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,221,117,117,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,117,117,221,136,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,185,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,101,237,254,136,0,0,0,0,0,0,0,0,0,0,85,221,254,185,101,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,85,221,254,169,0,0,0,0,0,0,0,0,0,16,152,237,254,254,205,48,0,0,0,
+0,0,0,0,0,254,254,254,254,254,254,185,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,205,205,0,0,0,0,136,205,0,0,0,0,0,0,0,237,85,0,0,68,32,0,32,237,0,0,0,
+0,0,0,0,0,152,254,48,0,0,85,254,48,0,0,0,0,0,0,0,0,152,221,0,0,0,0,117,221,0,0,0,
+0,0,0,0,0,185,254,254,254,254,254,254,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,185,185,85,117,254,117,0,0,0,0,0,0,0,0,85,254,117,0,68,237,254,0,0,0,0,
+0,0,0,0,0,0,0,254,185,205,101,117,185,0,0,0,0,0,0,0,0,0,152,221,32,0,0,68,32,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,101,254,48,0,0,0,237,101,0,0,0,0,0,0,0,185,117,0,48,254,136,0,68,185,0,0,0,
+0,0,0,0,0,16,205,221,16,16,237,117,0,0,0,0,0,0,0,0,0,68,254,101,0,0,0,221,117,0,0,0,
+0,0,0,0,0,0,0,0,0,48,237,152,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,169,0,0,0,169,221,0,0,0,0,0,0,0,0,185,169,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,254,205,16,0,32,101,0,0,0,0,0,0,0,0,0,185,221,32,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,16,237,152,0,0,101,237,16,0,0,0,0,0,0,0,117,169,0,117,185,205,0,117,117,0,0,0,
+0,0,0,0,0,0,48,237,169,185,185,0,0,0,0,0,0,0,0,0,0,0,221,185,0,0,85,237,16,0,0,0,
+0,0,0,0,0,0,0,0,16,205,152,0,0,0,0,0,0,0,0,0,0,0,0,85,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,85,0,0,0,0,0,
+0,0,0,0,0,0,48,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,68,237,254,205,117,16,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,152,237,16,0,185,152,0,0,0,0,0,0,0,0,85,205,0,185,48,254,16,169,85,0,0,0,
+0,0,0,0,0,0,0,101,254,237,32,0,0,0,0,0,0,0,0,0,0,0,101,254,32,0,185,152,0,0,0,0,
+0,0,0,0,0,0,0,16,205,185,0,0,0,0,0,0,0,0,0,0,0,0,254,254,117,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,254,0,0,0,0,
+0,0,0,0,0,117,221,221,185,32,0,48,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,0,0,0,0,254,117,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,117,205,254,237,32,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,32,254,117,32,254,32,0,0,0,0,0,0,0,0,48,254,16,237,0,205,85,205,48,0,0,0,
+0,0,0,0,0,0,0,117,254,237,48,0,0,0,0,0,0,0,0,0,0,0,16,237,136,48,254,32,0,0,0,0,
+0,0,0,0,0,0,0,185,205,16,0,0,0,0,0,0,0,0,0,0,0,0,0,85,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,85,0,0,0,0,0,
+0,0,0,0,0,237,16,0,117,237,136,205,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,169,185,0,0,0,0,0,0,0,0,221,169,0,0,0,169,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,254,117,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,68,254,117,0,0,0,
+0,0,0,0,0,0,0,185,221,136,185,0,0,0,0,0,0,0,0,0,0,254,117,169,0,136,136,254,0,0,0,0,
+0,0,0,0,0,0,48,254,101,221,205,16,0,0,0,0,0,0,0,0,0,0,0,152,237,169,169,0,0,0,0,0,
+0,0,0,0,0,0,152,205,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,32,117,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,237,68,0,117,254,85,0,0,0,0,0,0,0,0,117,254,117,85,185,185,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,117,48,0,0,117,254,68,0,0,0,
+0,0,0,0,0,0,0,221,205,32,0,0,0,0,0,0,0,0,0,0,0,0,221,221,85,117,169,254,117,0,0,0,
+0,0,0,0,0,0,0,101,254,237,101,0,0,0,0,0,0,0,0,0,0,185,237,101,0,85,254,185,0,0,0,0,
+0,0,0,0,0,16,221,136,0,48,254,152,0,0,0,0,0,0,0,0,0,0,0,48,254,254,68,0,0,0,0,0,
+0,0,0,0,0,152,237,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,136,169,254,221,101,0,0,0,0,0,0,0,0,0,0,136,254,221,101,117,254,0,0,0,0,
+0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,169,221,254,254,205,85,0,0,0,0,
+0,0,0,0,0,0,0,48,205,254,254,254,0,0,0,0,0,0,0,0,0,0,48,221,254,152,16,254,117,0,0,0,
+0,0,0,0,0,0,0,0,237,237,0,0,0,0,0,0,0,0,0,0,0,136,254,32,0,32,254,136,0,0,0,0,
+0,0,0,0,0,152,205,0,0,0,117,254,101,0,0,0,0,0,0,0,0,0,0,0,205,221,0,0,0,0,0,0,
+0,0,0,0,0,254,254,254,254,254,254,254,0,0,0,0,0,0,0,0,0,0,0,0,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,101,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,85,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,237,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,152,221,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,254,185,185,0,0,0,0,
+0,0,0,0,0,0,0,0,254,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,254,101,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,205,48,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,68,0,0,0,0,
+0,0,0,0,0,0,0,0,68,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,16,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,185,117,0,185,117,0,0,0,0,0,0,0,0,0,0,0,0,68,117,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,85,185,48,0,0,0,0,0,0,0,0,0,0,0,0,48,117,85,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,136,169,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,48,136,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,48,117,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,101,185,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,85,117,48,0,0,0,0,0,0,0,0,0,0,0,0,136,169,0,0,0,0,0,0,0,
+0,0,0,0,0,0,48,32,0,48,32,0,0,0,0,0,0,0,0,0,0,0,0,117,0,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,101,185,254,254,221,136,0,0,0,0,0,0,0,0,0,0,185,48,0,185,48,0,0,0,0,
+0,0,0,0,0,0,0,16,237,101,0,0,0,0,0,0,0,0,0,0,0,0,32,237,117,237,85,0,0,0,0,0,
+0,0,0,0,0,0,101,136,0,101,136,0,0,0,0,0,0,0,0,0,0,0,0,16,205,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,16,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,32,237,117,237,85,0,0,0,0,0,0,0,0,0,0,0,48,185,0,48,185,0,0,0,0,0,
+0,0,0,0,0,0,0,0,152,185,0,0,0,0,0,0,0,0,0,0,0,0,0,136,101,0,136,101,0,0,0,0,
+0,0,0,0,0,0,0,85,237,117,237,32,0,0,0,0,0,0,0,0,0,0,0,16,205,117,0,0,0,0,0,0,
+0,0,0,0,0,0,0,85,185,85,0,0,0,0,0,0,0,0,0,0,0,0,0,117,254,117,0,0,0,0,0,0,
+0,0,0,0,0,0,152,237,101,0,0,68,117,0,0,0,0,0,0,0,0,0,0,117,32,0,117,32,0,0,0,0,
+0,0,0,0,0,0,0,85,101,0,0,0,0,0,0,0,0,0,0,0,0,0,85,85,0,48,117,0,0,0,0,0,
+0,0,0,0,0,0,68,101,0,68,101,0,0,0,0,0,0,0,0,0,0,0,0,0,32,117,16,0,0,0,0,0,
+0,0,0,0,0,0,0,16,117,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,85,85,0,48,117,0,0,0,0,0,0,0,0,0,0,0,32,117,0,32,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,117,48,0,0,0,0,0,0,0,0,0,0,0,0,101,68,0,101,68,0,0,0,0,
+0,0,0,0,0,0,0,117,48,0,85,85,0,0,0,0,0,0,0,0,0,0,0,0,32,117,16,0,0,0,0,0,
+0,0,0,0,0,0,0,169,254,169,0,0,0,0,0,0,0,0,0,0,0,0,0,169,254,169,0,0,0,0,0,0,
+0,0,0,0,0,68,254,85,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,16,254,205,254,16,0,0,0,0,0,0,0,0,0,0,0,16,254,205,254,16,0,0,0,0,0,
+0,0,0,0,0,169,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,68,205,254,237,152,16,0,0,0,0,0,0,0,0,0,32,169,237,254,237,117,0,0,0,0,0,
+0,0,0,0,0,32,169,237,254,237,117,0,0,0,0,0,0,0,0,0,0,32,169,237,254,237,117,0,0,0,0,0,
+0,0,0,0,0,32,169,237,254,237,117,0,0,0,0,0,0,0,0,0,0,0,0,85,205,254,254,221,101,0,0,0,
+0,0,0,0,0,0,68,205,254,237,152,16,0,0,0,0,0,0,0,0,0,0,68,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,68,205,254,237,152,16,0,0,0,0,0,0,0,0,0,0,254,254,254,254,117,0,0,0,0,0,
+0,0,0,0,0,0,254,254,254,254,117,0,0,0,0,0,0,0,0,0,0,0,254,254,254,254,117,0,0,0,0,0,
+0,0,0,0,0,0,101,237,48,254,101,0,0,0,0,0,0,0,0,0,0,0,101,237,48,254,101,0,0,0,0,0,
+0,0,0,0,0,221,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,48,254,117,0,48,237,152,0,0,0,0,0,0,0,0,0,48,101,16,0,136,254,32,0,0,0,0,
+0,0,0,0,0,48,101,16,0,136,254,32,0,0,0,0,0,0,0,0,0,48,101,16,0,136,254,32,0,0,0,0,
+0,0,0,0,0,48,101,16,0,136,254,32,0,0,0,0,0,0,0,0,0,0,68,254,152,16,0,48,48,0,0,0,
+0,0,0,0,0,48,254,117,0,48,237,152,0,0,0,0,0,0,0,0,0,48,254,117,0,48,237,152,0,0,0,0,
+0,0,0,0,0,48,254,117,0,48,237,152,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,169,136,0,221,169,0,0,0,0,0,0,0,0,0,0,0,169,136,0,221,169,0,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,0,0,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,185,205,0,0,0,0,0,0,0,0,
+0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,
+0,0,0,0,0,169,152,0,0,0,136,221,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,32,254,48,0,117,254,32,0,0,0,0,0,0,0,0,0,32,254,48,0,117,254,32,0,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,254,221,185,185,185,221,254,0,0,0,0,0,0,0,0,0,0,68,152,185,205,254,68,0,0,0,0,
+0,0,0,0,0,0,68,152,185,205,254,68,0,0,0,0,0,0,0,0,0,0,68,152,185,205,254,68,0,0,0,0,
+0,0,0,0,0,0,68,152,185,205,254,68,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,221,185,185,185,221,254,0,0,0,0,0,0,0,0,0,254,221,185,185,185,221,254,0,0,0,0,
+0,0,0,0,0,254,221,185,185,185,221,254,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,117,221,0,0,32,254,117,0,0,0,0,0,0,0,0,0,117,221,0,0,32,254,117,0,0,0,0,
+0,0,0,0,0,205,185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,254,152,68,68,68,68,68,0,0,0,0,0,0,0,0,0,117,237,85,0,68,254,68,0,0,0,0,
+0,0,0,0,0,117,237,85,0,68,254,68,0,0,0,0,0,0,0,0,0,117,237,85,0,68,254,68,0,0,0,0,
+0,0,0,0,0,117,237,85,0,68,254,68,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,254,152,68,68,68,68,68,0,0,0,0,0,0,0,0,0,254,152,68,68,68,68,68,0,0,0,0,
+0,0,0,0,0,254,152,68,68,68,68,68,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,205,254,254,254,254,254,205,0,0,0,0,0,0,0,0,0,205,254,254,254,254,254,205,0,0,0,0,
+0,0,0,0,0,117,254,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,68,254,117,0,0,0,
+0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,237,117,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,237,117,0,0,68,254,68,0,0,0,0,0,0,0,0,0,237,117,0,0,68,254,68,0,0,0,0,
+0,0,0,0,0,237,117,0,0,68,254,68,0,0,0,0,0,0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,
+0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,205,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,32,254,48,0,0,0,117,254,32,0,0,0,0,0,0,0,32,254,48,0,0,0,117,254,32,0,0,0,
+0,0,0,0,0,16,205,237,68,0,0,0,32,0,0,0,0,0,0,0,0,0,221,221,85,117,169,254,117,0,0,0,
+0,0,0,0,0,85,254,152,32,0,32,101,0,0,0,0,0,0,0,0,0,221,185,16,32,169,254,85,0,0,0,0,
+0,0,0,0,0,221,185,16,32,169,254,85,0,0,0,0,0,0,0,0,0,221,185,16,32,169,254,85,0,0,0,0,
+0,0,0,0,0,221,185,16,32,169,254,85,0,0,0,0,0,0,0,0,0,0,85,254,152,32,0,32,68,0,0,0,
+0,0,0,0,0,85,254,152,32,0,32,101,0,0,0,0,0,0,0,0,0,85,254,152,32,0,32,101,0,0,0,0,
+0,0,0,0,0,85,254,152,32,0,32,101,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,117,221,0,0,0,0,32,254,117,0,0,0,0,0,0,0,117,221,0,0,0,0,32,254,117,0,0,0,
+0,0,0,0,0,0,32,185,254,205,185,221,169,0,0,0,0,0,0,0,0,0,48,221,254,152,16,254,117,0,0,0,
+0,0,0,0,0,0,85,185,254,254,237,169,0,0,0,0,0,0,0,0,0,48,221,254,205,85,169,254,117,0,0,0,
+0,0,0,0,0,48,221,254,205,85,169,254,117,0,0,0,0,0,0,0,0,48,221,254,205,85,169,254,117,0,0,0,
+0,0,0,0,0,48,221,254,205,85,169,254,117,0,0,0,0,0,0,0,0,0,0,85,205,254,254,221,117,0,0,0,
+0,0,0,0,0,0,85,185,254,254,237,169,0,0,0,0,0,0,0,0,0,0,85,185,254,254,237,169,0,0,0,0,
+0,0,0,0,0,0,85,185,254,254,237,169,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,
+0,0,0,0,205,117,0,0,0,0,0,185,205,0,0,0,0,0,0,0,205,117,0,0,0,0,0,185,205,0,0,0,
+0,0,0,0,0,0,0,0,68,185,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,205,16,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,32,136,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,48,237,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,143,251,198,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85,185,117,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,169,152,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,0,68,254,0,0,0,0,0,
+0,0,0,0,0,0,0,254,68,0,254,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,16,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,117,85,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,101,185,32,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,85,117,48,0,0,0,0,0,0,0,0,0,0,0,0,101,185,32,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,68,0,16,68,0,0,0,0,0,
+0,0,0,0,0,0,0,68,16,0,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,185,185,185,185,185,185,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,32,185,185,185,185,101,0,0,0,0,0,0,0,0,0,32,237,117,237,85,0,0,0,0,0,
+0,0,0,0,0,0,101,136,0,101,136,0,0,0,0,0,0,0,0,0,0,0,0,0,152,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,85,237,117,237,32,0,0,0,0,0,0,0,0,0,0,0,0,152,185,0,0,0,0,0,0,
+0,0,0,0,0,0,0,185,48,0,185,48,0,0,0,0,0,0,0,0,0,0,16,169,254,254,169,16,0,0,0,0,
+0,0,0,0,0,0,185,101,0,0,0,136,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,101,221,254,237,0,0,0,0,0,0,0,0,0,0,32,169,254,254,169,136,185,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,237,254,117,0,0,0,
+0,0,0,0,0,0,254,152,68,68,68,68,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,254,68,68,32,0,0,0,0,0,0,0,0,0,85,85,0,48,117,0,0,0,0,0,
+0,0,0,0,0,0,68,101,0,68,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,48,0,0,0,0,0,
+0,0,0,0,0,0,0,117,48,0,85,85,0,0,0,0,0,0,0,0,0,0,0,0,0,117,48,0,0,0,0,0,
+0,0,0,0,0,0,0,117,32,0,117,32,0,0,0,0,0,0,0,0,0,16,205,152,16,16,152,205,16,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,48,254,85,0,48,0,0,0,0,0,0,0,0,0,16,205,152,16,16,152,254,48,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,237,32,0,32,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,205,237,254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,117,237,16,0,0,16,237,117,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,117,237,16,0,0,185,254,117,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,221,136,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,68,254,254,237,136,237,254,136,0,0,0,
+0,0,0,0,0,0,48,254,152,254,0,0,0,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,152,221,0,0,0,0,117,221,0,0,0,0,0,0,0,0,185,169,0,0,0,0,169,185,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,0,85,205,254,254,169,221,48,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,185,169,0,0,85,221,205,185,0,0,0,
+0,0,0,0,0,85,16,0,0,0,0,48,48,0,0,0,0,0,0,0,0,0,0,48,254,68,0,0,0,0,0,0,
+0,0,0,0,0,0,254,152,68,68,68,48,0,0,0,0,0,0,0,0,0,16,32,0,169,254,117,48,254,48,0,0,
+0,0,0,0,0,0,136,205,117,254,68,68,16,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,68,254,101,0,0,0,221,117,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,85,254,117,0,48,254,205,0,0,0,0,
+0,0,0,0,0,0,48,152,254,68,32,0,0,0,0,0,0,0,0,0,0,254,117,0,16,221,85,117,254,0,0,0,
+0,0,0,0,0,101,205,16,0,0,101,221,48,0,0,0,0,0,0,0,0,0,48,152,254,85,16,0,0,0,0,0,
+0,0,0,0,0,0,254,221,185,185,185,136,0,0,0,0,0,0,0,0,0,0,0,48,152,254,68,68,254,117,0,0,
+0,0,0,0,0,0,221,101,117,254,185,185,48,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,221,185,0,0,85,237,16,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,205,205,0,0,169,185,254,85,0,0,0,
+0,0,0,0,0,0,136,221,254,185,101,0,0,0,0,0,0,0,0,0,0,254,117,0,136,185,0,117,254,0,0,0,
+0,0,0,0,0,0,101,205,16,101,237,48,0,0,0,0,0,0,0,0,0,0,136,237,237,185,48,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,48,205,221,221,254,254,254,254,117,0,0,
+0,0,0,0,0,85,254,16,117,254,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,101,254,32,0,185,152,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,117,254,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,254,117,0,117,185,0,254,117,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,254,117,48,254,32,0,117,254,0,0,0,
+0,0,0,0,0,0,0,101,221,237,48,0,0,0,0,0,0,0,0,0,0,0,0,205,169,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,117,254,0,0,0,0,0,0,
+0,0,0,0,0,152,237,185,221,254,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,0,0,0,0,0,254,117,0,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,0,254,117,0,0,0,
+0,0,0,0,0,0,16,237,136,48,254,32,0,0,0,0,0,0,0,0,0,205,152,0,0,0,0,152,205,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,185,117,0,0,0,0,0,0,0,0,254,117,68,237,16,0,254,117,0,0,0,
+0,0,0,0,0,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,0,205,169,185,117,0,0,152,205,0,0,0,
+0,0,0,0,0,0,0,48,221,205,16,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,117,254,16,0,0,0,0,0,
+0,0,0,0,0,237,117,68,152,254,0,0,0,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,0,0,0,0,0,205,185,0,0,0,68,254,85,0,0,0,
+0,0,0,0,0,0,254,117,0,0,68,254,117,0,0,0,0,0,0,0,0,0,254,117,0,0,68,254,117,0,0,0,
+0,0,0,0,0,0,0,152,237,169,169,0,0,0,0,0,0,0,0,0,0,136,221,0,0,0,0,221,136,0,0,0,
+0,0,0,0,0,0,237,117,0,0,0,205,117,0,0,0,0,0,0,0,0,205,205,237,48,0,85,254,85,0,0,0,
+0,0,0,0,0,0,0,152,169,0,0,0,0,0,0,0,0,0,0,0,0,136,254,221,16,0,0,221,136,0,0,0,
+0,0,0,0,0,0,48,221,48,101,205,16,0,0,0,0,0,0,0,0,0,0,68,254,85,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,0,0,0,0,0,221,221,68,205,254,152,0,48,68,0,0,
+0,0,0,0,101,237,0,0,117,254,0,0,0,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,0,0,0,0,0,85,254,117,0,32,205,205,0,0,0,0,
+0,0,0,0,0,0,221,221,85,117,169,254,117,0,0,0,0,0,0,0,0,0,221,221,85,117,169,254,117,0,0,0,
+0,0,0,0,0,0,0,48,254,254,68,0,0,0,0,0,0,0,0,0,0,32,237,117,0,0,117,237,32,0,0,0,
+0,0,0,0,0,0,152,221,16,0,48,254,32,0,0,0,0,0,0,0,0,101,254,169,0,32,205,205,0,0,0,0,
+0,0,0,0,0,0,117,237,85,68,68,68,0,0,0,0,0,0,0,0,0,48,254,152,0,0,117,237,32,0,0,0,
+0,0,0,0,0,48,221,48,0,0,101,205,16,0,0,0,0,0,0,0,0,0,117,254,32,0,0,0,0,0,0,0,
+0,0,0,0,0,0,254,254,254,254,254,254,185,0,0,0,0,0,0,0,0,48,221,237,136,136,237,254,205,85,0,0,
+0,0,0,0,169,152,0,0,117,254,254,254,185,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,0,0,0,0,0,0,85,205,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,48,221,254,152,16,254,117,0,0,0,0,0,0,0,0,0,48,221,254,152,16,254,117,0,0,0,
+0,0,0,0,0,0,0,0,205,221,0,0,0,0,0,0,0,0,0,0,0,0,48,237,205,205,237,48,0,0,0,0,
+0,0,0,0,0,0,16,205,237,185,254,101,0,0,0,0,0,0,0,0,0,152,185,221,254,237,152,16,0,0,0,0,
+0,0,0,0,0,0,254,254,254,254,254,254,0,0,0,0,0,0,0,0,0,136,205,237,221,205,237,48,0,0,0,0,
+0,0,0,0,0,117,48,0,0,0,0,101,85,0,0,0,0,0,0,0,0,0,136,237,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,237,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,48,68,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,16,0,68,68,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,185,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,152,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,117,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,117,254,205,48,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,32,0,0,0,0,0,0,0,0
+};
diff --git a/KaplaDemo/samples/sampleViewer3/GLFontRenderer.cpp b/KaplaDemo/samples/sampleViewer3/GLFontRenderer.cpp
new file mode 100644
index 00000000..ec205445
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/GLFontRenderer.cpp
@@ -0,0 +1,334 @@
+#ifndef PHYSX_NO_RENDERER
+
+#include "GLFontData.h"
+#include "GLFontRenderer.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <GL/gl.h>
+
+using namespace physx;
+
+bool GLFontRenderer::init()
+{
+ m_isInit=false;
+ m_textureObject=0;
+ m_screenWidth=640;
+ m_screenHeight=480;
+ m_color = 0xffffffff;
+
+ glGenTextures(1, &m_textureObject);
+ if(m_textureObject == 0)
+ return false;
+
+ glBindTexture(GL_TEXTURE_2D, m_textureObject);
+
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
+ // expand to rgba
+ unsigned char* pNewSource = new unsigned char[OGL_FONT_TEXTURE_WIDTH*OGL_FONT_TEXTURE_HEIGHT*4];
+ for(int i=0;i<OGL_FONT_TEXTURE_WIDTH*OGL_FONT_TEXTURE_HEIGHT;i++)
+ {
+ pNewSource[i*4+0]=255;
+ pNewSource[i*4+1]=255;
+ pNewSource[i*4+2]=255;
+ pNewSource[i*4+3]=OGLFontData[i];
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, OGL_FONT_TEXTURE_WIDTH, OGL_FONT_TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, pNewSource);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+// delete[] pNewSource;
+
+ m_isInit=true;
+ return true;
+}
+
+inline unsigned int safeStrlen( const char* pString )
+{
+ return ( pString && *pString) ? (unsigned int)strlen(pString) : 0;
+}
+
+template<typename TOperator>
+void GLFontRenderer::print( float fontSize, const char* pString, bool forceMonoSpace, int monoSpaceWidth, bool doOrthoProj, TOperator inOperator )
+{
+ if ( !m_isInit )
+ init();
+ unsigned int num = safeStrlen( pString );
+ if ( !m_isInit || !num )
+ return;
+
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, m_textureObject);
+
+ if(doOrthoProj)
+ {
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glOrtho(0, m_screenWidth, 0, m_screenHeight, -1, 1);
+ }
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glEnable(GL_BLEND);
+
+ glColor4f((m_color&0xff) / float(0xff), ((m_color>>8)&0xff) / float(0xff),
+ ((m_color>>16)&0xff) / float(0xff), ((m_color>>24)&0xff) / float(0xff));
+
+ mVertList.resize( PxMax( num * 6 * 3, mVertList.size() ) );
+ mTextureCoordList.resize( PxMax( num * 6 * 2, mTextureCoordList.size() ) );
+ PxF32* pVertList = reinterpret_cast<PxF32*>( mVertList.begin() );
+ PxF32* pTextureCoordList = reinterpret_cast<PxF32*>( mTextureCoordList.begin() );
+
+ int vertIndex = 0;
+ int textureCoordIndex = 0;
+
+ float translateDown = 0.0f;
+ float translate = 0.0f;
+ unsigned int count = 0;
+
+ const float glyphHeightUV = ((float)OGL_FONT_CHARS_PER_COL)/OGL_FONT_TEXTURE_HEIGHT*2-0.01f;
+ const float glyphWidthUV = ((float)OGL_FONT_CHARS_PER_ROW)/OGL_FONT_TEXTURE_WIDTH;
+
+ for(unsigned int i=0;i<num; i++)
+ {
+ if (pString[i] == '\n') {
+ translateDown-=0.005f*m_screenHeight+fontSize;
+ translate = 0.0f;
+ continue;
+ }
+
+ int c = pString[i]-OGL_FONT_CHAR_BASE;
+ if (c < OGL_FONT_CHARS_PER_ROW*OGL_FONT_CHARS_PER_COL) {
+
+ count++;
+
+ float glyphWidth = (float)GLFontGlyphWidth[c];
+ if(forceMonoSpace){
+ glyphWidth = (float)monoSpaceWidth;
+ }
+
+ glyphWidth = glyphWidth*(fontSize/(((float)OGL_FONT_TEXTURE_WIDTH)/OGL_FONT_CHARS_PER_ROW));
+
+ float cxUV = float((c)%OGL_FONT_CHARS_PER_ROW)/OGL_FONT_CHARS_PER_ROW+0.008f;
+ float cyUV = float((c)/OGL_FONT_CHARS_PER_ROW)/OGL_FONT_CHARS_PER_COL+0.008f;
+ inOperator( cxUV, cyUV, glyphWidthUV, glyphHeightUV
+ , pVertList, pTextureCoordList, vertIndex, textureCoordIndex
+ , translate, translateDown, glyphWidth );
+ vertIndex += 6*3;
+ textureCoordIndex += 6*2;
+
+ translate+=1.0f * glyphWidth;
+ }
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, 0, pVertList);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, pTextureCoordList);
+ glDrawArrays(GL_TRIANGLES, 0, count*6);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if(doOrthoProj)
+ {
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ }
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ glDisable(GL_TEXTURE_2D);
+ glDisable(GL_BLEND);
+}
+
+struct TextPrintRender
+{
+ float x;
+ float y;
+ float fontSize;
+ int screenHeight;
+
+ TextPrintRender( float _x, float _y, float _fontSize, int _screenWidth, int _screenHeight )
+ : x( _x*_screenWidth )
+ , y( _y*_screenHeight )
+ , fontSize( _fontSize * _screenHeight )
+ , screenHeight( _screenHeight )
+ {
+ }
+ void operator()( float cxUV, float cyUV, float glyphWidthUV, float glyphHeightUV
+ , float* pVertList, float* pTextureCoordList, int vertIndex, int textureCoordIndex
+ , float translate, float translateDown, float glyphWidth )
+ {
+ translate *= screenHeight; //move translate to pixel space
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ pVertList[vertIndex++] = x+0+translate;
+ pVertList[vertIndex++] = y+0+translateDown;
+ pVertList[vertIndex++] = 0;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ pVertList[vertIndex++] = x+fontSize+translate;
+ pVertList[vertIndex++] = y+fontSize+translateDown;
+ pVertList[vertIndex++] = 0;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ pVertList[vertIndex++] = x+0+translate;
+ pVertList[vertIndex++] = y+fontSize+translateDown;
+ pVertList[vertIndex++] = 0;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ pVertList[vertIndex++] = x+0+translate;
+ pVertList[vertIndex++] = y+0+translateDown;
+ pVertList[vertIndex++] = 0;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ pVertList[vertIndex++] = x+fontSize+translate;
+ pVertList[vertIndex++] = y+0+translateDown;
+ pVertList[vertIndex++] = 0;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ pVertList[vertIndex++] = x+fontSize+translate;
+ pVertList[vertIndex++] = y+fontSize+translateDown;
+ pVertList[vertIndex++] = 0;
+ }
+};
+
+
+void GLFontRenderer::print(float x, float y, float fontSize, const char* pString, bool forceMonoSpace, int monoSpaceWidth, bool doOrthoProj)
+{
+ print( fontSize, pString, forceMonoSpace, monoSpaceWidth, doOrthoProj, TextPrintRender( x, y, fontSize, m_screenWidth, m_screenHeight ) );
+}
+
+GLFontMeasureResult GLFontRenderer::measure( float fontSize, const char* pString, bool forceMonoSpace, int monoSpaceWidth )
+{
+ GLFontMeasureResult retval( 0, fontSize );
+ if ( !m_isInit )
+ init();
+ unsigned int num( safeStrlen( pString ) );
+
+ for(unsigned int i=0;i<num; i++)
+ {
+ int c = pString[i]-OGL_FONT_CHAR_BASE;
+ if (c < OGL_FONT_CHARS_PER_ROW*OGL_FONT_CHARS_PER_COL) {
+ float glyphWidth = (float)GLFontGlyphWidth[c];
+ if(forceMonoSpace){
+ glyphWidth = (float)monoSpaceWidth;
+ }
+
+ glyphWidth = glyphWidth*(fontSize/(((float)OGL_FONT_TEXTURE_WIDTH)/OGL_FONT_CHARS_PER_ROW));
+ retval.width += glyphWidth;
+ }
+ }
+ return retval;
+}
+
+struct TextPrint3DRender
+{
+ PxVec3 pos;
+ PxVec3 cameraDir;
+ PxVec3 up;
+ PxVec3 right;
+ float fontSize;
+ TextPrint3DRender( const PxVec3& _pos, const PxVec3& _cameraDir, const PxVec3& _up, float _fontSize )
+ : pos( _pos )
+ , cameraDir( _cameraDir )
+ , up( _up )
+ , fontSize( _fontSize )
+ {
+ }
+ void operator()( float cxUV, float cyUV, float glyphWidthUV, float glyphHeightUV
+ , float* pVertList, float* pTextureCoordList, int vertIndex, int textureCoordIndex
+ , float translate, float translateDown, float glyphWidth )
+ {
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ PxVec3 v;
+ v = pos + right * translate - up * (translateDown + fontSize);
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ v = pos + right * (glyphWidth + translate) - up * translateDown;
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ v = pos + right * translate - up * translateDown;
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ v = pos + right * translate - up * (fontSize + translateDown);
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV+glyphHeightUV;
+
+ v = pos + right * (glyphWidth + translate) - up * (fontSize + translateDown);
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+
+ pTextureCoordList[textureCoordIndex++] = cxUV+glyphWidthUV;
+ pTextureCoordList[textureCoordIndex++] = cyUV;
+
+ v = pos + right * (glyphWidth + translate) - up * translateDown;
+ pVertList[vertIndex++] = v.x;
+ pVertList[vertIndex++] = v.y;
+ pVertList[vertIndex++] = v.z;
+ }
+};
+
+void GLFontRenderer::print3d(const PxVec3& pos, const PxVec3& cameraDir, const PxVec3& up, float fontSize, const char* pString, bool forceMonoSpace, int monoSpaceWidth)
+{
+ print( fontSize, pString, forceMonoSpace, monoSpaceWidth, false, TextPrint3DRender( pos, cameraDir, up, fontSize ) );
+}
+
+
+void GLFontRenderer::setScreenResolution(int screenWidth, int screenHeight)
+{
+ m_screenWidth = screenWidth;
+ m_screenHeight = screenHeight;
+}
+
+void GLFontRenderer::setColor(unsigned int abgr)
+{
+ m_color = abgr;
+}
+
+#endif //!PHYSX_NO_RENDERER \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/GLFontRenderer.h b/KaplaDemo/samples/sampleViewer3/GLFontRenderer.h
new file mode 100644
index 00000000..321ddc41
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/GLFontRenderer.h
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------------*\
+|
+| AGEIA PhysX Technology
+|
+| www.ageia.com
+|
+\*----------------------------------------------------------------------------*/
+
+#ifndef __GL_FONT_RENDERER__
+#define __GL_FONT_RENDERER__
+
+#include "foundation/PxVec3.h"
+#include "PsArray.h"
+
+using namespace physx;
+
+enum FontColor
+{
+ FNT_COLOR_BLUE = 0xffff0000,
+ FNT_COLOR_GREEN = 0xff00ff00,
+ FNT_COLOR_RED = 0xff0000ff,
+
+ FNT_COLOR_DARK_BLUE = 0xff800000,
+ FNT_COLOR_DARK_GREEN = 0xff008000,
+ FNT_COLOR_DARK_RED = 0xff000080,
+
+ FNT_COLOR_WHITE = 0xffffffff
+};
+
+struct GLFontMeasureResult
+{
+ float width;
+ float height;
+ GLFontMeasureResult( float w, float h )
+ : width( w )
+ , height( h )
+ {
+ }
+};
+
+class GLFontRenderer{
+
+private:
+
+ bool m_isInit;
+ unsigned int m_textureObject;
+ int m_screenWidth;
+ int m_screenHeight;
+ unsigned int m_color;
+ shdfnd::Array<PxF32> mVertList;
+ shdfnd::Array<PxF32> mTextureCoordList;
+ template<typename TOperator>
+ void print( float fontSize, const char* pString, bool forceMonoSpace, int monoSpaceWidth, bool doOthoProj, TOperator inOperator );
+
+public:
+ GLFontRenderer() : m_isInit(false), m_textureObject(0), m_screenWidth(0), m_screenHeight(0) {}
+
+ bool init();
+ void print(float x, float y, float fontSize, const char* pString, bool forceMonoSpace=false, int monoSpaceWidth=11, bool doOrthoProj=true);
+ GLFontMeasureResult measure( float fontSize, const char* pString, bool forceMonoSpace=false, int monoSpaceWidth=11 );
+
+ void print3d(const physx::PxVec3& pos, const physx::PxVec3& cameraDir, const physx::PxVec3& up, float fontSize, const char* pString, bool forceMonoSpace=false, int monoSpaceWidth=11);
+ void setScreenResolution(int screenWidth, int screenHeight);
+ void getScreenResolution( int& screenWidth, int& screenHeight ) { screenWidth = m_screenWidth; screenHeight = m_screenHeight; }
+
+ // PT: contrary to what the comment said before the format is abgr:
+ // 0xffff0000 = blue
+ // 0xff00ff00 = green
+ // 0xff0000ff = red
+ void setColor(unsigned int abgr);
+};
+
+#endif // __GL_FONT_RENDERER__
diff --git a/KaplaDemo/samples/sampleViewer3/HBAOHelper.cpp b/KaplaDemo/samples/sampleViewer3/HBAOHelper.cpp
new file mode 100644
index 00000000..661b8311
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/HBAOHelper.cpp
@@ -0,0 +1,289 @@
+#include <GL/glew.h>
+#include "HBAOHelper.h"
+#include "foundation/PxMat44.h"
+#include "stdio.h"
+
+using namespace physx;
+
+static PxMat44 PerspectiveProjectionMatrix(float fovy, float x, float y, float n, float f)
+{
+ float PPM[16];
+
+ float coty = 1.0f / tan(fovy * physx::PxPi / 360.0f);
+ float aspect = x / (y > 0.0f ? y : 1.0f);
+
+ PPM[0] = coty / aspect;
+ PPM[1] = 0.0f;
+ PPM[2] = 0.0f;
+ PPM[3] = 0.0f;
+
+ PPM[4] = 0.0f;
+ PPM[5] = coty;
+ PPM[6] = 0.0f;
+ PPM[7] = 0.0f;
+
+ PPM[8] = 0.0f;
+ PPM[9] = 0.0f;
+ PPM[10] = (n + f) / (n - f);
+ PPM[11] = -1.0f;
+
+ PPM[12] = 0.0f;
+ PPM[13] = 0.0f;
+ PPM[14] = 2.0f * n * f / (n - f);
+ PPM[15] = 0.0f;
+
+ return PxMat44(PPM);
+}
+
+#ifndef CHECK_GL_ERROR
+#define CHECK_GL_ERROR() checkGLError(__FILE__, __LINE__)
+#endif
+
+void checkGLError(const char* file, int32_t line)
+{
+#if defined(_DEBUG)
+ GLint error = glGetError();
+ if (error)
+ {
+ const char* errorString = 0;
+ switch (error)
+ {
+ case GL_INVALID_ENUM: errorString = "GL_INVALID_ENUM"; break;
+ case GL_INVALID_FRAMEBUFFER_OPERATION: errorString = "GL_INVALID_FRAMEBUFFER_OPERATION"; break;
+ case GL_INVALID_VALUE: errorString = "GL_INVALID_VALUE"; break;
+ case GL_INVALID_OPERATION: errorString = "GL_INVALID_OPERATION"; break;
+ case GL_OUT_OF_MEMORY: errorString = "GL_OUT_OF_MEMORY"; break;
+ default: errorString = "unknown error"; break;
+ }
+ printf("GL error: %s, line %d: %s\n", file, line, errorString);
+ error = 0; // nice place to hang a breakpoint in compiler... :)
+ }
+#endif
+}
+
+HBAOHelper::HBAOHelper(float fov, float zNear, float zFar)
+ : mHbaoGlContext(NULL)
+ , mFov(fov)
+ , mZnear(zNear)
+ , mZFar(zFar)
+ , mWidthAA(0)
+ , mHeightAA(0)
+ , mWidthReal(0)
+ , mHeightReal(0)
+ , mNormalTex(-1)
+ , mDepthTex(-1)
+ , mFBO(0)
+ , mDownScaledFBO(0)
+ , mColorTex(-1)
+{
+ init();
+}
+
+HBAOHelper::~HBAOHelper()
+{
+ if (mHbaoGlContext)
+ mHbaoGlContext->Release();
+
+ glDeleteTextures(1, &mNormalTex);
+ glDeleteTextures(1, &mDepthTex);
+ glDeleteTextures(1, &mColorTex);
+ glDeleteFramebuffers(1, &mFBO);
+ glDeleteFramebuffers(1, &mDownScaledFBO);
+
+ CHECK_GL_ERROR();
+}
+
+bool HBAOHelper::init()
+{
+ memset(mNormalMapTransform, 0, sizeof(float)*16);
+ mNormalMapTransform[0] = -1.0f;
+ mNormalMapTransform[5] = 1.0f;
+ mNormalMapTransform[10] = 1.0f;
+ mNormalMapTransform[15] = 1.0f;
+
+ glGenTextures(1, &mNormalTex);
+ glGenTextures(1, &mDepthTex);
+ glGenTextures(1, &mColorTex);
+ glGenFramebuffers(1, &mFBO);
+ glGenFramebuffers(1, &mDownScaledFBO);
+ CHECK_GL_ERROR();
+
+ GFSDK_SSAO_CustomHeap CustomHeap;
+ CustomHeap.new_ = ::operator new;
+ CustomHeap.delete_ = ::operator delete;
+
+ GFSDK_SSAO_INIT_GL_FUNCTIONS(mGLFunctions);
+
+ GFSDK_SSAO_Status status = GFSDK_SSAO_CreateContext_GL(&mHbaoGlContext, &mGLFunctions, &CustomHeap);
+ if (status != GFSDK_SSAO_OK)
+ return false;
+
+ GFSDK_SSAO_Version Version;
+ status = GFSDK_SSAO_GetVersion(&Version);
+
+ mAoParams.Radius = 1.0f;
+ mAoParams.Bias = 0.5f;
+ mAoParams.NearAO = 4.0f;
+ mAoParams.FarAO = 1.5f;
+
+ mAoParams.BackgroundAO.Enable = false;
+ mAoParams.BackgroundAO.BackgroundViewDepth = 1.f;
+
+ mAoParams.ForegroundAO.Enable = false;
+ mAoParams.ForegroundAO.ForegroundViewDepth = 1.0f;
+
+ mAoParams.DepthStorage = true ? GFSDK_SSAO_FP16_VIEW_DEPTHS : GFSDK_SSAO_FP32_VIEW_DEPTHS;
+ mAoParams.PowerExponent = 2.0f;
+ mAoParams.DepthClampMode = false ? GFSDK_SSAO_CLAMP_TO_BORDER : GFSDK_SSAO_CLAMP_TO_EDGE;
+ mAoParams.Blur.Enable = true;
+ mAoParams.Blur.Sharpness = 16.0f;
+ mAoParams.Blur.Radius = GFSDK_SSAO_BLUR_RADIUS_4;
+
+ return status == GFSDK_SSAO_OK;
+}
+
+void HBAOHelper::resize(int wAA, int hAA, int realw, int realH)
+{
+ mWidthAA = wAA;
+ mHeightAA = hAA;
+
+ mWidthReal = realw;
+ mHeightReal = realH;
+
+ glViewport(0, 0, mWidthReal, mHeightReal);
+ PxMat44 Projection = PerspectiveProjectionMatrix(mFov, float(mWidthReal), float(mHeightReal), mZnear, mZFar);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+ glBindTexture(GL_TEXTURE_2D, mNormalTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidthReal, mHeightReal, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ glBindTexture(GL_TEXTURE_2D, mDepthTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, mWidthReal, mHeightReal, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+ GFSDK_SSAO_Status status = mHbaoGlContext->PreCreateFBOs(mAoParams, mWidthReal, mHeightReal);
+
+ glBindTexture(GL_TEXTURE_2D, mColorTex);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidthReal, mHeightReal, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mDownScaledFBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mColorTex, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ CHECK_GL_ERROR();
+}
+
+bool HBAOHelper::renderAO(void(*renderScene)(), GLuint oldFBO, bool useNormalTexture)
+{
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mNormalTex, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, mDepthTex, 0);
+
+ glViewport(0, 0, mWidthReal, mHeightReal);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ PxMat44 Projection = PerspectiveProjectionMatrix(mFov, float(mWidthReal), float(mHeightReal), mZnear, mZFar);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ renderScene();
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+
+ CHECK_GL_ERROR();
+
+ //
+ // render AO
+ //
+
+ GFSDK_SSAO_InputData_GL Input;
+ Input.DepthData.DepthTextureType = GFSDK_SSAO_HARDWARE_DEPTHS;
+ Input.DepthData.FullResDepthTexture = GFSDK_SSAO_Texture_GL(GL_TEXTURE_2D, mDepthTex);
+ Input.DepthData.ProjectionMatrix.Data = GFSDK_SSAO_Float4x4(&Projection.column0.x);
+ Input.DepthData.ProjectionMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER;
+ Input.DepthData.MetersToViewSpaceUnits = 1.0f;
+
+ if (useNormalTexture)
+ {
+ Input.NormalData.Enable = true;
+ Input.NormalData.FullResNormalTexture = GFSDK_SSAO_Texture_GL(GL_TEXTURE_2D, mNormalTex);
+ Input.NormalData.WorldToViewMatrix.Data = GFSDK_SSAO_Float4x4(mNormalMapTransform);
+ Input.NormalData.WorldToViewMatrix.Layout = GFSDK_SSAO_ROW_MAJOR_ORDER;
+ Input.NormalData.DecodeScale = -2.f;
+ Input.NormalData.DecodeBias = 1.0f;
+ }
+
+ bool renderDirectlyToOldFbo = ((mHeightReal == mHeightAA) && (mWidthReal == mWidthAA));
+ bool showDebugNormals = false;
+ bool showHBAO = false;
+
+ GFSDK_SSAO_RenderMask RenderMask = showDebugNormals ? GFSDK_SSAO_RENDER_DEBUG_NORMAL : GFSDK_SSAO_RENDER_AO;
+ GFSDK_SSAO_Output_GL Output;
+ Output.OutputFBO = renderDirectlyToOldFbo ? oldFBO : mDownScaledFBO;
+ Output.Blend.Mode = !renderDirectlyToOldFbo || showHBAO ? GFSDK_SSAO_OVERWRITE_RGB : GFSDK_SSAO_MULTIPLY_RGB;
+
+ GFSDK_SSAO_Status status;
+ status = mHbaoGlContext->RenderAO(Input, mAoParams, Output, RenderMask);
+
+ if (!renderDirectlyToOldFbo)
+ {
+ // upscale to oldFbo
+ glBindFramebuffer(GL_FRAMEBUFFER, oldFBO);
+
+ glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+ glEnable(GL_BLEND);
+ glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+ glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
+
+ glViewport(0, 0, mWidthAA, mHeightAA);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0, mWidthAA, 0, mHeightAA, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glUseProgram(0);
+
+ glDisable(GL_LIGHTING);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_TEXTURE_2D);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mColorTex);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(float(mWidthAA), 0.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(float(mWidthAA), float(mHeightAA));
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f, float(mHeightAA));
+ glEnd();
+
+ glEnable(GL_LIGHTING);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_BLEND);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ CHECK_GL_ERROR();
+ return true;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/HBAOHelper.h b/KaplaDemo/samples/sampleViewer3/HBAOHelper.h
new file mode 100644
index 00000000..33519ebc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/HBAOHelper.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "GFSDK_SSAO.h"
+#include "Shader.h"
+
+class HBAOHelper
+{
+public:
+ HBAOHelper(float fov, float zNear, float zFar);
+ ~HBAOHelper();
+
+ bool init();
+ bool renderAO(void(*renderScene)(), GLuint oldFBO = 0, bool useNormalTexture = true);
+ void resize(int wAA, int hAA, int realw, int realH);
+
+private:
+ GFSDK_SSAO_Parameters mAoParams;
+ GFSDK_SSAO_GLFunctions mGLFunctions;
+ GFSDK_SSAO_Context_GL* mHbaoGlContext;
+ float mNormalMapTransform[16];
+ float mFov;
+ float mZnear;
+ float mZFar;
+ GLint mWidthAA;
+ GLint mHeightAA;
+ GLint mWidthReal;
+ GLint mHeightReal;
+ GLuint mNormalTex;
+ GLuint mDepthTex;
+ GLuint mFBO;
+ GLuint mDownScaledFBO;
+ GLuint mColorTex;
+};
diff --git a/KaplaDemo/samples/sampleViewer3/HDRHelper.cpp b/KaplaDemo/samples/sampleViewer3/HDRHelper.cpp
new file mode 100644
index 00000000..6f750986
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/HDRHelper.cpp
@@ -0,0 +1,356 @@
+#include "HDRHelper.h"
+#include "foundation/PxMat44.h"
+
+namespace
+{
+PxMat44 PerspectiveProjectionMatrix(float fovy,float x,float y,float n,float f)
+{
+ float PPM[16];
+
+ float coty = 1.0f / tan(fovy * physx::PxPi / 360.0f);
+ float aspect = x / (y > 0.0f ? y : 1.0f);
+
+ PPM[0] = coty / aspect;
+ PPM[1] = 0.0f;
+ PPM[2] = 0.0f;
+ PPM[3] = 0.0f;
+
+ PPM[4] = 0.0f;
+ PPM[5] = coty;
+ PPM[6] = 0.0f;
+ PPM[7] = 0.0f;
+
+ PPM[8] = 0.0f;
+ PPM[9] = 0.0f;
+ PPM[10] = (n + f) / (n - f);
+ PPM[11] = -1.0f;
+
+ PPM[12] = 0.0f;
+ PPM[13] = 0.0f;
+ PPM[14] = 2.0f * n * f / (n - f);
+ PPM[15] = 0.0f;
+
+ return PxMat44(PPM);
+}
+}
+
+const char *HDRToneMappingVS = STRINGIFY(
+ void main(void)
+ {
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex * 2.0 - 1.0;
+ }
+);
+
+const char *HDRBlurHFS = STRINGIFY(
+ uniform sampler2D colorTex;
+ uniform float sx;
+
+ void main (void)
+ {
+ vec3 bloom = vec3(0.0, 0.0, 0.0);
+ const float hdrScale = 1.5;
+ const int kernelSize = 10;
+ const float invScale = 1.0 / (hdrScale * float(kernelSize));
+
+ for (int x = -kernelSize; x <= kernelSize; x++)
+ {
+ float s = gl_TexCoord[0].s + x * sx;
+ float t = gl_TexCoord[0].t;
+ vec3 color = texture2D(colorTex, vec2(s,t)).rgb;
+ float luminance = dot(color, vec3(0.2125, 0.7154, 0.0721));
+ if (luminance > 1.0)
+ {
+ bloom += color * ((kernelSize+1) - abs(float(x)));
+ }
+ }
+
+ gl_FragColor = vec4(bloom * invScale, 1.0);
+ }
+);
+
+const char *HDRBlurVFS = STRINGIFY(
+ uniform sampler2D colorTex;
+ uniform sampler2D blurTex;
+ uniform float sy;
+
+ void main (void)
+ {
+ const float hdrScale = 1.5;
+ const int kernelSize = 10;
+ const float invScale = 1.0 / (hdrScale * float(kernelSize) * 100.0);
+
+ vec3 colorP = texture2D(colorTex, gl_TexCoord[0]).rgb;
+ vec3 bloom = vec3(0.0, 0.0, 0.0);
+
+ for (int y = -kernelSize; y <= kernelSize; y++)
+ {
+ float s = gl_TexCoord[0].s;
+ float t = gl_TexCoord[0].t + y * sy;
+ vec3 color = texture2D(blurTex, vec2(s,t)).rgb;
+ float luminance = dot(color, vec3(0.2125, 0.7154, 0.0721));
+ if (luminance > 1.0)
+ {
+ bloom += color * ((kernelSize+1) - abs(float(y)));
+ }
+ }
+
+ vec3 hdrColor = invScale * bloom + colorP;
+
+ vec3 toneMappedColor = 2.0 * hdrColor / (hdrColor + vec3(1.0));
+ gl_FragColor = vec4(toneMappedColor, 1.0);
+ }
+);
+
+const char *HDRDepthOfFieldFS = STRINGIFY(
+ uniform sampler2D colorTex;
+ uniform sampler2D depthTex;
+ uniform float sx;
+ uniform float sy;
+
+ void main(void)
+ {
+ const float depthEnd = 0.993;
+ const float depthSize = 0.01;
+
+ vec3 colorP = texture2D(colorTex, gl_TexCoord[0]).rgb;
+ float depth = texture2D(depthTex, gl_TexCoord[0].st).r;
+
+ if ((depth - depthEnd) < depthSize)
+ {
+ const int depthKernelSize = 5;
+ vec3 colorSum = vec3(0.0);
+ float cnt = 0.0;
+ for (int x = -depthKernelSize; x <= depthKernelSize; x++)
+ for (int y = -depthKernelSize; y <= depthKernelSize; y++)
+ {
+ float s = gl_TexCoord[0].s + x * sy;
+ float t = gl_TexCoord[0].t + y * sy;
+ float scalex = ((depthKernelSize + 1) - abs(float(x))) / depthKernelSize;
+ float scaley = ((depthKernelSize + 1) - abs(float(y))) / depthKernelSize;
+ float scale = scalex * scaley;
+ vec3 color = texture2D(colorTex, vec2(s, t)).rgb;
+ colorSum += scale * color;
+ cnt += scale;
+ }
+
+ colorSum /= cnt;
+ float depthScale = pow(max(0.0f, min(1.0, (abs(depth - depthEnd)) / depthSize)), 1.5);
+ colorP = depthScale * colorSum + (1.0 - depthScale) * colorP;
+ }
+
+ gl_FragColor = vec4(colorP, 1.0);
+ }
+);
+
+HDRHelper::HDRHelper(float fov,float padding,float zNear,float zFar, const char* resourcePath, float scale) : fov(fov),padding(padding),zNear(zNear),zFar(zFar), scale(scale)
+{
+ mShaderBloomH.loadShaderCode(HDRToneMappingVS, HDRBlurHFS);
+ mShaderBloomV.loadShaderCode(HDRToneMappingVS, HDRBlurVFS);
+ mShaderDOF.loadShaderCode(HDRToneMappingVS, HDRDepthOfFieldFS);
+
+ glGenTextures(1,&mHDRColorTex);
+ glGenTextures(1,&mHDRDepthTex);
+ glGenTextures(1,&mHDRBlurTex);
+ glGenTextures(1,&mHDRBloomTex);
+
+ glGenFramebuffers(1,&mHDRFbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,mHDRColorTex, 0);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ glGenFramebuffers(1,&mHDRBlurFbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRBlurFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,mHDRBlurTex, 0);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ //printf("Frame buffer status %d\n\n\n",
+ // (status == GL_FRAMEBUFFER_COMPLETE) ? 1 : 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void HDRHelper::Resize(int w,int h) {
+
+ realWidth = w;
+ realHeight = h;
+ Width = w*scale;
+ Height = h*scale;
+
+ fovPad = 2.0f*atan(tan(fov*0.5f*physx::PxPi/180.0f)*(1.0f+padding))*180.0f/physx::PxPi;
+
+ glViewport(0,0,w,h);
+
+ // allocate HDR color buffer
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRFbo);
+
+ glBindTexture(GL_TEXTURE_2D,mHDRColorTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F,w,h,0,GL_RGBA,GL_FLOAT,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,mHDRDepthTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT24,w,h,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL);
+
+ // allocate HDR color buffer for blur operations
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRBlurFbo);
+
+ glBindTexture(GL_TEXTURE_2D,mHDRBlurTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F,w,h,0,GL_RGBA,GL_FLOAT,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,mHDRBloomTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F,w,h,0,GL_RGBA,GL_FLOAT,NULL);
+
+ // set program values
+ glUseProgram(mShaderBloomH);
+ glUniform1f(glGetUniformLocation(mShaderBloomH,"sx"),1.0f / (float)w);
+
+ glUseProgram(mShaderBloomV);
+ glUniform1f(glGetUniformLocation(mShaderBloomV,"sy"),1.0f / (float)h);
+
+ glUseProgram(mShaderDOF);
+ glUniform1f(glGetUniformLocation(mShaderDOF,"sx"),1.0f / (float)w);
+ glUniform1f(glGetUniformLocation(mShaderDOF,"sy"),1.0f / (float)h);
+
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+}
+
+void HDRHelper::Destroy() {
+
+ mShaderBloomH.deleteShaders();
+ mShaderBloomV.deleteShaders();
+
+ glDeleteTextures(1,&mHDRColorTex);
+ glDeleteTextures(1,&mHDRDepthTex);
+ glDeleteTextures(1,&mHDRBlurTex);
+ glDeleteTextures(1,&mHDRBloomTex);
+
+ glDeleteFramebuffers(1,&mHDRFbo);
+ glDeleteFramebuffers(1,&mHDRBlurFbo);
+}
+
+void HDRHelper::beginHDR(bool useOwnFbo)
+{
+ if (useOwnFbo)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,mHDRColorTex, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,mHDRDepthTex,0);
+
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+}
+
+void HDRHelper::endHDR(bool useOwnFbo)
+{
+ if (useOwnFbo)
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void
+drawQuads(float s = 1.0f)
+{
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(s,0.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(s,s);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(0.0f,s);
+ glEnd();
+}
+
+void HDRHelper::DoHDR(GLuint oldFBO, bool useDOF) {
+
+ PxMat44 Projection = PerspectiveProjectionMatrix(fov,Width,Height,zNear,zFar);
+
+ // render stored HDR fbo onto blur fbo, first with horizontal blur
+ glBindFramebuffer(GL_FRAMEBUFFER, mHDRBlurFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,mHDRBlurTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,0,0);
+
+ glViewport(0,0,realWidth,realHeight);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, mHDRColorTex);
+
+ glUseProgram(mShaderBloomH);
+ glUniform1f(glGetUniformLocation(mShaderBloomH, "sx"), 1.0f / (float)realWidth);
+ glUniform1i(glGetUniformLocation(mShaderBloomH,"colorTex"),0);
+
+ drawQuads();
+
+ glUseProgram(0);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,0);
+
+ // now apply vertical blur for the bloom
+ if (useDOF)
+ {
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,mHDRBloomTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,0,0);
+ }
+ else
+ glBindFramebuffer(GL_FRAMEBUFFER,oldFBO);
+
+ glViewport(0,0,realWidth,realHeight);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,mHDRColorTex);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,mHDRBlurTex);
+
+ glUseProgram(mShaderBloomV);
+ glUniform1f(glGetUniformLocation(mShaderBloomV, "sy"), 1.0f / (float)realHeight);
+ glUniform1i(glGetUniformLocation(mShaderBloomV,"colorTex"),0);
+ glUniform1i(glGetUniformLocation(mShaderBloomV,"blurTex"),1);
+
+ drawQuads();
+
+ glUseProgram(0);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,0);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,0);
+
+ // now render the final image onto supplied fbo, apply DOF
+ if (!useDOF) return;
+
+ glBindFramebuffer(GL_FRAMEBUFFER,oldFBO);
+
+ glViewport(0,0,realWidth,realHeight);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,mHDRBloomTex);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,mHDRDepthTex);
+
+ glUseProgram(mShaderDOF);
+ glUniform1f(glGetUniformLocation(mShaderDOF, "sx"), 1.0f / (float)realWidth);
+ glUniform1f(glGetUniformLocation(mShaderDOF, "sy"), 1.0f / (float)realHeight);
+ glUniform1i(glGetUniformLocation(mShaderDOF,"colorTex"),0);
+ glUniform1i(glGetUniformLocation(mShaderDOF,"depthTex"),1);
+
+ drawQuads();
+
+ glUseProgram(0);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,0);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,0);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/HDRHelper.h b/KaplaDemo/samples/sampleViewer3/HDRHelper.h
new file mode 100644
index 00000000..8fa610a3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/HDRHelper.h
@@ -0,0 +1,37 @@
+#pragma once
+#include <GL/glew.h>
+#include "Shader.h"
+
+class HDRHelper{
+public:
+ int Width, Height;
+ int realWidth, realHeight;
+
+ float padding;
+ float fov;
+ float fovPad;
+ float zNear, zFar;
+ float scale;
+
+ Shader mShaderBloomH;
+ Shader mShaderBloomV;
+ Shader mShaderDOF;
+
+ HDRHelper(float fov, float padding, float zNear, float zFar, const char* resourcePath, float scale);
+
+ void beginHDR(bool useOwnFbo = true);
+ void endHDR(bool useOwnFbo = true);
+
+ void Resize(int w, int h);
+
+ void DoHDR(GLuint oldFBO = 0, bool useDOF = true);
+ void Destroy();
+
+ GLuint mHDRFbo;
+ GLuint mHDRBlurFbo;
+
+ GLuint mHDRColorTex;
+ GLuint mHDRDepthTex;
+ GLuint mHDRBlurTex;
+ GLuint mHDRBloomTex;
+};
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.cpp
new file mode 100644
index 00000000..685d0209
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.cpp
@@ -0,0 +1,94 @@
+#include "stdafx.h"
+#include "CPPJPEGWrapper.h"
+
+CPPJPEGWrapper::CPPJPEGWrapper() {
+ data = 0;
+ x = 0;
+ y = 0;
+}
+CPPJPEGWrapper::~CPPJPEGWrapper() {
+ Unload();
+}
+void CPPJPEGWrapper::Unload() {
+ if (data) {
+ delete [] data;
+ data = 0;
+ }
+}
+
+unsigned char* CPPJPEGWrapper::GetData() const {
+ return data;
+}
+unsigned CPPJPEGWrapper::GetWidth() {
+ return x;
+}
+unsigned CPPJPEGWrapper::GetHeight() {
+ return y;
+}
+unsigned CPPJPEGWrapper::GetBPP() {
+ return bpp;
+}
+unsigned CPPJPEGWrapper::GetChannels() {
+ return channels;
+}
+
+
+bool CPPJPEGWrapper::LoadJPEG(const char* FileName, bool Fast)
+{
+ Unload();
+ FILE* file = fopen(FileName, "rb"); //open the file
+ if (!file) return false;
+ struct jpeg_decompress_struct info; //the jpeg decompress info
+ struct jpeg_error_mgr err; //the error handler
+
+ info.err = jpeg_std_error(&err); //tell the jpeg decompression handler to send the errors to err
+ jpeg_create_decompress(&info); //sets info to all the default stuff
+
+ //if the jpeg file didnt load exit
+ if(!file)
+ {
+ //fprintf(stderr, "Error reading JPEG file %s!!!", FileName);
+ //LoadBlackWhiteBorder();
+ return false;
+ }
+
+ jpeg_stdio_src(&info, file); //tell the jpeg lib the file we'er reading
+
+ jpeg_read_header(&info, TRUE); //tell it to start reading it
+
+ //if it wants to be read fast or not
+ if(Fast)
+ {
+ info.do_fancy_upsampling = FALSE;
+ }
+
+ jpeg_start_decompress(&info); //decompress the file
+
+ //set the x and y
+ x = info.output_width;
+ y = info.output_height;
+ channels = info.num_components;
+
+ bpp = channels * 8;
+
+ size = x * y * 3;
+
+ //read turn the uncompressed data into something ogl can read
+ data = new unsigned char[size]; //setup data for the data its going to be handling
+
+ unsigned char* p1 = data;
+ unsigned char** p2 = &p1;
+ int numlines = 0;
+
+ while(info.output_scanline < info.output_height)
+ {
+ numlines = jpeg_read_scanlines(&info, p2, 1);
+ *p2 += numlines * 3 * info.output_width;
+ }
+
+ jpeg_finish_decompress(&info); //finish decompressing this file
+
+ fclose(file); //close the file
+
+ return true;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.h
new file mode 100644
index 00000000..da5f1f59
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/CPPJPEGWrapper.h
@@ -0,0 +1,32 @@
+#pragma once
+#include <cstdio>
+#include <cstdlib>
+#include "jpeglib.h"
+#include "jerror.h"
+
+class CPPJPEGWrapper{
+public:
+ CPPJPEGWrapper();
+ ~CPPJPEGWrapper();
+ void Unload();
+
+ unsigned char* GetData() const;
+ unsigned GetWidth();
+ unsigned GetHeight();
+ unsigned GetBPP();
+ unsigned GetChannels();
+
+
+ bool LoadJPEG(const char* FileName, bool Fast = true);
+protected:
+ //if the jpeglib stuff isnt after I think stdlib then it wont work just put it at the end
+ unsigned long x;
+ unsigned long y;
+ unsigned short int bpp; //bits per pixels unsigned short int
+ unsigned char* data; //the data of the image
+ unsigned int ID; //the id ogl gives it
+ unsigned long size; //length of the file
+ int channels; //the channels of the image 3 = RGA 4 = RGBA
+
+
+};
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/ReadMe.txt b/KaplaDemo/samples/sampleViewer3/IJGWin32/ReadMe.txt
new file mode 100644
index 00000000..aa307f9b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/ReadMe.txt
@@ -0,0 +1,29 @@
+========================================================================
+ STATIC LIBRARY : IJGWin32 Project Overview
+========================================================================
+
+AppWizard has created this IJGWin32 library project for you.
+This file contains a summary of what you will find in each of the files that
+make up your IJGWin32 application.
+
+
+IJGWin32.vcproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named IJGWin32.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/ansi2knr.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/ansi2knr.cpp
new file mode 100644
index 00000000..b8f09941
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/ansi2knr.cpp
@@ -0,0 +1,681 @@
+/* ansi2knr.c */
+/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
+
+/*
+ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone for the
+consequences of using it or for whether it serves any particular purpose or
+works at all, unless he says so in writing. Refer to the GNU General Public
+License (the "GPL") for full details.
+
+Everyone is granted permission to copy, modify and redistribute ansi2knr,
+but only under the conditions described in the GPL. A copy of this license
+is supposed to have been given to you along with ansi2knr so you can know
+your rights and responsibilities. It should be in a file named COPYLEFT.
+[In the IJG distribution, the GPL appears below, not in a separate file.]
+Among other things, the copyright notice and this notice must be preserved
+on all copies.
+
+We explicitly state here what we believe is already implied by the GPL: if
+the ansi2knr program is distributed as a separate set of sources and a
+separate executable file which are aggregated on a storage medium together
+with another program, this in itself does not bring the other program under
+the GPL, nor does the mere fact that such a program or the procedures for
+constructing it invoke the ansi2knr executable bring any other part of the
+program under the GPL.
+*/
+
+/*
+---------- Here is the GNU GPL file COPYLEFT, referred to above ----------
+----- These terms do NOT apply to the JPEG software itself; see README ------
+
+ GHOSTSCRIPT GENERAL PUBLIC LICENSE
+ (Clarified 11 Feb 1988)
+
+ Copyright (C) 1988 Richard M. Stallman
+ Everyone is permitted to copy and distribute verbatim copies of this
+ license, but changing it is not allowed. You can also use this wording
+ to make the terms for other programs.
+
+ The license agreements of most software companies keep you at the
+mercy of those companies. By contrast, our general public license is
+intended to give everyone the right to share Ghostscript. To make sure
+that you get the rights we want you to have, we need to make
+restrictions that forbid anyone to deny you these rights or to ask you
+to surrender the rights. Hence this license agreement.
+
+ Specifically, we want to make sure that you have the right to give
+away copies of Ghostscript, that you receive source code or else can get
+it if you want it, that you can change Ghostscript or use pieces of it
+in new free programs, and that you know you can do these things.
+
+ To make sure that everyone has such rights, we have to forbid you to
+deprive anyone else of these rights. For example, if you distribute
+copies of Ghostscript, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ Also, for our own protection, we must make certain that everyone finds
+out that there is no warranty for Ghostscript. If Ghostscript is
+modified by someone else and passed on, we want its recipients to know
+that what they have is not what we distributed, so that any problems
+introduced by others will not reflect on our reputation.
+
+ Therefore we (Richard M. Stallman and the Free Software Foundation,
+Inc.) make the following terms which say what you must do to be allowed
+to distribute or change Ghostscript.
+
+
+ COPYING POLICIES
+
+ 1. You may copy and distribute verbatim copies of Ghostscript source
+code as you receive it, in any medium, provided that you conspicuously
+and appropriately publish on each copy a valid copyright and license
+notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved.
+Distributed by Free Software Foundation, Inc." (or with whatever year is
+appropriate); keep intact the notices on all files that refer to this
+License Agreement and to the absence of any warranty; and give any other
+recipients of the Ghostscript program a copy of this License Agreement
+along with the program. You may charge a distribution fee for the
+physical act of transferring a copy.
+
+ 2. You may modify your copy or copies of Ghostscript or any portion of
+it, and copy and distribute such modifications under the terms of
+Paragraph 1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating
+ that you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish,
+ that in whole or in part contains or is a derivative of Ghostscript
+ or any part thereof, to be licensed at no charge to all third
+ parties on terms identical to those contained in this License
+ Agreement (except that you may choose to grant more extensive
+ warranty protection to some or all third parties, at your option).
+
+ c) You may charge a distribution fee for the physical act of
+ transferring a copy, and you may at your option offer warranty
+ protection in exchange for a fee.
+
+Mere aggregation of another unrelated program with this program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other program under the scope of these terms.
+
+ 3. You may copy and distribute Ghostscript (or a portion or derivative
+of it, under Paragraph 2) in object code or executable form under the
+terms of Paragraphs 1 and 2 above provided that you also do one of the
+following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal
+ shipping charge) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+For an executable file, complete source code means all the source code for
+all modules it contains; but, as a special exception, it need not include
+source code for modules which are standard libraries that accompany the
+operating system on which the executable file runs.
+
+ 4. You may not copy, sublicense, distribute or transfer Ghostscript
+except as expressly provided under this License Agreement. Any attempt
+otherwise to copy, sublicense, distribute or transfer Ghostscript is
+void and your rights to use the program under this License agreement
+shall be automatically terminated. However, parties who have received
+computer software programs from you with this License Agreement will not
+have their licenses terminated so long as such parties remain in full
+compliance.
+
+ 5. If you wish to incorporate parts of Ghostscript into other free
+programs whose distribution conditions are different, write to the Free
+Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not
+yet worked out a simple rule that can be stated here, but we will often
+permit this. We will be guided by the two goals of preserving the free
+status of all derivatives of our free software and of promoting the
+sharing and reuse of software.
+
+Your comments and suggestions about our licensing policies and our
+software are welcome! Please contact the Free Software Foundation,
+Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
+
+ NO WARRANTY
+
+ BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
+NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
+WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
+M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
+PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
+EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
+YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
+NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
+STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
+ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
+GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
+ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
+(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
+INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
+PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
+HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
+BY ANY OTHER PARTY.
+
+-------------------- End of file COPYLEFT ------------------------------
+*/
+
+/*
+ * Usage:
+ ansi2knr input_file [output_file]
+ * If no output_file is supplied, output goes to stdout.
+ * There are no error messages.
+ *
+ * ansi2knr recognizes function definitions by seeing a non-keyword
+ * identifier at the left margin, followed by a left parenthesis,
+ * with a right parenthesis as the last character on the line,
+ * and with a left brace as the first token on the following line
+ * (ignoring possible intervening comments).
+ * It will recognize a multi-line header provided that no intervening
+ * line ends with a left or right brace or a semicolon.
+ * These algorithms ignore whitespace and comments, except that
+ * the function name must be the first thing on the line.
+ * The following constructs will confuse it:
+ * - Any other construct that starts at the left margin and
+ * follows the above syntax (such as a macro or function call).
+ * - Some macros that tinker with the syntax of the function header.
+ */
+
+/*
+ * The original and principal author of ansi2knr is L. Peter Deutsch
+ * <[email protected]>. Other authors are noted in the change history
+ * that follows (in reverse chronological order):
+ lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
+ compilers that don't understand void, as suggested by
+ Tom Lane
+ lpd 96-01-15 changed to require that the first non-comment token
+ on the line following a function header be a left brace,
+ to reduce sensitivity to macros, as suggested by Tom Lane
+ lpd 95-06-22 removed #ifndefs whose sole purpose was to define
+ undefined preprocessor symbols as 0; changed all #ifdefs
+ for configuration symbols to #ifs
+ lpd 95-04-05 changed copyright notice to make it clear that
+ including ansi2knr in a program does not bring the entire
+ program under the GPL
+ lpd 94-12-18 added conditionals for systems where ctype macros
+ don't handle 8-bit characters properly, suggested by
+ Francois Pinard <[email protected]>;
+ removed --varargs switch (this is now the default)
+ lpd 94-10-10 removed CONFIG_BROKETS conditional
+ lpd 94-07-16 added some conditionals to help GNU `configure',
+ suggested by Francois Pinard <[email protected]>;
+ properly erase prototype args in function parameters,
+ contributed by Jim Avera <[email protected]>;
+ correct error in writeblanks (it shouldn't erase EOLs)
+ lpd 89-xx-xx original version
+ */
+
+/* Most of the conditionals here are to make ansi2knr work with */
+/* or without the GNU configure machinery. */
+#include "stdafx.h"
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if HAVE_CONFIG_H
+
+/*
+ For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
+ This will define HAVE_CONFIG_H and so, activate the following lines.
+ */
+
+# if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+#else /* not HAVE_CONFIG_H */
+
+/* Otherwise do it the hard way */
+
+# ifdef BSD
+# include <strings.h>
+# else
+# ifdef VMS
+ extern int strlen(), strncmp();
+# else
+# include <string.h>
+# endif
+# endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+/*
+ malloc and free should be declared in stdlib.h,
+ but if you've got a K&R compiler, they probably aren't.
+ */
+# ifdef MSDOS
+# include <malloc.h>
+# else
+# ifdef VMS
+ extern char *malloc();
+ extern void free();
+# else
+ extern char *malloc();
+ extern int free();
+# endif
+# endif
+
+#endif
+
+/*
+ * The ctype macros don't always handle 8-bit characters correctly.
+ * Compensate for this here.
+ */
+#ifdef isascii
+# undef HAVE_ISASCII /* just in case */
+# define HAVE_ISASCII 1
+#else
+#endif
+#if STDC_HEADERS || !HAVE_ISASCII
+# define is_ascii(c) 1
+#else
+# define is_ascii(c) isascii(c)
+#endif
+
+#define is_space(c) (is_ascii(c) && isspace(c))
+#define is_alpha(c) (is_ascii(c) && isalpha(c))
+#define is_alnum(c) (is_ascii(c) && isalnum(c))
+
+/* Scanning macros */
+#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
+#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
+
+/* Forward references */
+char *skipspace();
+int writeblanks();
+int test1();
+int convert1();
+
+///* The main program */
+//int
+//main(argc, argv)
+// int argc;
+// char *argv[];
+//{ FILE *in, *out;
+//#define bufsize 5000 /* arbitrary size */
+// char *buf;
+// char *line;
+// char *more;
+// /*
+// * In previous versions, ansi2knr recognized a --varargs switch.
+// * If this switch was supplied, ansi2knr would attempt to convert
+// * a ... argument to va_alist and va_dcl; if this switch was not
+// * supplied, ansi2knr would simply drop any such arguments.
+// * Now, ansi2knr always does this conversion, and we only
+// * check for this switch for backward compatibility.
+// */
+// int convert_varargs = 1;
+//
+// if ( argc > 1 && argv[1][0] == '-' )
+// { if ( !strcmp(argv[1], "--varargs") )
+// { convert_varargs = 1;
+// argc--;
+// argv++;
+// }
+// else
+// { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
+// exit(1);
+// }
+// }
+// switch ( argc )
+// {
+// default:
+// printf("Usage: ansi2knr input_file [output_file]\n");
+// exit(0);
+// case 2:
+// out = stdout;
+// break;
+// case 3:
+// out = fopen(argv[2], "w");
+// if ( out == NULL )
+// { fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+// exit(1);
+// }
+// }
+// in = fopen(argv[1], "r");
+// if ( in == NULL )
+// { fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+// exit(1);
+// }
+// fprintf(out, "#line 1 \"%s\"\n", argv[1]);
+// buf = malloc(bufsize);
+// line = buf;
+// while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
+// {
+//test: line += strlen(line);
+// switch ( test1(buf) )
+// {
+// case 2: /* a function header */
+// convert1(buf, out, 1, convert_varargs);
+// break;
+// case 1: /* a function */
+// /* Check for a { at the start of the next line. */
+// more = ++line;
+//f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
+// goto wl;
+// if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
+// goto wl;
+// switch ( *skipspace(more, 1) )
+// {
+// case '{':
+// /* Definitely a function header. */
+// convert1(buf, out, 0, convert_varargs);
+// fputs(more, out);
+// break;
+// case 0:
+// /* The next line was blank or a comment: */
+// /* keep scanning for a non-comment. */
+// line += strlen(line);
+// goto f;
+// default:
+// /* buf isn't a function header, but */
+// /* more might be. */
+// fputs(buf, out);
+// strcpy(buf, more);
+// line = buf;
+// goto test;
+// }
+// break;
+// case -1: /* maybe the start of a function */
+// if ( line != buf + (bufsize - 1) ) /* overflow check */
+// continue;
+// /* falls through */
+// default: /* not a function */
+//wl: fputs(buf, out);
+// break;
+// }
+// line = buf;
+// }
+// if ( line != buf )
+// fputs(buf, out);
+// free(buf);
+// fclose(out);
+// fclose(in);
+// return 0;
+//}
+
+/* Skip over space and comments, in either direction. */
+char * skipspace(register char *p, register int dir) /* 1 for forward, -1 for backward */
+{ for ( ; ; )
+ { while ( is_space(*p) )
+ p += dir;
+ if ( !(*p == '/' && p[dir] == '*') )
+ break;
+ p += dir; p += dir;
+ while ( !(*p == '*' && p[dir] == '/') )
+ { if ( *p == 0 )
+ return p; /* multi-line comment?? */
+ p += dir;
+ }
+ p += dir; p += dir;
+ }
+ return p;
+}
+
+/*
+ * Write blanks over part of a string.
+ * Don't overwrite end-of-line characters.
+ */
+int writeblanks(char *start, char *end)
+{ char *p;
+ for ( p = start; p < end; p++ )
+ if ( *p != '\r' && *p != '\n' )
+ *p = ' ';
+ return 0;
+}
+
+/*
+ * Test whether the string in buf is a function definition.
+ * The string may contain and/or end with a newline.
+ * Return as follows:
+ * 0 - definitely not a function definition;
+ * 1 - definitely a function definition;
+ * 2 - definitely a function prototype (NOT USED);
+ * -1 - may be the beginning of a function definition,
+ * append another line and look again.
+ * The reason we don't attempt to convert function prototypes is that
+ * Ghostscript's declaration-generating macros look too much like
+ * prototypes, and confuse the algorithms.
+ */
+int test1(char *buf)
+{ register char *p = buf;
+ char *bend;
+ char *endfn;
+ int contin;
+
+ if ( !isidfirstchar(*p) )
+ return 0; /* no name at left margin */
+ bend = skipspace(buf + strlen(buf) - 1, -1);
+ switch ( *bend )
+ {
+ case ';': contin = 0 /*2*/; break;
+ case ')': contin = 1; break;
+ case '{': return 0; /* not a function */
+ case '}': return 0; /* not a function */
+ default: contin = -1;
+ }
+ while ( isidchar(*p) )
+ p++;
+ endfn = p;
+ p = skipspace(p, 1);
+ if ( *p++ != '(' )
+ return 0; /* not a function */
+ p = skipspace(p, 1);
+ if ( *p == ')' )
+ return 0; /* no parameters */
+ /* Check that the apparent function name isn't a keyword. */
+ /* We only need to check for keywords that could be followed */
+ /* by a left parenthesis (which, unfortunately, is most of them). */
+ { static char *words[] =
+ { "asm", "auto", "case", "char", "const", "double",
+ "extern", "float", "for", "if", "int", "long",
+ "register", "return", "short", "signed", "sizeof",
+ "static", "switch", "typedef", "unsigned",
+ "void", "volatile", "while", 0
+ };
+ char **key = words;
+ char *kp;
+ int len = (int)(endfn - buf);
+
+ while ( (kp = *key) != 0 )
+ { if ( strlen(kp) == len && !strncmp(kp, buf, len) )
+ return 0; /* name is a keyword */
+ key++;
+ }
+ }
+ return contin;
+}
+
+/* Convert a recognized function definition or header to K&R syntax. */
+int convert1(char *buf, FILE *out, int header,int convert_varargs)
+{ char *endfn;
+ register char *p;
+ char **breaks;
+ unsigned num_breaks = 2; /* for testing */
+ char **btop;
+ char **bp;
+ char **ap;
+ char *vararg = 0;
+
+ /* Pre-ANSI implementations don't agree on whether strchr */
+ /* is called strchr or index, so we open-code it here. */
+ for ( endfn = buf; *(endfn++) != '('; )
+ ;
+top: p = endfn;
+ breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
+ if ( breaks == 0 )
+ { /* Couldn't allocate break table, give up */
+ fprintf(stderr, "Unable to allocate break table!\n");
+ fputs(buf, out);
+ return -1;
+ }
+ btop = breaks + num_breaks * 2 - 2;
+ bp = breaks;
+ /* Parse the argument list */
+ do
+ { int level = 0;
+ char *lp = NULL;
+ char *rp;
+ char *end = NULL;
+
+ if ( bp >= btop )
+ { /* Filled up break table. */
+ /* Allocate a bigger one and start over. */
+ free((char *)breaks);
+ num_breaks <<= 1;
+ goto top;
+ }
+ *bp++ = p;
+ /* Find the end of the argument */
+ for ( ; end == NULL; p++ )
+ { switch(*p)
+ {
+ case ',':
+ if ( !level ) end = p;
+ break;
+ case '(':
+ if ( !level ) lp = p;
+ level++;
+ break;
+ case ')':
+ if ( --level < 0 ) end = p;
+ else rp = p;
+ break;
+ case '/':
+ p = skipspace(p, 1) - 1;
+ break;
+ default:
+ ;
+ }
+ }
+ /* Erase any embedded prototype parameters. */
+ if ( lp )
+ writeblanks(lp + 1, rp);
+ p--; /* back up over terminator */
+ /* Find the name being declared. */
+ /* This is complicated because of procedure and */
+ /* array modifiers. */
+ for ( ; ; )
+ { p = skipspace(p - 1, -1);
+ switch ( *p )
+ {
+ case ']': /* skip array dimension(s) */
+ case ')': /* skip procedure args OR name */
+ { int level = 1;
+ while ( level )
+ switch ( *--p )
+ {
+ case ']': case ')': level++; break;
+ case '[': case '(': level--; break;
+ case '/': p = skipspace(p, -1) + 1; break;
+ default: ;
+ }
+ }
+ if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
+ { /* We found the name being declared */
+ while ( !isidfirstchar(*p) )
+ p = skipspace(p, 1) + 1;
+ goto found;
+ }
+ break;
+ default:
+ goto found;
+ }
+ }
+found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
+ { if ( convert_varargs )
+ { *bp++ = "va_alist";
+ vararg = p-2;
+ }
+ else
+ { p++;
+ if ( bp == breaks + 1 ) /* sole argument */
+ writeblanks(breaks[0], p);
+ else
+ writeblanks(bp[-1] - 1, p);
+ bp--;
+ }
+ }
+ else
+ { while ( isidchar(*p) ) p--;
+ *bp++ = p+1;
+ }
+ p = end;
+ }
+ while ( *p++ == ',' );
+ *bp = p;
+ /* Make a special check for 'void' arglist */
+ if ( bp == breaks+2 )
+ { p = skipspace(breaks[0], 1);
+ if ( !strncmp(p, "void", 4) )
+ { p = skipspace(p+4, 1);
+ if ( p == breaks[2] - 1 )
+ { bp = breaks; /* yup, pretend arglist is empty */
+ writeblanks(breaks[0], p + 1);
+ }
+ }
+ }
+ /* Put out the function name and left parenthesis. */
+ p = buf;
+ while ( p != endfn ) putc(*p, out), p++;
+ /* Put out the declaration. */
+ if ( header )
+ { fputs(");", out);
+ for ( p = breaks[0]; *p; p++ )
+ if ( *p == '\r' || *p == '\n' )
+ putc(*p, out);
+ }
+ else
+ { for ( ap = breaks+1; ap < bp; ap += 2 )
+ { p = *ap;
+ while ( isidchar(*p) )
+ putc(*p, out), p++;
+ if ( ap < bp - 1 )
+ fputs(", ", out);
+ }
+ fputs(") ", out);
+ /* Put out the argument declarations */
+ for ( ap = breaks+2; ap <= bp; ap += 2 )
+ (*ap)[-1] = ';';
+ if ( vararg != 0 )
+ { *vararg = 0;
+ fputs(breaks[0], out); /* any prior args */
+ fputs("va_dcl", out); /* the final arg */
+ fputs(bp[0], out);
+ }
+ else
+ fputs(breaks[0], out);
+ }
+ free((char *)breaks);
+ return 0;
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/cderror.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/cderror.h
new file mode 100644
index 00000000..70435e16
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/cderror.h
@@ -0,0 +1,132 @@
+/*
+ * cderror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the cjpeg/djpeg
+ * applications. These strings are not needed as part of the JPEG library
+ * proper.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef CDERROR_H
+#define CDERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* CDERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
+
+#ifdef BMP_SUPPORTED
+JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
+JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
+JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
+JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
+JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
+JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
+JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
+JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
+JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
+JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
+JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
+#endif /* BMP_SUPPORTED */
+
+#ifdef GIF_SUPPORTED
+JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
+JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
+JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
+JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
+JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
+JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
+JMESSAGE(JTRC_GIF_BADVERSION,
+ "Warning: unexpected GIF version number '%c%c%c'")
+JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
+JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
+JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
+JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
+JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
+JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
+#endif /* GIF_SUPPORTED */
+
+#ifdef PPM_SUPPORTED
+JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
+JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
+JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
+JMESSAGE(JTRC_PGM, "%ux%u PGM image")
+JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
+JMESSAGE(JTRC_PPM, "%ux%u PPM image")
+JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
+#endif /* PPM_SUPPORTED */
+
+#ifdef RLE_SUPPORTED
+JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
+JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
+JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
+JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
+JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
+JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
+JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
+JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
+JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
+JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
+JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
+JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
+#endif /* RLE_SUPPORTED */
+
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
+JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
+JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
+JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
+JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
+JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
+#else
+JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
+#endif /* TARGA_SUPPORTED */
+
+JMESSAGE(JERR_BAD_CMAP_FILE,
+ "Color map file is invalid or of unsupported format")
+JMESSAGE(JERR_TOO_MANY_COLORS,
+ "Output file format cannot handle %d colormap entries")
+JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_UNKNOWN_FORMAT,
+ "Unrecognized input file format --- perhaps you need -targa")
+#else
+JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
+#endif
+JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTADDONCODE
+} ADDON_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.cpp
new file mode 100644
index 00000000..d19cff24
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.cpp
@@ -0,0 +1,182 @@
+/*
+ * cdjpeg.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains common support routines used by the IJG application
+ * programs (cjpeg, djpeg, jpegtran).
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include <ctype.h> /* to declare isupper(), tolower() */
+#ifdef NEED_SIGNAL_CATCHER
+#include <signal.h> /* to declare signal() */
+#endif
+#ifdef USE_SETMODE
+#include <fcntl.h> /* to declare setmode()'s parameter macros */
+/* If you have setmode() but not <io.h>, just delete this line: */
+#include <io.h> /* to declare setmode() */
+#endif
+
+
+/*
+ * Signal catcher to ensure that temporary files are removed before aborting.
+ * NB: for Amiga Manx C this is actually a global routine named _abort();
+ * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
+ */
+
+#ifdef NEED_SIGNAL_CATCHER
+
+static j_common_ptr sig_cinfo;
+
+void /* must be global for Manx C */
+signal_catcher (int signum)
+{
+ if (sig_cinfo != NULL) {
+ if (sig_cinfo->err != NULL) /* turn off trace output */
+ sig_cinfo->err->trace_level = 0;
+ jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
+ }
+ exit(EXIT_FAILURE);
+}
+
+
+GLOBAL(void)
+enable_signal_catcher (j_common_ptr cinfo)
+{
+ sig_cinfo = cinfo;
+#ifdef SIGINT /* not all systems have SIGINT */
+ signal(SIGINT, signal_catcher);
+#endif
+#ifdef SIGTERM /* not all systems have SIGTERM */
+ signal(SIGTERM, signal_catcher);
+#endif
+}
+
+#endif
+
+
+/*
+ * Optional progress monitor: display a percent-done figure on stderr.
+ */
+
+#ifdef PROGRESS_REPORT
+
+METHODDEF(void)
+progress_monitor (j_common_ptr cinfo)
+{
+ cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
+ int total_passes = prog->pub.total_passes + prog->total_extra_passes;
+ int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
+
+ if (percent_done != prog->percent_done) {
+ prog->percent_done = percent_done;
+ if (total_passes > 1) {
+ fprintf(stderr, "\rPass %d/%d: %3d%% ",
+ prog->pub.completed_passes + prog->completed_extra_passes + 1,
+ total_passes, percent_done);
+ } else {
+ fprintf(stderr, "\r %3d%% ", percent_done);
+ }
+ fflush(stderr);
+ }
+}
+
+
+GLOBAL(void)
+start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
+{
+ /* Enable progress display, unless trace output is on */
+ if (cinfo->err->trace_level == 0) {
+ progress->pub.progress_monitor = progress_monitor;
+ progress->completed_extra_passes = 0;
+ progress->total_extra_passes = 0;
+ progress->percent_done = -1;
+ cinfo->progress = &progress->pub;
+ }
+}
+
+
+GLOBAL(void)
+end_progress_monitor (j_common_ptr cinfo)
+{
+ /* Clear away progress display */
+ if (cinfo->err->trace_level == 0) {
+ fprintf(stderr, "\r \r");
+ fflush(stderr);
+ }
+}
+
+#endif
+
+
+/*
+ * Case-insensitive matching of possibly-abbreviated keyword switches.
+ * keyword is the constant keyword (must be lower case already),
+ * minchars is length of minimum legal abbreviation.
+ */
+
+GLOBAL(boolean)
+keymatch (char * arg, const char * keyword, int minchars)
+{
+ register int ca, ck;
+ register int nmatched = 0;
+
+ while ((ca = *arg++) != '\0') {
+ if ((ck = *keyword++) == '\0')
+ return FALSE; /* arg longer than keyword, no good */
+ if (isupper(ca)) /* force arg to lcase (assume ck is already) */
+ ca = tolower(ca);
+ if (ca != ck)
+ return FALSE; /* no good */
+ nmatched++; /* count matched characters */
+ }
+ /* reached end of argument; fail if it's too short for unique abbrev */
+ if (nmatched < minchars)
+ return FALSE;
+ return TRUE; /* A-OK */
+}
+
+
+/*
+ * Routines to establish binary I/O mode for stdin and stdout.
+ * Non-Unix systems often require some hacking to get out of text mode.
+ */
+
+GLOBAL(FILE *)
+read_stdin (void)
+{
+ FILE * input_file = stdin;
+
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdin), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
+ fprintf(stderr, "Cannot reopen stdin\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+ return input_file;
+}
+
+
+GLOBAL(FILE *)
+write_stdout (void)
+{
+ FILE * output_file = stdout;
+
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdout), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "Cannot reopen stdout\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+ return output_file;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.h
new file mode 100644
index 00000000..2b387b6e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/cdjpeg.h
@@ -0,0 +1,184 @@
+/*
+ * cdjpeg.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains common declarations for the sample applications
+ * cjpeg and djpeg. It is NOT used by the core JPEG library.
+ */
+
+#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
+#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h" /* get library error codes too */
+#include "cderror.h" /* get application-specific error codes */
+
+
+/*
+ * Object interface for cjpeg's source file decoding modules
+ */
+
+typedef struct cjpeg_source_struct * cjpeg_source_ptr;
+
+struct cjpeg_source_struct {
+ JMETHOD(void, start_input, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+ JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+ JMETHOD(void, finish_input, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+
+ FILE *input_file;
+
+ JSAMPARRAY buffer;
+ JDIMENSION buffer_height;
+};
+
+
+/*
+ * Object interface for djpeg's output file encoding modules
+ */
+
+typedef struct djpeg_dest_struct * djpeg_dest_ptr;
+
+struct djpeg_dest_struct {
+ /* start_output is called after jpeg_start_decompress finishes.
+ * The color map will be ready at this time, if one is needed.
+ */
+ JMETHOD(void, start_output, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo));
+ /* Emit the specified number of pixel rows from the buffer. */
+ JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied));
+ /* Finish up at the end of the image. */
+ JMETHOD(void, finish_output, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo));
+
+ /* Target file spec; filled in by djpeg.c after object is created. */
+ FILE * output_file;
+
+ /* Output pixel-row buffer. Created by module init or start_output.
+ * Width is cinfo->output_width * cinfo->output_components;
+ * height is buffer_height.
+ */
+ JSAMPARRAY buffer;
+ JDIMENSION buffer_height;
+};
+
+
+/*
+ * cjpeg/djpeg may need to perform extra passes to convert to or from
+ * the source/destination file format. The JPEG library does not know
+ * about these passes, but we'd like them to be counted by the progress
+ * monitor. We use an expanded progress monitor object to hold the
+ * additional pass count.
+ */
+
+struct cdjpeg_progress_mgr {
+ struct jpeg_progress_mgr pub; /* fields known to JPEG library */
+ int completed_extra_passes; /* extra passes completed */
+ int total_extra_passes; /* total extra */
+ /* last printed percentage stored here to avoid multiple printouts */
+ int percent_done;
+};
+
+typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_read_bmp jIRdBMP
+#define jinit_write_bmp jIWrBMP
+#define jinit_read_gif jIRdGIF
+#define jinit_write_gif jIWrGIF
+#define jinit_read_ppm jIRdPPM
+#define jinit_write_ppm jIWrPPM
+#define jinit_read_rle jIRdRLE
+#define jinit_write_rle jIWrRLE
+#define jinit_read_targa jIRdTarga
+#define jinit_write_targa jIWrTarga
+#define read_quant_tables RdQTables
+#define read_scan_script RdScnScript
+#define set_quant_slots SetQSlots
+#define set_sample_factors SetSFacts
+#define read_color_map RdCMap
+#define enable_signal_catcher EnSigCatcher
+#define start_progress_monitor StProgMon
+#define end_progress_monitor EnProgMon
+#define read_stdin RdStdin
+#define write_stdout WrStdout
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Module selection routines for I/O modules. */
+
+EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo,
+ boolean is_os2));
+EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo));
+
+/* cjpeg support routines (in rdswitch.c) */
+
+EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
+ int scale_factor, boolean force_baseline));
+EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
+EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
+EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));
+
+/* djpeg support routines (in rdcolmap.c) */
+
+EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* common support routines (in cdjpeg.c) */
+
+EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo));
+EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo,
+ cd_progress_ptr progress));
+EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo));
+EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars));
+EXTERN(FILE *) read_stdin JPP((void));
+EXTERN(FILE *) write_stdout JPP((void));
+
+/* miscellaneous useful macros */
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#else
+#ifdef VMS /* VMS is very nonstandard */
+#define READ_BINARY "rb", "ctx=stm"
+#define WRITE_BINARY "wb", "ctx=stm"
+#else /* standard ANSI-compliant case */
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#endif
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#ifdef VMS
+#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
+#else
+#define EXIT_SUCCESS 0
+#endif
+#endif
+#ifndef EXIT_WARNING
+#ifdef VMS
+#define EXIT_WARNING 1 /* VMS is very nonstandard */
+#else
+#define EXIT_WARNING 2
+#endif
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/cjpeg.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/cjpeg.cpp
new file mode 100644
index 00000000..5c7b63f3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/cjpeg.cpp
@@ -0,0 +1,630 @@
+/*
+ * cjpeg.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for the JPEG compressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ * cjpeg [options] inputfile outputfile
+ * cjpeg [options] [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program. Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes. Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ * To simplify script writing, the "-outfile" switch is provided. The syntax
+ * cjpeg [options] -outfile outputfile inputfile
+ * works regardless of which command line style is used.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+//#include "jversion.h" /* for version message */
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string) string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+ NULL
+};
+
+
+/*
+ * This routine determines what format the input file is,
+ * and selects the appropriate input-reading module.
+ *
+ * To determine which family of input formats the file belongs to,
+ * we may look only at the first byte of the file, since C does not
+ * guarantee that more than one character can be pushed back with ungetc.
+ * Looking at additional bytes would require one of these approaches:
+ * 1) assume we can fseek() the input file (fails for piped input);
+ * 2) assume we can push back more than one character (works in
+ * some C implementations, but unportable);
+ * 3) provide our own buffering (breaks input readers that want to use
+ * stdio directly, such as the RLE library);
+ * or 4) don't put back the data, and modify the input_init methods to assume
+ * they start reading after the start of file (also breaks RLE library).
+ * #1 is attractive for MS-DOS but is untenable on Unix.
+ *
+ * The most portable solution for file types that can't be identified by their
+ * first byte is to make the user tell us what they are. This is also the
+ * only approach for "raw" file types that contain only arbitrary values.
+ * We presently apply this method for Targa files. Most of the time Targa
+ * files start with 0x00, so we recognize that case. Potentially, however,
+ * a Targa file could start with any byte value (byte 0 is the length of the
+ * seldom-used ID field), so we provide a switch to force Targa input mode.
+ */
+
+static boolean is_targa; /* records user -targa switch */
+
+
+LOCAL(cjpeg_source_ptr)
+select_file_type (j_compress_ptr cinfo, FILE * infile)
+{
+ int c;
+
+ if (is_targa) {
+#ifdef TARGA_SUPPORTED
+ return jinit_read_targa(cinfo);
+#else
+ ERREXIT(cinfo, JERR_TGA_NOTCOMP);
+#endif
+ }
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ if (ungetc(c, infile) == EOF)
+ ERREXIT(cinfo, JERR_UNGETC_FAILED);
+
+ switch (c) {
+#ifdef BMP_SUPPORTED
+ case 'B':
+ return jinit_read_bmp(cinfo);
+#endif
+#ifdef GIF_SUPPORTED
+ case 'G':
+ return jinit_read_gif(cinfo);
+#endif
+#ifdef PPM_SUPPORTED
+ case 'P':
+ return jinit_read_ppm(cinfo);
+#endif
+#ifdef RLE_SUPPORTED
+ case 'R':
+ return jinit_read_rle(cinfo);
+#endif
+#ifdef TARGA_SUPPORTED
+ case 0x00:
+ return jinit_read_targa(cinfo);
+#endif
+ default:
+ ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
+ break;
+ }
+
+ return NULL; /* suppress compiler warnings */
+}
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ * The main program in this file doesn't actually use this capability...
+ */
+
+
+static const char * progname; /* program name for error messages */
+static char * outfilename; /* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -quality N Compression quality (0..100; 5-95 is useful range)\n");
+ fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
+#ifdef ENTROPY_OPT_SUPPORTED
+ fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
+#endif
+#ifdef C_PROGRESSIVE_SUPPORTED
+ fprintf(stderr, " -progressive Create progressive JPEG file\n");
+#endif
+#ifdef C_LOSSLESS_SUPPORTED
+ fprintf(stderr, " -lossless psv[,Pt] Create lossless JPEG file\n");
+#endif
+#ifdef TARGA_SUPPORTED
+ fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
+#endif
+ fprintf(stderr, "Switches for advanced users:\n");
+#ifdef DCT_ISLOW_SUPPORTED
+ fprintf(stderr, " -dct int Use integer DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
+ (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+ fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
+#endif
+ fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
+ fprintf(stderr, " -outfile name Specify name for output file\n");
+ fprintf(stderr, " -verbose or -debug Emit debug output\n");
+ fprintf(stderr, "Switches for wizards:\n");
+#ifdef C_ARITH_CODING_SUPPORTED
+ fprintf(stderr, " -arithmetic Use arithmetic coding\n");
+#endif
+ fprintf(stderr, " -baseline Force baseline quantization tables\n");
+ fprintf(stderr, " -qtables file Use quantization tables given in file\n");
+ fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
+ fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
+#endif
+ exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_compress_ptr cinfo, int argc, char **argv,
+ int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+ int argn;
+ char * arg;
+ int quality; /* -quality parameter */
+ int q_scale_factor; /* scaling percentage for -qtables */
+ boolean force_baseline;
+ boolean simple_progressive;
+ char * qtablefile = NULL; /* saves -qtables filename if any */
+ char * qslotsarg = NULL; /* saves -qslots parm if any */
+ char * samplearg = NULL; /* saves -sample parm if any */
+ char * scansarg = NULL; /* saves -scans parm if any */
+ char * losslsarg = NULL; /* saves -lossless parm if any */
+
+ /* Set up default JPEG parameters. */
+ /* Note that default -quality level need not, and does not,
+ * match the default scaling for an explicit -qtables argument.
+ */
+ quality = 75; /* default -quality value */
+ q_scale_factor = 100; /* default to no scaling for -qtables */
+ force_baseline = FALSE; /* by default, allow 16-bit quantizers */
+ simple_progressive = FALSE;
+ is_targa = FALSE;
+ outfilename = NULL;
+ cinfo->err->trace_level = 0;
+
+ /* Scan command line options, adjust parameters */
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Not a switch, must be a file name argument */
+ if (argn <= last_file_arg_seen) {
+ outfilename = NULL; /* -outfile applies to just one input file */
+ continue; /* ignore this name if previously processed */
+ }
+ break; /* else done parsing switches */
+ }
+ arg++; /* advance past switch marker character */
+
+ if (keymatch(arg, "arithmetic", 1)) {
+ /* Use arithmetic coding. */
+#ifdef C_ARITH_CODING_SUPPORTED
+ cinfo->arith_code = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "baseline", 1)) {
+ /* Force baseline-compatible output (8-bit quantizer values). */
+ force_baseline = TRUE;
+
+ } else if (keymatch(arg, "dct", 2)) {
+ /* Select DCT algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "int", 1)) {
+ cinfo->dct_method = JDCT_ISLOW;
+ } else if (keymatch(argv[argn], "fast", 2)) {
+ cinfo->dct_method = JDCT_IFAST;
+ } else if (keymatch(argv[argn], "float", 2)) {
+ cinfo->dct_method = JDCT_FLOAT;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+ /* Enable debug printouts. */
+ /* On first -d, print version identification */
+ static boolean printed_version = FALSE;
+
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+
+ } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+ /* Force a monochrome JPEG file to be generated. */
+ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+
+ } else if (keymatch(arg, "lossless", 1)) {
+/* Select simple lossless mode. */
+#ifdef C_LOSSLESS_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ losslsarg = argv[argn];
+ /* We must postpone execution until num_components is known. */
+#else
+ fprintf(stderr, "%s: sorry, lossless output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "maxmemory", 3)) {
+ /* Maximum memory in Kb (or Mb with 'm'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (ch == 'm' || ch == 'M')
+ lval *= 1000L;
+ cinfo->mem->max_memory_to_use = lval * 1000L;
+
+ } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
+ /* Enable entropy parm optimization. */
+#ifdef ENTROPY_OPT_SUPPORTED
+ cinfo->optimize_coding = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "outfile", 4)) {
+ /* Set output file name. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ outfilename = argv[argn]; /* save it away for later use */
+
+ } else if (keymatch(arg, "progressive", 1)) {
+ /* Select simple progressive mode. */
+#ifdef C_PROGRESSIVE_SUPPORTED
+ simple_progressive = TRUE;
+ /* We must postpone execution until num_components is known. */
+#else
+ fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "quality", 1)) {
+ /* Quality factor (quantization table scaling factor). */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d", &quality) != 1)
+ usage();
+ /* Change scale factor in case -qtables is present. */
+ q_scale_factor = jpeg_quality_scaling(quality);
+
+ } else if (keymatch(arg, "qslots", 2)) {
+ /* Quantization table slot numbers. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ qslotsarg = argv[argn];
+ /* Must delay setting qslots until after we have processed any
+ * colorspace-determining switches, since jpeg_set_colorspace sets
+ * default quant table numbers.
+ */
+
+ } else if (keymatch(arg, "qtables", 2)) {
+ /* Quantization tables fetched from file. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ qtablefile = argv[argn];
+ /* We postpone actually reading the file in case -quality comes later. */
+
+ } else if (keymatch(arg, "restart", 1)) {
+ /* Restart interval in MCU rows (or in MCUs with 'b'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (lval < 0 || lval > 65535L)
+ usage();
+ if (ch == 'b' || ch == 'B') {
+ cinfo->restart_interval = (unsigned int) lval;
+ cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
+ } else {
+ cinfo->restart_in_rows = (int) lval;
+ /* restart_interval will be computed during startup */
+ }
+
+ } else if (keymatch(arg, "sample", 2)) {
+ /* Set sampling factors. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ samplearg = argv[argn];
+ /* Must delay setting sample factors until after we have processed any
+ * colorspace-determining switches, since jpeg_set_colorspace sets
+ * default sampling factors.
+ */
+
+ } else if (keymatch(arg, "scans", 2)) {
+ /* Set scan script. */
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ scansarg = argv[argn];
+ /* We must postpone reading the file in case -progressive appears. */
+#else
+ fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "smooth", 2)) {
+ /* Set input smoothing factor. */
+ int val;
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d", &val) != 1)
+ usage();
+ if (val < 0 || val > 100)
+ usage();
+ cinfo->smoothing_factor = val;
+
+ } else if (keymatch(arg, "targa", 1)) {
+ /* Input file is Targa format. */
+ is_targa = TRUE;
+
+ } else {
+ usage(); /* bogus switch */
+ }
+ }
+
+ /* Post-switch-scanning cleanup */
+
+ if (for_real) {
+
+ /* Set quantization tables for selected quality. */
+ /* Some or all may be overridden if -qtables is present. */
+ jpeg_set_quality(cinfo, quality, force_baseline);
+
+ if (qtablefile != NULL) /* process -qtables if it was present */
+ if (! read_quant_tables(cinfo, qtablefile,
+ q_scale_factor, force_baseline))
+ usage();
+
+ if (qslotsarg != NULL) /* process -qslots if it was present */
+ if (! set_quant_slots(cinfo, qslotsarg))
+ usage();
+
+ if (samplearg != NULL) /* process -sample if it was present */
+ if (! set_sample_factors(cinfo, samplearg))
+ usage();
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+ if (simple_progressive) /* process -progressive; -scans can override */
+ jpeg_simple_progression(cinfo);
+#endif
+
+#ifdef C_LOSSLESS_SUPPORTED
+ if (losslsarg != NULL) /* process -lossless if it was present */
+ if (! set_simple_lossless(cinfo, losslsarg))
+ usage();
+#endif
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (scansarg != NULL) /* process -scans if it was present */
+ if (! read_scan_script(cinfo, scansarg))
+ usage();
+#endif
+ }
+
+ return argn; /* return index of next arg (file name) */
+}
+
+
+/*
+ * The main program.
+ */
+
+//int
+//main (int argc, char **argv)
+//{
+// struct jpeg_compress_struct cinfo;
+// struct jpeg_error_mgr jerr;
+//#ifdef PROGRESS_REPORT
+// struct cdjpeg_progress_mgr progress;
+//#endif
+// int file_index;
+// cjpeg_source_ptr src_mgr;
+// FILE * input_file;
+// FILE * output_file;
+// JDIMENSION num_scanlines;
+//
+// /* On Mac, fetch a command line. */
+//#ifdef USE_CCOMMAND
+// argc = ccommand(&argv);
+//#endif
+//
+// progname = argv[0];
+// if (progname == NULL || progname[0] == 0)
+// progname = "cjpeg"; /* in case C library doesn't provide it */
+//
+// /* Initialize the JPEG compression object with default error handling. */
+// cinfo.err = jpeg_std_error(&jerr);
+// jpeg_create_compress(&cinfo);
+// /* Add some application-specific error messages (from cderror.h) */
+// jerr.addon_message_table = cdjpeg_message_table;
+// jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+// jerr.last_addon_message = JMSG_LASTADDONCODE;
+//
+// /* Now safe to enable signal catcher. */
+//#ifdef NEED_SIGNAL_CATCHER
+// enable_signal_catcher((j_common_ptr) &cinfo);
+//#endif
+//
+// /* Initialize JPEG parameters.
+// * Much of this may be overridden later.
+// * In particular, we don't yet know the input file's color space,
+// * but we need to provide some value for jpeg_set_defaults() to work.
+// */
+//
+// cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
+// jpeg_set_defaults(&cinfo);
+//
+// /* Scan command line to find file names.
+// * It is convenient to use just one switch-parsing routine, but the switch
+// * values read here are ignored; we will rescan the switches after opening
+// * the input file.
+// */
+//
+// file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
+//
+//#ifdef TWO_FILE_COMMANDLINE
+// /* Must have either -outfile switch or explicit output file name */
+// if (outfilename == NULL) {
+// if (file_index != argc-2) {
+// fprintf(stderr, "%s: must name one input and one output file\n",
+// progname);
+// usage();
+// }
+// outfilename = argv[file_index+1];
+// } else {
+// if (file_index != argc-1) {
+// fprintf(stderr, "%s: must name one input and one output file\n",
+// progname);
+// usage();
+// }
+// }
+//#else
+// /* Unix style: expect zero or one file name */
+// if (file_index < argc-1) {
+// fprintf(stderr, "%s: only one input file\n", progname);
+// usage();
+// }
+//#endif /* TWO_FILE_COMMANDLINE */
+//
+// /* Open the input file. */
+// if (file_index < argc) {
+// if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
+// fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
+// exit(EXIT_FAILURE);
+// }
+// } else {
+// /* default input file is stdin */
+// input_file = read_stdin();
+// }
+//
+// /* Open the output file. */
+// if (outfilename != NULL) {
+// if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+// fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
+// exit(EXIT_FAILURE);
+// }
+// } else {
+// /* default output file is stdout */
+// output_file = write_stdout();
+// }
+//
+//#ifdef PROGRESS_REPORT
+// start_progress_monitor((j_common_ptr) &cinfo, &progress);
+//#endif
+//
+// /* Figure out the input file format, and set up to read it. */
+// src_mgr = select_file_type(&cinfo, input_file);
+// src_mgr->input_file = input_file;
+//
+// /* Read the input file header to obtain file size & colorspace. */
+// (*src_mgr->start_input) (&cinfo, src_mgr);
+//
+// /* Now that we know input colorspace, fix colorspace-dependent defaults */
+// jpeg_default_colorspace(&cinfo);
+//
+// /* Adjust default compression parameters by re-parsing the options */
+// file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
+//
+// /* Specify data destination for compression */
+// jpeg_stdio_dest(&cinfo, output_file);
+//
+// /* Start compressor */
+// jpeg_start_compress(&cinfo, TRUE);
+//
+// /* Process data */
+// while (cinfo.next_scanline < cinfo.image_height) {
+// num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
+// (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
+// }
+//
+// /* Finish compression and release memory */
+// (*src_mgr->finish_input) (&cinfo, src_mgr);
+// jpeg_finish_compress(&cinfo);
+// jpeg_destroy_compress(&cinfo);
+//
+// /* Close files, if we opened them */
+// if (input_file != stdin)
+// fclose(input_file);
+// if (output_file != stdout)
+// fclose(output_file);
+//
+//#ifdef PROGRESS_REPORT
+// end_progress_monitor((j_common_ptr) &cinfo);
+//#endif
+//
+// /* All done. */
+// exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
+// return 0; /* suppress no-return-value warnings */
+//}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/ckconfig.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/ckconfig.cpp
new file mode 100644
index 00000000..ce665f0f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/ckconfig.cpp
@@ -0,0 +1,403 @@
+/*
+ * ckconfig.c
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ */
+
+/*
+ * This program is intended to help you determine how to configure the JPEG
+ * software for installation on a particular system. The idea is to try to
+ * compile and execute this program. If your compiler fails to compile the
+ * program, make changes as indicated in the comments below. Once you can
+ * compile the program, run it, and it will produce a "jconfig.h" file for
+ * your system.
+ *
+ * As a general rule, each time you try to compile this program,
+ * pay attention only to the *first* error message you get from the compiler.
+ * Many C compilers will issue lots of spurious error messages once they
+ * have gotten confused. Go to the line indicated in the first error message,
+ * and read the comments preceding that line to see what to change.
+ *
+ * Almost all of the edits you may need to make to this program consist of
+ * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
+ * or vice versa. This is called defining or undefining that symbol.
+ */
+#include "stdafx.h"
+
+
+/* First we must see if your system has the include files we need.
+ * We start out with the assumption that your system has all the ANSI-standard
+ * include files. If you get any error trying to include one of these files,
+ * undefine the corresponding HAVE_xxx symbol.
+ */
+
+#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */
+#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */
+#include <stddef.h>
+#endif
+
+#define HAVE_STDLIB_H /* same thing for stdlib.h */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h> /* If you ain't got this, you ain't got C. */
+
+/* We have to see if your string functions are defined by
+ * strings.h (old BSD convention) or string.h (everybody else).
+ * We try the non-BSD convention first; define NEED_BSD_STRINGS
+ * if the compiler says it can't find string.h.
+ */
+
+#undef NEED_BSD_STRINGS
+
+#ifdef NEED_BSD_STRINGS
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+/* On some systems (especially older Unix machines), type size_t is
+ * defined only in the include file <sys/types.h>. If you get a failure
+ * on the size_t test below, try defining NEED_SYS_TYPES_H.
+ */
+
+#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+
+/* Usually type size_t is defined in one of the include files we've included
+ * above. If not, you'll get an error on the "typedef size_t my_size_t;" line.
+ * In that case, first try defining NEED_SYS_TYPES_H just above.
+ * If that doesn't work, you'll have to search through your system library
+ * to figure out which include file defines "size_t". Look for a line that
+ * says "typedef something-or-other size_t;". Then, change the line below
+ * that says "#include <someincludefile.h>" to instead include the file
+ * you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find
+ * type size_t anywhere, try replacing "#include <someincludefile.h>" with
+ * "typedef unsigned int size_t;".
+ */
+
+#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
+
+#ifdef NEED_SPECIAL_INCLUDE
+#include <someincludefile.h>
+#endif
+
+typedef size_t my_size_t; /* The payoff: do we have size_t now? */
+
+
+/* The next question is whether your compiler supports ANSI-style function
+ * prototypes. You need to know this in order to choose between using
+ * makefile.ansi and using makefile.unix.
+ * The #define line below is set to assume you have ANSI function prototypes.
+ * If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
+ */
+
+#define HAVE_PROTOTYPES
+
+#ifdef HAVE_PROTOTYPES
+int testfunction (int arg1, int * arg2); /* check prototypes */
+
+struct methods_struct { /* check method-pointer declarations */
+ int (*error_exit) (char *msgtext);
+ int (*trace_message) (char *msgtext);
+ int (*another_method) (void);
+};
+
+int testfunction (int arg1, int * arg2) /* check definitions */
+{
+ return arg2[arg1];
+}
+
+int test2function (void) /* check void arg list */
+{
+ return 0;
+}
+#endif
+
+
+/* Now we want to find out if your compiler knows what "unsigned char" means.
+ * If you get an error on the "unsigned char un_char;" line,
+ * then undefine HAVE_UNSIGNED_CHAR.
+ */
+
+#define HAVE_UNSIGNED_CHAR
+
+#ifdef HAVE_UNSIGNED_CHAR
+unsigned char un_char;
+#endif
+
+
+/* Now we want to find out if your compiler knows what "unsigned short" means.
+ * If you get an error on the "unsigned short un_short;" line,
+ * then undefine HAVE_UNSIGNED_SHORT.
+ */
+
+#define HAVE_UNSIGNED_SHORT
+
+#ifdef HAVE_UNSIGNED_SHORT
+unsigned short un_short;
+#endif
+
+
+/* Now we want to find out if your compiler understands type "void".
+ * If you get an error anywhere in here, undefine HAVE_VOID.
+ */
+
+#define HAVE_VOID
+
+#ifdef HAVE_VOID
+/* Caution: a C++ compiler will insist on complete prototypes */
+typedef void * void_ptr; /* check void * */
+#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
+typedef void (*void_func) (int a, int b);
+#else
+typedef void (*void_func) ();
+#endif
+
+#ifdef HAVE_PROTOTYPES /* check void function result */
+void test3function (void_ptr arg1, void_func arg2)
+#else
+void test3function (arg1, arg2)
+ void_ptr arg1;
+ void_func arg2;
+#endif
+{
+ char * locptr = (char *) arg1; /* check casting to and from void * */
+ arg1 = (void *) locptr;
+ (*arg2) (1, 2); /* check call of fcn returning void */
+}
+#endif
+
+
+/* Now we want to find out if your compiler knows what "const" means.
+ * If you get an error here, undefine HAVE_CONST.
+ */
+
+#define HAVE_CONST
+
+#ifdef HAVE_CONST
+static const int carray[3] = {1, 2, 3};
+
+#ifdef HAVE_PROTOTYPES
+int test4function (const int arg1)
+#else
+int test4function (arg1)
+ const int arg1;
+#endif
+{
+ return carray[arg1];
+}
+#endif
+
+
+/* If you get an error or warning about this structure definition,
+ * define INCOMPLETE_TYPES_BROKEN.
+ */
+
+#undef INCOMPLETE_TYPES_BROKEN
+
+#ifndef INCOMPLETE_TYPES_BROKEN
+typedef struct undefined_structure * undef_struct_ptr;
+#endif
+
+
+/* If you get an error about duplicate names,
+ * define NEED_SHORT_EXTERNAL_NAMES.
+ */
+
+#undef NEED_SHORT_EXTERNAL_NAMES
+
+#ifndef NEED_SHORT_EXTERNAL_NAMES
+
+int possibly_duplicate_function ()
+{
+ return 0;
+}
+
+int possibly_dupli_function ()
+{
+ return 1;
+}
+
+#endif
+
+
+
+/************************************************************************
+ * OK, that's it. You should not have to change anything beyond this
+ * point in order to compile and execute this program. (You might get
+ * some warnings, but you can ignore them.)
+ * When you run the program, it will make a couple more tests that it
+ * can do automatically, and then it will create jconfig.h and print out
+ * any additional suggestions it has.
+ ************************************************************************
+ */
+
+
+#ifdef HAVE_PROTOTYPES
+int is_char_signed (int arg)
+#else
+int is_char_signed (arg)
+ int arg;
+#endif
+{
+ if (arg == 189) { /* expected result for unsigned char */
+ return 0; /* type char is unsigned */
+ }
+ else if (arg != -67) { /* expected result for signed char */
+ printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
+ printf("I fear the JPEG software will not work at all.\n\n");
+ }
+ return 1; /* assume char is signed otherwise */
+}
+
+
+#ifdef HAVE_PROTOTYPES
+int is_shifting_signed (long arg)
+#else
+int is_shifting_signed (arg)
+ long arg;
+#endif
+/* See whether right-shift on a long is signed or not. */
+{
+ long res = arg >> 4;
+
+ if (res == -0x7F7E80CL) { /* expected result for signed shift */
+ return 1; /* right shift is signed */
+ }
+ /* see if unsigned-shift hack will fix it. */
+ /* we can't just test exact value since it depends on width of long... */
+ res |= (~0L) << (32-4);
+ if (res == -0x7F7E80CL) { /* expected result now? */
+ return 0; /* right shift is unsigned */
+ }
+ printf("Right shift isn't acting as I expect it to.\n");
+ printf("I fear the JPEG software will not work at all.\n\n");
+ return 0; /* try it with unsigned anyway */
+}
+
+
+//#ifdef HAVE_PROTOTYPES
+//int main (int argc, char ** argv)
+//#else
+//int main (argc, argv)
+// int argc;
+// char ** argv;
+//#endif
+//{
+// char signed_char_check = (char) (-67);
+// FILE *outfile;
+//
+// /* Attempt to write jconfig.h */
+// if ((outfile = fopen("jconfig.h", "w")) == NULL) {
+// printf("Failed to write jconfig.h\n");
+// return 1;
+// }
+//
+// /* Write out all the info */
+// fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
+// fprintf(outfile, "/* see jconfig.doc for explanations */\n\n");
+//#ifdef HAVE_PROTOTYPES
+// fprintf(outfile, "#define HAVE_PROTOTYPES\n");
+//#else
+// fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
+//#endif
+//#ifdef HAVE_UNSIGNED_CHAR
+// fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
+//#else
+// fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
+//#endif
+//#ifdef HAVE_UNSIGNED_SHORT
+// fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
+//#else
+// fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
+//#endif
+//#ifdef HAVE_VOID
+// fprintf(outfile, "/* #define void char */\n");
+//#else
+// fprintf(outfile, "#define void char\n");
+//#endif
+//#ifdef HAVE_CONST
+// fprintf(outfile, "/* #define const */\n");
+//#else
+// fprintf(outfile, "#define const\n");
+//#endif
+// if (is_char_signed((int) signed_char_check))
+// fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
+// else
+// fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
+//#ifdef HAVE_STDDEF_H
+// fprintf(outfile, "#define HAVE_STDDEF_H\n");
+//#else
+// fprintf(outfile, "#undef HAVE_STDDEF_H\n");
+//#endif
+//#ifdef HAVE_STDLIB_H
+// fprintf(outfile, "#define HAVE_STDLIB_H\n");
+//#else
+// fprintf(outfile, "#undef HAVE_STDLIB_H\n");
+//#endif
+//#ifdef NEED_BSD_STRINGS
+// fprintf(outfile, "#define NEED_BSD_STRINGS\n");
+//#else
+// fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
+//#endif
+//#ifdef NEED_SYS_TYPES_H
+// fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
+//#else
+// fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
+//#endif
+// fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
+//#ifdef NEED_SHORT_EXTERNAL_NAMES
+// fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
+//#else
+// fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
+//#endif
+//#ifdef INCOMPLETE_TYPES_BROKEN
+// fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
+//#else
+// fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
+//#endif
+// fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
+// if (is_shifting_signed(-0x7F7E80B1L))
+// fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
+// else
+// fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
+// fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
+// fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
+// fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n");
+// fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n");
+// fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n");
+// fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n");
+// fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n");
+// fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n");
+// fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n");
+// fprintf(outfile, "#undef DONT_USE_B_MODE\n");
+// fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n");
+// fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
+//
+// /* Close the jconfig.h file */
+// fclose(outfile);
+//
+// /* User report */
+// printf("Configuration check for Independent JPEG Group's software done.\n");
+// printf("\nI have written the jconfig.h file for you.\n\n");
+//#ifdef HAVE_PROTOTYPES
+// printf("You should use makefile.ansi as the starting point for your Makefile.\n");
+//#else
+// printf("You should use makefile.unix as the starting point for your Makefile.\n");
+//#endif
+//
+//#ifdef NEED_SPECIAL_INCLUDE
+// printf("\nYou'll need to change jconfig.h to include the system include file\n");
+// printf("that you found type size_t in, or add a direct definition of type\n");
+// printf("size_t if that's what you used. Just add it to the end.\n");
+//#endif
+//
+// return 0;
+//}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/djpeg.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/djpeg.cpp
new file mode 100644
index 00000000..b7b0dd76
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/djpeg.cpp
@@ -0,0 +1,616 @@
+/*
+ * djpeg.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for the JPEG decompressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ * djpeg [options] inputfile outputfile
+ * djpeg [options] [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program. Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes. Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ * To simplify script writing, the "-outfile" switch is provided. The syntax
+ * djpeg [options] -outfile outputfile inputfile
+ * works regardless of which command line style is used.
+ */
+#include "stdafx.h"
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+//#include "jversion.h" /* for version message */
+
+#include <ctype.h> /* to declare isprint() */
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string) string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+ NULL
+};
+
+
+/*
+ * This list defines the known output image formats
+ * (not all of which need be supported by a given version).
+ * You can change the default output format by defining DEFAULT_FMT;
+ * indeed, you had better do so if you undefine PPM_SUPPORTED.
+ */
+
+typedef enum {
+ FMT_BMP, /* BMP format (Windows flavor) */
+ FMT_GIF, /* GIF format */
+ FMT_OS2, /* BMP format (OS/2 flavor) */
+ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
+ FMT_RLE, /* RLE format */
+ FMT_TARGA, /* Targa format */
+ FMT_TIFF /* TIFF format */
+} IMAGE_FORMATS;
+
+#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
+#define DEFAULT_FMT FMT_PPM
+#endif
+
+static IMAGE_FORMATS requested_fmt;
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ * The main program in this file doesn't actually use this capability...
+ */
+
+
+static const char * progname; /* program name for error messages */
+static char * outfilename; /* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
+ fprintf(stderr, " -fast Fast, low-quality processing\n");
+ fprintf(stderr, " -grayscale Force grayscale output\n");
+#ifdef IDCT_SCALING_SUPPORTED
+ fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
+#endif
+#ifdef BMP_SUPPORTED
+ fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
+ (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
+#endif
+#ifdef GIF_SUPPORTED
+ fprintf(stderr, " -gif Select GIF output format%s\n",
+ (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
+#endif
+#ifdef BMP_SUPPORTED
+ fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
+ (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
+#endif
+#ifdef PPM_SUPPORTED
+ fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
+ (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
+#endif
+#ifdef RLE_SUPPORTED
+ fprintf(stderr, " -rle Select Utah RLE output format%s\n",
+ (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
+#endif
+#ifdef TARGA_SUPPORTED
+ fprintf(stderr, " -targa Select Targa output format%s\n",
+ (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
+#endif
+ fprintf(stderr, "Switches for advanced users:\n");
+#ifdef DCT_ISLOW_SUPPORTED
+ fprintf(stderr, " -dct int Use integer DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
+ (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+ fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
+ fprintf(stderr, " -dither none Don't use dithering in quantization\n");
+ fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
+#ifdef QUANT_2PASS_SUPPORTED
+ fprintf(stderr, " -map FILE Map to colors used in named image file\n");
+#endif
+ fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
+#ifdef QUANT_1PASS_SUPPORTED
+ fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
+#endif
+ fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
+ fprintf(stderr, " -outfile name Specify name for output file\n");
+ fprintf(stderr, " -verbose or -debug Emit debug output\n");
+ exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
+ int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+ int argn;
+ char * arg;
+
+ /* Set up default JPEG parameters. */
+ requested_fmt = DEFAULT_FMT; /* set default output file format */
+ outfilename = NULL;
+ cinfo->err->trace_level = 0;
+
+ /* Scan command line options, adjust parameters */
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Not a switch, must be a file name argument */
+ if (argn <= last_file_arg_seen) {
+ outfilename = NULL; /* -outfile applies to just one input file */
+ continue; /* ignore this name if previously processed */
+ }
+ break; /* else done parsing switches */
+ }
+ arg++; /* advance past switch marker character */
+
+ if (keymatch(arg, "bmp", 1)) {
+ /* BMP output format. */
+ requested_fmt = FMT_BMP;
+
+ } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
+ keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
+ /* Do color quantization. */
+ int val;
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d", &val) != 1)
+ usage();
+ cinfo->desired_number_of_colors = val;
+ cinfo->quantize_colors = TRUE;
+
+ } else if (keymatch(arg, "dct", 2)) {
+ /* Select IDCT algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "int", 1)) {
+ cinfo->dct_method = JDCT_ISLOW;
+ } else if (keymatch(argv[argn], "fast", 2)) {
+ cinfo->dct_method = JDCT_IFAST;
+ } else if (keymatch(argv[argn], "float", 2)) {
+ cinfo->dct_method = JDCT_FLOAT;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "dither", 2)) {
+ /* Select dithering algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "fs", 2)) {
+ cinfo->dither_mode = JDITHER_FS;
+ } else if (keymatch(argv[argn], "none", 2)) {
+ cinfo->dither_mode = JDITHER_NONE;
+ } else if (keymatch(argv[argn], "ordered", 2)) {
+ cinfo->dither_mode = JDITHER_ORDERED;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+ /* Enable debug printouts. */
+ /* On first -d, print version identification */
+ static boolean printed_version = FALSE;
+
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+
+ } else if (keymatch(arg, "fast", 1)) {
+ /* Select recommended processing options for quick-and-dirty output. */
+ cinfo->two_pass_quantize = FALSE;
+ cinfo->dither_mode = JDITHER_ORDERED;
+ if (! cinfo->quantize_colors) /* don't override an earlier -colors */
+ cinfo->desired_number_of_colors = 216;
+ cinfo->dct_method = JDCT_FASTEST;
+ cinfo->do_fancy_upsampling = FALSE;
+
+ } else if (keymatch(arg, "gif", 1)) {
+ /* GIF output format. */
+ requested_fmt = FMT_GIF;
+
+ } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+ /* Force monochrome output. */
+ cinfo->out_color_space = JCS_GRAYSCALE;
+
+ } else if (keymatch(arg, "map", 3)) {
+ /* Quantize to a color map taken from an input file. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (for_real) { /* too expensive to do twice! */
+#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
+ FILE * mapfile;
+
+ if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ read_color_map(cinfo, mapfile);
+ fclose(mapfile);
+ cinfo->quantize_colors = TRUE;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+
+ } else if (keymatch(arg, "maxmemory", 3)) {
+ /* Maximum memory in Kb (or Mb with 'm'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (ch == 'm' || ch == 'M')
+ lval *= 1000L;
+ cinfo->mem->max_memory_to_use = lval * 1000L;
+
+ } else if (keymatch(arg, "nosmooth", 3)) {
+ /* Suppress fancy upsampling */
+ cinfo->do_fancy_upsampling = FALSE;
+
+ } else if (keymatch(arg, "onepass", 3)) {
+ /* Use fast one-pass quantization. */
+ cinfo->two_pass_quantize = FALSE;
+
+ } else if (keymatch(arg, "os2", 3)) {
+ /* BMP output format (OS/2 flavor). */
+ requested_fmt = FMT_OS2;
+
+ } else if (keymatch(arg, "outfile", 4)) {
+ /* Set output file name. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ outfilename = argv[argn]; /* save it away for later use */
+
+ } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
+ /* PPM/PGM output format. */
+ requested_fmt = FMT_PPM;
+
+ } else if (keymatch(arg, "rle", 1)) {
+ /* RLE output format. */
+ requested_fmt = FMT_RLE;
+
+ } else if (keymatch(arg, "scale", 1)) {
+ /* Scale the output image by a fraction M/N. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d/%d",
+ &cinfo->scale_num, &cinfo->scale_denom) != 2)
+ usage();
+
+ } else if (keymatch(arg, "targa", 1)) {
+ /* Targa output format. */
+ requested_fmt = FMT_TARGA;
+
+ } else {
+ usage(); /* bogus switch */
+ }
+ }
+
+ return argn; /* return index of next arg (file name) */
+}
+
+
+/*
+ * Marker processor for COM and interesting APPn markers.
+ * This replaces the library's built-in processor, which just skips the marker.
+ * We want to print out the marker as text, to the extent possible.
+ * Note this code relies on a non-suspending data source.
+ */
+
+LOCAL(unsigned int)
+jpeg_getc (j_decompress_ptr cinfo)
+/* Read next byte */
+{
+ struct jpeg_source_mgr * datasrc = cinfo->src;
+
+ if (datasrc->bytes_in_buffer == 0) {
+ if (! (*datasrc->fill_input_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+ datasrc->bytes_in_buffer--;
+ return GETJOCTET(*datasrc->next_input_byte++);
+}
+
+
+METHODDEF(boolean)
+print_text_marker (j_decompress_ptr cinfo)
+{
+ boolean traceit = (cinfo->err->trace_level >= 1);
+ INT32 length;
+ unsigned int ch;
+ unsigned int lastch = 0;
+
+ length = jpeg_getc(cinfo) << 8;
+ length += jpeg_getc(cinfo);
+ length -= 2; /* discount the length word itself */
+
+ if (traceit) {
+ if (cinfo->unread_marker == JPEG_COM)
+ fprintf(stderr, "Comment, length %ld:\n", (long) length);
+ else /* assume it is an APPn otherwise */
+ fprintf(stderr, "APP%d, length %ld:\n",
+ cinfo->unread_marker - JPEG_APP0, (long) length);
+ }
+
+ while (--length >= 0) {
+ ch = jpeg_getc(cinfo);
+ if (traceit) {
+ /* Emit the character in a readable form.
+ * Nonprintables are converted to \nnn form,
+ * while \ is converted to \\.
+ * Newlines in CR, CR/LF, or LF form will be printed as one newline.
+ */
+ if (ch == '\r') {
+ fprintf(stderr, "\n");
+ } else if (ch == '\n') {
+ if (lastch != '\r')
+ fprintf(stderr, "\n");
+ } else if (ch == '\\') {
+ fprintf(stderr, "\\\\");
+ } else if (isprint(ch)) {
+ putc(ch, stderr);
+ } else {
+ fprintf(stderr, "\\%03o", ch);
+ }
+ lastch = ch;
+ }
+ }
+
+ if (traceit)
+ fprintf(stderr, "\n");
+
+ return TRUE;
+}
+
+
+///*
+// * The main program.
+// */
+//
+//int
+//main (int argc, char **argv)
+//{
+// struct jpeg_decompress_struct cinfo;
+// struct jpeg_error_mgr jerr;
+//#ifdef PROGRESS_REPORT
+// struct cdjpeg_progress_mgr progress;
+//#endif
+// int file_index;
+// djpeg_dest_ptr dest_mgr = NULL;
+// FILE * input_file;
+// FILE * output_file;
+// JDIMENSION num_scanlines;
+//
+// /* On Mac, fetch a command line. */
+//#ifdef USE_CCOMMAND
+// argc = ccommand(&argv);
+//#endif
+//
+// progname = argv[0];
+// if (progname == NULL || progname[0] == 0)
+// progname = "djpeg"; /* in case C library doesn't provide it */
+//
+// /* Initialize the JPEG decompression object with default error handling. */
+// cinfo.err = jpeg_std_error(&jerr);
+// jpeg_create_decompress(&cinfo);
+// /* Add some application-specific error messages (from cderror.h) */
+// jerr.addon_message_table = cdjpeg_message_table;
+// jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+// jerr.last_addon_message = JMSG_LASTADDONCODE;
+//
+// /* Insert custom marker processor for COM and APP12.
+// * APP12 is used by some digital camera makers for textual info,
+// * so we provide the ability to display it as text.
+// * If you like, additional APPn marker types can be selected for display,
+// * but don't try to override APP0 or APP14 this way (see libjpeg.doc).
+// */
+// jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
+// jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
+//
+// /* Now safe to enable signal catcher. */
+//#ifdef NEED_SIGNAL_CATCHER
+// enable_signal_catcher((j_common_ptr) &cinfo);
+//#endif
+//
+// /* Scan command line to find file names. */
+// /* It is convenient to use just one switch-parsing routine, but the switch
+// * values read here are ignored; we will rescan the switches after opening
+// * the input file.
+// * (Exception: tracing level set here controls verbosity for COM markers
+// * found during jpeg_read_header...)
+// */
+//
+// file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
+//
+//#ifdef TWO_FILE_COMMANDLINE
+// /* Must have either -outfile switch or explicit output file name */
+// if (outfilename == NULL) {
+// if (file_index != argc-2) {
+// fprintf(stderr, "%s: must name one input and one output file\n",
+// progname);
+// usage();
+// }
+// outfilename = argv[file_index+1];
+// } else {
+// if (file_index != argc-1) {
+// fprintf(stderr, "%s: must name one input and one output file\n",
+// progname);
+// usage();
+// }
+// }
+//#else
+// /* Unix style: expect zero or one file name */
+// if (file_index < argc-1) {
+// fprintf(stderr, "%s: only one input file\n", progname);
+// usage();
+// }
+//#endif /* TWO_FILE_COMMANDLINE */
+//
+// /* Open the input file. */
+// if (file_index < argc) {
+// if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
+// fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
+// exit(EXIT_FAILURE);
+// }
+// } else {
+// /* default input file is stdin */
+// input_file = read_stdin();
+// }
+//
+// /* Open the output file. */
+// if (outfilename != NULL) {
+// if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+// fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
+// exit(EXIT_FAILURE);
+// }
+// } else {
+// /* default output file is stdout */
+// output_file = write_stdout();
+// }
+//
+//#ifdef PROGRESS_REPORT
+// start_progress_monitor((j_common_ptr) &cinfo, &progress);
+//#endif
+//
+// /* Specify data source for decompression */
+// jpeg_stdio_src(&cinfo, input_file);
+//
+// /* Read file header, set default decompression parameters */
+// (void) jpeg_read_header(&cinfo, TRUE);
+//
+// /* Adjust default decompression parameters by re-parsing the options */
+// file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
+//
+// /* Initialize the output module now to let it override any crucial
+// * option settings (for instance, GIF wants to force color quantization).
+// */
+// switch (requested_fmt) {
+//#ifdef BMP_SUPPORTED
+// case FMT_BMP:
+// dest_mgr = jinit_write_bmp(&cinfo, FALSE);
+// break;
+// case FMT_OS2:
+// dest_mgr = jinit_write_bmp(&cinfo, TRUE);
+// break;
+//#endif
+//#ifdef GIF_SUPPORTED
+// case FMT_GIF:
+// dest_mgr = jinit_write_gif(&cinfo);
+// break;
+//#endif
+//#ifdef PPM_SUPPORTED
+// case FMT_PPM:
+// dest_mgr = jinit_write_ppm(&cinfo);
+// break;
+//#endif
+//#ifdef RLE_SUPPORTED
+// case FMT_RLE:
+// dest_mgr = jinit_write_rle(&cinfo);
+// break;
+//#endif
+//#ifdef TARGA_SUPPORTED
+// case FMT_TARGA:
+// dest_mgr = jinit_write_targa(&cinfo);
+// break;
+//#endif
+// default:
+// ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
+// break;
+// }
+// dest_mgr->output_file = output_file;
+//
+// /* Start decompressor */
+// (void) jpeg_start_decompress(&cinfo);
+//
+// /* Write output file header */
+// (*dest_mgr->start_output) (&cinfo, dest_mgr);
+//
+// /* Process data */
+// while (cinfo.output_scanline < cinfo.output_height) {
+// num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+// dest_mgr->buffer_height);
+// (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
+// }
+//
+//#ifdef PROGRESS_REPORT
+// /* Hack: count final pass as done in case finish_output does an extra pass.
+// * The library won't have updated completed_passes.
+// */
+// progress.pub.completed_passes = progress.pub.total_passes;
+//#endif
+//
+// /* Finish decompression and release memory.
+// * I must do it in this order because output module has allocated memory
+// * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
+// */
+// (*dest_mgr->finish_output) (&cinfo, dest_mgr);
+// (void) jpeg_finish_decompress(&cinfo);
+// jpeg_destroy_decompress(&cinfo);
+//
+// /* Close files, if we opened them */
+// if (input_file != stdin)
+// fclose(input_file);
+// if (output_file != stdout)
+// fclose(output_file);
+//
+//#ifdef PROGRESS_REPORT
+// end_progress_monitor((j_common_ptr) &cinfo);
+//#endif
+//
+// /* All done. */
+// exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
+// return 0; /* suppress no-return-value warnings */
+//}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapimin.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapimin.cpp
new file mode 100644
index 00000000..0c0f0e78
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapimin.cpp
@@ -0,0 +1,282 @@
+/*
+ * jcapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-compression case or the transcoding-only
+ * case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jcapistd.c. But also see jcparam.c for
+ * parameter-setup helper routines, jcomapi.c for routines shared by
+ * compression and decompression, and jctrans.c for the transcoding case.
+ */
+#include "stdafx.h"
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#define JPEG_INTERNALS
+
+
+
+/*
+ * Initialization of a JPEG compression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_compress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = FALSE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->dest = NULL;
+
+ cinfo->comp_info = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++)
+ cinfo->quant_tbl_ptrs[i] = NULL;
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ cinfo->script_space = NULL;
+
+ cinfo->input_gamma = 1.0; /* in case application forgets */
+
+ /* OK, I'm ready */
+ cinfo->global_state = CSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG compression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_compress (j_compress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG compression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_compress (j_compress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Forcibly suppress or un-suppress all quantization and Huffman tables.
+ * Marks all currently defined tables as already written (if suppress)
+ * or not written (if !suppress). This will control whether they get emitted
+ * by a subsequent jpeg_start_compress call.
+ *
+ * This routine is exported for use by applications that want to produce
+ * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
+ * since it is called by jpeg_start_compress, we put it here --- otherwise
+ * jcparam.o would be linked whether the application used it or not.
+ */
+
+GLOBAL(void)
+jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+{
+ int i;
+ JQUANT_TBL * qtbl;
+ JHUFF_TBL * htbl;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
+ qtbl->sent_table = suppress;
+ }
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ }
+}
+
+
+/*
+ * Finish JPEG compression.
+ *
+ * If a multipass operating mode was selected, this may do a great deal of
+ * work including most of the actual output.
+ */
+
+GLOBAL(void)
+jpeg_finish_compress (j_compress_ptr cinfo)
+{
+ JDIMENSION iMCU_row;
+
+ if (cinfo->global_state == CSTATE_SCANNING ||
+ cinfo->global_state == CSTATE_RAW_OK) {
+ /* Terminate first pass */
+ if (cinfo->next_scanline < cinfo->image_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_pass) (cinfo);
+ } else if (cinfo->global_state != CSTATE_WRCOEFS)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any remaining passes */
+ while (! cinfo->master->is_last_pass) {
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) iMCU_row;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* We bypass the main controller and invoke coef controller directly;
+ * all work is being done from the coefficient buffer.
+ */
+ if (! (*cinfo->codec->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+ (*cinfo->master->finish_pass) (cinfo);
+ }
+ /* Write EOI, do final cleanup */
+ (*cinfo->marker->write_file_trailer) (cinfo);
+ (*cinfo->dest->term_destination) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+}
+
+
+/*
+ * Write a special marker.
+ * This is only recommended for writing COM or APPn markers.
+ * Must be called after jpeg_start_compress() and before
+ * first call to jpeg_write_scanlines() or jpeg_write_raw_data().
+ */
+
+GLOBAL(void)
+jpeg_write_marker (j_compress_ptr cinfo, int marker,
+ const JOCTET *dataptr, unsigned int datalen)
+{
+ JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
+
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+ write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
+ while (datalen--) {
+ (*write_marker_byte) (cinfo, *dataptr);
+ dataptr++;
+ }
+}
+
+/* Same, but piecemeal. */
+
+GLOBAL(void)
+jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+{
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+}
+
+GLOBAL(void)
+jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+{
+ (*cinfo->marker->write_marker_byte) (cinfo, val);
+}
+
+
+/*
+ * Alternate compression function: just write an abbreviated table file.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * To produce a pair of files containing abbreviated tables and abbreviated
+ * image data, one would proceed as follows:
+ *
+ * initialize JPEG object
+ * set JPEG parameters
+ * set destination to table file
+ * jpeg_write_tables(cinfo);
+ * set destination to image file
+ * jpeg_start_compress(cinfo, FALSE);
+ * write data...
+ * jpeg_finish_compress(cinfo);
+ *
+ * jpeg_write_tables has the side effect of marking all tables written
+ * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
+ * will not re-emit the tables unless it is passed write_all_tables=TRUE.
+ */
+
+GLOBAL(void)
+jpeg_write_tables (j_compress_ptr cinfo)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Initialize the marker writer ... bit of a crock to do it here. */
+ jinit_marker_writer(cinfo);
+ /* Write them tables! */
+ (*cinfo->marker->write_tables_only) (cinfo);
+ /* And clean up. */
+ (*cinfo->dest->term_destination) (cinfo);
+ /*
+ * In library releases up through v6a, we called jpeg_abort() here to free
+ * any working memory allocated by the destination manager and marker
+ * writer. Some applications had a problem with that: they allocated space
+ * of their own from the library memory manager, and didn't want it to go
+ * away during write_tables. So now we do nothing. This will cause a
+ * memory leak if an app calls write_tables repeatedly without doing a full
+ * compression cycle or otherwise resetting the JPEG object. However, that
+ * seems less bad than unexpectedly freeing memory in the normal case.
+ * An app that prefers the old behavior can call jpeg_abort for itself after
+ * each call to jpeg_write_tables().
+ */
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapistd.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapistd.cpp
new file mode 100644
index 00000000..7bc31678
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcapistd.cpp
@@ -0,0 +1,163 @@
+/*
+ * jcapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-compression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_compress, it will end up linking in the entire compressor.
+ * We thus must separate this file from jcapimin.c to avoid linking the
+ * whole compression library into a transcoder.
+ */
+#include "stdafx.h"
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#define JPEG_INTERNALS
+
+
+
+/*
+ * Compression initialization.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * We require a write_all_tables parameter as a failsafe check when writing
+ * multiple datastreams from the same compression object. Since prior runs
+ * will have left all the tables marked sent_table=TRUE, a subsequent run
+ * would emit an abbreviated stream (no tables) by default. This may be what
+ * is wanted, but for safety's sake it should not be the default behavior:
+ * programmers should have to make a deliberate choice to emit abbreviated
+ * images. Therefore the documentation and examples should encourage people
+ * to pass write_all_tables=TRUE; then it will take active thought to do the
+ * wrong thing.
+ */
+
+GLOBAL(void)
+jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (write_all_tables)
+ jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ jinit_compress_master(cinfo);
+ /* Set up for the first pass */
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ /* Ready for application to drive first pass through jpeg_write_scanlines
+ * or jpeg_write_raw_data.
+ */
+ cinfo->next_scanline = 0;
+ cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
+}
+
+
+/*
+ * Write some scanlines of data to the JPEG compressor.
+ *
+ * The return value will be the number of lines actually written.
+ * This should be less than the supplied num_lines only in case that
+ * the data destination module has requested suspension of the compressor,
+ * or if more than image_height scanlines are passed in.
+ *
+ * Note: we warn about excess calls to jpeg_write_scanlines() since
+ * this likely signals an application programmer error. However,
+ * excess scanlines passed in the last valid call are *silently* ignored,
+ * so that the application need not adjust num_lines for end-of-image
+ * when using a multiple-scanline buffer.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION num_lines)
+{
+ JDIMENSION row_ctr, rows_left;
+
+ if (cinfo->global_state != CSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height)
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_scanlines. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_scanlines.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Ignore any extra scanlines at bottom of image. */
+ rows_left = cinfo->image_height - cinfo->next_scanline;
+ if (num_lines > rows_left)
+ num_lines = rows_left;
+
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
+ cinfo->next_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to write raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != CSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_raw_data. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_raw_data.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Verify that at least one iMCU row has been passed. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->data_unit;
+ if (num_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Directly compress the row. */
+ if (! (*cinfo->codec->compress_data) (cinfo, data)) {
+ /* If compressor did not consume the whole row, suspend processing. */
+ return 0;
+ }
+
+ /* OK, we processed one iMCU row. */
+ cinfo->next_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jccoefct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jccoefct.cpp
new file mode 100644
index 00000000..2f0ecbd8
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jccoefct.cpp
@@ -0,0 +1,456 @@
+/*
+ * jccoefct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for compression.
+ * This controller is the top level of the JPEG compressor proper.
+ * The coefficient buffer lies between forward-DCT and entropy encoding steps.
+ */
+#include "stdafx.h"
+
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+
+#define JPEG_INTERNALS
+
+
+/* We use a full-image coefficient buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files. In all cases, the DCT
+ * step is run during the first pass, and subsequent passes need only read
+ * the buffered coefficients.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* For single-pass compression, it's sufficient to buffer just one MCU
+ * (although this may prove a bit slow in practice). We allocate a
+ * workspace of C_MAX_DATA_UNITS_IN_MCU coefficient blocks, and reuse it for
+ * each MCU constructed and sent. (On 80x86, the workspace is FAR even
+ * though it's not really very big; this is to keep the module interfaces
+ * unchanged when a large coefficient buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays.
+ */
+ JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
+
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+} c_coef_controller;
+
+typedef c_coef_controller * c_coef_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (coef->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ lossyc->pub.compress_data = compress_data;
+ break;
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ lossyc->pub.compress_data = compress_first_pass;
+ break;
+ case JBUF_CRANK_DEST:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ lossyc->pub.compress_data = compress_output;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, bi, ci, yindex, yoffset, blockcnt;
+ JDIMENSION ypos, xpos;
+ jpeg_component_info *compptr;
+
+ /* Loop to write as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Determine where data comes from in input_buf and do the DCT thing.
+ * Each call on forward_DCT processes a horizontal row of DCT blocks
+ * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
+ * sequentially. Dummy blocks at the right or bottom edge are filled in
+ * specially. The data in them does not matter for image reconstruction,
+ * so we fill them with values that will encode to the smallest amount of
+ * data, viz: all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. (Thanks to Thomas Kinsman for this idea.)
+ */
+ blkn = 0;
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ xpos = MCU_col_num * compptr->MCU_sample_width;
+ ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ (*lossyc->fdct_forward_DCT) (cinfo, compptr,
+ input_buf[compptr->component_index],
+ coef->MCU_buffer[blkn],
+ ypos, xpos, (JDIMENSION) blockcnt);
+ if (blockcnt < compptr->MCU_width) {
+ /* Create some dummy blocks at the right edge of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
+ (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
+ for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+ }
+ }
+ } else {
+ /* Create a row of dummy blocks at the bottom of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn],
+ compptr->MCU_width * SIZEOF(JBLOCK));
+ for (bi = 0; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+ }
+ }
+ blkn += compptr->MCU_width;
+ ypos += DCTSIZE;
+ }
+ }
+ /* Try to write the MCU. In event of a suspension failure, we will
+ * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
+ */
+ if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * This amount of data is read from the source buffer, DCT'd and quantized,
+ * and saved into the virtual arrays. We also generate suitable dummy blocks
+ * as needed at the right and lower edges. (The dummy blocks are constructed
+ * in the virtual arrays, which have been padded appropriately.) This makes
+ * it possible for subsequent passes not to worry about real vs. dummy blocks.
+ *
+ * We must also emit the data to the entropy encoder. This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image. All
+ * components are DCT'd and loaded into the virtual arrays in this pass.
+ * However, it may be that only a subset of the components are emitted to
+ * the entropy encoder during this first pass; be careful about looking
+ * at the scan-dependent variables (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION blocks_across, MCUs_across, MCUindex;
+ int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
+ JCOEF lastDC;
+ jpeg_component_info *compptr;
+ JBLOCKARRAY buffer;
+ JBLOCKROW thisblockrow, lastblockrow;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (coef->iMCU_row_num < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here, since may not be set! */
+ block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ blocks_across = compptr->width_in_data_units;
+ h_samp_factor = compptr->h_samp_factor;
+ /* Count number of dummy blocks to be added at the right margin. */
+ ndummy = (int) (blocks_across % h_samp_factor);
+ if (ndummy > 0)
+ ndummy = h_samp_factor - ndummy;
+ /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
+ * on forward_DCT processes a complete horizontal row of DCT blocks.
+ */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ thisblockrow = buffer[block_row];
+ (*lossyc->fdct_forward_DCT) (cinfo, compptr,
+ input_buf[ci], thisblockrow,
+ (JDIMENSION) (block_row * DCTSIZE),
+ (JDIMENSION) 0, blocks_across);
+ if (ndummy > 0) {
+ /* Create dummy blocks at the right edge of the image. */
+ thisblockrow += blocks_across; /* => first dummy block */
+ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
+ lastDC = thisblockrow[-1][0];
+ for (bi = 0; bi < ndummy; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ }
+ }
+ /* If at end of image, create dummy block rows as needed.
+ * The tricky part here is that within each MCU, we want the DC values
+ * of the dummy blocks to match the last real block's DC value.
+ * This squeezes a few more bytes out of the resulting file...
+ */
+ if (coef->iMCU_row_num == last_iMCU_row) {
+ blocks_across += ndummy; /* include lower right corner */
+ MCUs_across = blocks_across / h_samp_factor;
+ for (block_row = block_rows; block_row < compptr->v_samp_factor;
+ block_row++) {
+ thisblockrow = buffer[block_row];
+ lastblockrow = buffer[block_row-1];
+ jzero_far((void FAR *) thisblockrow,
+ (size_t) (blocks_across * SIZEOF(JBLOCK)));
+ for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
+ lastDC = lastblockrow[h_samp_factor-1][0];
+ for (bi = 0; bi < h_samp_factor; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ thisblockrow += h_samp_factor; /* advance to next MCU in row */
+ lastblockrow += h_samp_factor;
+ }
+ }
+ }
+ }
+ /* NB: compress_output will increment iMCU_row_num if successful.
+ * A suspension return will result in redoing all the work above next time.
+ */
+
+ /* Emit data to the entropy encoder, sharing code with subsequent passes */
+ return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan.
+ * NB: during first pass, this is safe only because the buffers will
+ * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*lossyc->entropy_encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+#endif /* FULL_COEF_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef;
+
+ coef = (c_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_coef_controller));
+ lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
+ lossyc->coef_start_pass = start_pass_coef;
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ int ci;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ coef->whole_image[0] = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jccolor.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jccolor.cpp
new file mode 100644
index 00000000..59630c08
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jccolor.cpp
@@ -0,0 +1,460 @@
+/*
+ * jccolor.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input colorspace conversion routines.
+ */
+#include "stdafx.h"
+
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#define JPEG_INTERNALS
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_converter pub; /* public fields */
+
+ /* Private state for RGB->YCC conversion */
+ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
+} my_color_converter;
+
+typedef my_color_converter * my_cconvert_ptr;
+
+
+/**************** RGB -> YCbCr conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
+ * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
+ * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
+ * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
+ * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
+ * were not represented exactly. Now we sacrifice exact representation of
+ * maximum red and maximum blue in order to get exact grayscales.
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times R,G,B for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
+ * in the tables to save adding them separately in the inner loop.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX_JCCOLOR(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+/* We allocate one big table and divide it up into eight parts, instead of
+ * doing eight alloc_small requests. This lets us use a single table base
+ * address, which can be held in a register in the inner loops on many
+ * machines (more than can hold all eight addresses, anyway).
+ */
+
+#define R_Y_OFF 0 /* offset to R => Y section */
+#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
+#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
+#define R_CB_OFF (3*(MAXJSAMPLE+1))
+#define G_CB_OFF (4*(MAXJSAMPLE+1))
+#define B_CB_OFF (5*(MAXJSAMPLE+1))
+#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
+#define G_CR_OFF (6*(MAXJSAMPLE+1))
+#define B_CR_OFF (7*(MAXJSAMPLE+1))
+#define TABLE_SIZE (8*(MAXJSAMPLE+1))
+
+
+/*
+ * Initialize for RGB->YCC colorspace conversion.
+ */
+
+METHODDEF(void)
+rgb_ycc_start (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ INT32 * rgb_ycc_tab;
+ INT32 i;
+
+ /* Allocate and fill in the conversion tables. */
+ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (TABLE_SIZE * SIZEOF(INT32)));
+
+ for (i = 0; i <= MAXJSAMPLE; i++) {
+ rgb_ycc_tab[i+R_Y_OFF] = FIX_JCCOLOR(0.29900) * i;
+ rgb_ycc_tab[i+G_Y_OFF] = FIX_JCCOLOR(0.58700) * i;
+ rgb_ycc_tab[i+B_Y_OFF] = FIX_JCCOLOR(0.11400) * i + ONE_HALF;
+ rgb_ycc_tab[i+R_CB_OFF] = (-FIX_JCCOLOR(0.16874)) * i;
+ rgb_ycc_tab[i+G_CB_OFF] = (-FIX_JCCOLOR(0.33126)) * i;
+ /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
+ * This ensures that the maximum output will round to MAXJSAMPLE
+ * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
+ */
+ rgb_ycc_tab[i+B_CB_OFF] = FIX_JCCOLOR(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+/* B=>Cb and R=>Cr tables are the same
+ rgb_ycc_tab[i+R_CR_OFF] = FIX_JCCOLOR(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+*/
+ rgb_ycc_tab[i+G_CR_OFF] = (-FIX_JCCOLOR(0.41869)) * i;
+ rgb_ycc_tab[i+B_CR_OFF] = (-FIX_JCCOLOR(0.08131)) * i;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ *
+ * Note that we change from the application's interleaved-pixel format
+ * to our internal noninterleaved, one-plane-per-component format.
+ * The input buffer is therefore three times as wide as the output buffer.
+ *
+ * A starting row offset is provided only for the output buffer. The caller
+ * can easily adjust the passed input_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+rgb_ycc_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/**************** Cases other than RGB -> YCbCr **************/
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles RGB->grayscale conversion, which is the same
+ * as the RGB->Y portion of RGB->YCbCr.
+ * We assume rgb_ycc_start has been called (we only use the Y tables).
+ */
+
+METHODDEF(void)
+rgb_gray_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* Y */
+ outptr[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles Adobe-style CMYK->YCCK conversion,
+ * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume rgb_ycc_start has been called.
+ */
+
+METHODDEF(void)
+cmyk_ycck_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2, outptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ outptr3 = output_buf[3][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
+ g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
+ b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
+ /* K passes through as-is */
+ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
+ inptr += 4;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles grayscale output with no conversion.
+ * The source can be either plain grayscale or YCbCr (since Y == gray).
+ */
+
+METHODDEF(void)
+grayscale_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+ int instride = cinfo->input_components;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
+ inptr += instride;
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles multi-component colorspaces without conversion.
+ * We assume input_components == num_components.
+ */
+
+METHODDEF(void)
+null_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ register int ci;
+ int nc = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ /* It seems fastest to make a separate pass for each component. */
+ for (ci = 0; ci < nc; ci++) {
+ inptr = *input_buf;
+ outptr = output_buf[ci][output_row];
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
+ inptr += nc;
+ }
+ }
+ input_buf++;
+ output_row++;
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+null_method (j_compress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for input colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_converter (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_converter));
+ cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+ /* set start_pass to null method until we find out differently */
+ cconvert->pub.start_pass = null_method;
+
+ /* Make sure input_components agrees with in_color_space */
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->input_components != 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ if (cinfo->input_components != RGB_PIXELSIZE)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+#endif /* else share code with YCbCr */
+
+ case JCS_YCbCr:
+ if (cinfo->input_components != 3)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->input_components != 4)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->input_components < 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+ }
+
+ /* Check num_components, set conversion method based on requested space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_GRAYSCALE)
+ cconvert->pub.color_convert = grayscale_convert;
+ else if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_gray_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = grayscale_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_ycc_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = cmyk_ycck_convert;
+ } else if (cinfo->in_color_space == JCS_YCCK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default: /* allow null conversion of JCS_UNKNOWN */
+ if (cinfo->jpeg_color_space != cinfo->in_color_space ||
+ cinfo->num_components != cinfo->input_components)
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ cconvert->pub.color_convert = null_convert;
+ break;
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdctmgr.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdctmgr.cpp
new file mode 100644
index 00000000..e0956e6f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdctmgr.cpp
@@ -0,0 +1,391 @@
+/*
+ * jcdctmgr.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the forward-DCT management logic.
+ * This code selects a particular DCT implementation to be used,
+ * and it performs related housekeeping chores including coefficient
+ * quantization.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ /* Pointer to the DCT routine actually in use */
+ forward_DCT_method_ptr do_dct;
+
+ /* The actual post-DCT divisors --- not identical to the quant table
+ * entries, because of scaling (especially for an unnormalized DCT).
+ * Each table is given in normal array order.
+ */
+ DCTELEM * divisors[NUM_QUANT_TBLS];
+
+#ifdef DCT_FLOAT_SUPPORTED
+ /* Same as above for the floating-point case. */
+ float_DCT_method_ptr do_float_dct;
+ FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
+#endif
+} fdct_controller;
+
+typedef fdct_controller * fdct_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ * Verify that all referenced Q-tables are present, and set up
+ * the divisor table for each one.
+ * In the current implementation, DCT of all components is done during
+ * the first pass, even if only some components will be output in the
+ * first scan. Hence all components should be examined here.
+ */
+
+METHODDEF(void)
+start_pass_fdctmgr (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+ int ci, qtblno, i;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtbl;
+ DCTELEM * dtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ qtblno = compptr->quant_tbl_no;
+ /* Make sure specified quantization table is present */
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ qtbl = cinfo->quant_tbl_ptrs[qtblno];
+ /* Compute divisors for this quant table */
+ /* We may do this more than once for same table, but it's not a big deal */
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ /* For LL&M IDCT method, divisors are equal to raw quantization
+ * coefficients multiplied by 8 (to counteract scaling).
+ */
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ }
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ */
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = (DCTELEM)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-3);
+ }
+ }
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ * What's actually stored is 1/divisor so that the inner loop can
+ * use a multiplication rather than a division.
+ */
+ FAST_FLOAT * fdtbl;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ if (fdct->float_divisors[qtblno] == NULL) {
+ fdct->float_divisors[qtblno] = (FAST_FLOAT *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(FAST_FLOAT));
+ }
+ fdtbl = fdct->float_divisors[qtblno];
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fdtbl[i] = (FAST_FLOAT)
+ (1.0 / (((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col] * 8.0)));
+ i++;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Perform forward DCT on one or more blocks of a component.
+ *
+ * The input samples are taken from the sample_data[] array starting at
+ * position start_row/start_col, and moving to the right for any additional
+ * blocks. The quantized coefficients are returned in coef_blocks[].
+ */
+
+METHODDEF(void)
+forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for integer DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+ forward_DCT_method_ptr do_dct = fdct->do_dct;
+ DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
+ DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+ /* Load data into workspace, applying unsigned->signed conversion */
+ { register DCTELEM *workspaceptr;
+ register JSAMPROW elemptr;
+ register int elemr;
+
+ workspaceptr = workspace;
+ for (elemr = 0; elemr < DCTSIZE; elemr++) {
+ elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8 /* unroll the inner loop */
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+#else
+ { register int elemc;
+ for (elemc = DCTSIZE; elemc > 0; elemc--) {
+ *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE;
+ }
+ }
+#endif
+ }
+ }
+
+ /* Perform the DCT */
+ (*do_dct) (workspace);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register DCTELEM temp, qval;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ qval = divisors[i];
+ temp = workspace[i];
+ /* Divide the coefficient value by qval, ensuring proper rounding.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ *
+ * In most files, at least half of the output values will be zero
+ * (at default quantization settings, more like three-quarters...)
+ * so we should ensure that this case is fast. On many machines,
+ * a comparison is enough cheaper than a divide to make a special test
+ * a win. Since both inputs will be nonnegative, we need only test
+ * for a < b to discover whether a/b is 0.
+ * If your machine's division is fast enough, define FAST_DIVIDE.
+ */
+#ifdef FAST_DIVIDE
+#define DIVIDE_BY(a,b) a /= b
+#else
+#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
+#endif
+ if (temp < 0) {
+ temp = -temp;
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ temp = -temp;
+ } else {
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ }
+ output_ptr[i] = (JCOEF) temp;
+ }
+ }
+ }
+}
+
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+METHODDEF(void)
+forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for floating-point DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ fdct_ptr fdct = (fdct_ptr) lossyc->fdct_private;
+ float_DCT_method_ptr do_dct = fdct->do_float_dct;
+ FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
+ FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
+ /* Load data into workspace, applying unsigned->signed conversion */
+ { register FAST_FLOAT *workspaceptr;
+ register JSAMPROW elemptr;
+ register int elemr;
+
+ workspaceptr = workspace;
+ for (elemr = 0; elemr < DCTSIZE; elemr++) {
+ elemptr = sample_data[elemr] + start_col;
+#if DCTSIZE == 8 /* unroll the inner loop */
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ *workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+#else
+ { register int elemc;
+ for (elemc = DCTSIZE; elemc > 0; elemc--) {
+ *workspaceptr++ = (FAST_FLOAT)
+ (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE);
+ }
+ }
+#endif
+ }
+ }
+
+ /* Perform the DCT */
+ (*do_dct) (workspace);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register FAST_FLOAT temp;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* Apply the quantization and scaling factor */
+ temp = workspace[i] * divisors[i];
+ /* Round to nearest integer.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ * The maximum coefficient size is +-16K (for 12-bit data), so this
+ * code should work for either 16-bit or 32-bit ints.
+ */
+ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+ }
+ }
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
+
+
+/*
+ * Initialize FDCT manager.
+ */
+
+GLOBAL(void)
+jinit_forward_dct (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ fdct_ptr fdct;
+ int i;
+
+ fdct = (fdct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(fdct_controller));
+ lossyc->fdct_private = (struct jpeg_forward_dct *) fdct;
+ lossyc->fdct_start_pass = start_pass_fdctmgr;
+
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ lossyc->fdct_forward_DCT = forward_DCT;
+ fdct->do_dct = jpeg_fdct_islow;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ lossyc->fdct_forward_DCT = forward_DCT;
+ fdct->do_dct = jpeg_fdct_ifast;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ lossyc->fdct_forward_DCT = forward_DCT_float;
+ fdct->do_float_dct = jpeg_fdct_float;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+
+ /* Mark divisor tables unallocated */
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ fdct->divisors[i] = NULL;
+#ifdef DCT_FLOAT_SUPPORTED
+ fdct->float_divisors[i] = NULL;
+#endif
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.cpp
new file mode 100644
index 00000000..2acfb063
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.cpp
@@ -0,0 +1,410 @@
+/*
+ * jcdiffct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the difference buffer controller for compression.
+ * This controller is the top level of the lossless JPEG compressor proper.
+ * The difference buffer lies between prediction/differencing and entropy
+ * encoding.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/* We use a full-image sample buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files. In all cases, the
+ * full-image buffer is filled during the first pass, and the scaling,
+ * prediction and differencing steps are run during subsequent passes.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_SAMP_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_SAMP_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ JSAMPROW cur_row[MAX_COMPONENTS]; /* row of point transformed samples */
+ JSAMPROW prev_row[MAX_COMPONENTS]; /* previous row of Pt'd samples */
+ JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */
+
+ /* In multi-pass modes, we need a virtual sample array for each component. */
+ jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+} c_diff_controller;
+
+typedef c_diff_controller * c_diff_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ diff->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (diff->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ diff->mcu_ctr = 0;
+ diff->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_diff (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+
+ diff->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (diff->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ losslsc->pub.compress_data = compress_data;
+ break;
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ if (diff->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ losslsc->pub.compress_data = compress_first_pass;
+ break;
+ case JBUF_CRANK_DEST:
+ if (diff->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ losslsc->pub.compress_data = compress_output;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+#define SWAP_ROWS(rowa,rowb) {JSAMPROW temp; temp=rowa; rowa=rowb; rowb=temp;}
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION MCU_count; /* number of MCUs encoded */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int comp, ci, yoffset, samp_row, samp_rows, samps_across;
+ jpeg_component_info *compptr;
+
+ /* Loop to write as much as one whole iMCU row */
+ for (yoffset = diff->MCU_vert_offset; yoffset < diff->MCU_rows_per_iMCU_row;
+ yoffset++) {
+
+ MCU_col_num = diff->mcu_ctr;
+
+ /* Scale and predict each scanline of the MCU-row separately.
+ *
+ * Note: We only do this if we are at the start of a MCU-row, ie,
+ * we don't want to reprocess a row suspended by the output.
+ */
+ if (MCU_col_num == 0) {
+ for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+ compptr = cinfo->cur_comp_info[comp];
+ ci = compptr->component_index;
+ if (diff->iMCU_row_num < last_iMCU_row)
+ samp_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here, since may not be set! */
+ samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+ else {
+ /* Fill dummy difference rows at the bottom edge with zeros, which
+ * will encode to the smallest amount of data.
+ */
+ for (samp_row = samp_rows; samp_row < compptr->v_samp_factor;
+ samp_row++)
+ MEMZERO(diff->diff_buf[ci][samp_row],
+ jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
+ }
+ }
+ samps_across = compptr->width_in_data_units;
+
+ for (samp_row = 0; samp_row < samp_rows; samp_row++) {
+ (*losslsc->scaler_scale) (cinfo,
+ input_buf[ci][samp_row],
+ diff->cur_row[ci], samps_across);
+ (*losslsc->predict_difference[ci]) (cinfo, ci,
+ diff->cur_row[ci],
+ diff->prev_row[ci],
+ diff->diff_buf[ci][samp_row],
+ samps_across);
+ SWAP_ROWS(diff->cur_row[ci], diff->prev_row[ci]);
+ }
+ }
+ }
+
+ /* Try to write the MCU-row (or remaining portion of suspended MCU-row). */
+ MCU_count =
+ (*losslsc->entropy_encode_mcus) (cinfo,
+ diff->diff_buf, yoffset, MCU_col_num,
+ cinfo->MCUs_per_row - MCU_col_num);
+ if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
+ /* Suspension forced; update state counters and exit */
+ diff->MCU_vert_offset = yoffset;
+ diff->mcu_ctr += MCU_col_num;
+ return FALSE;
+ }
+
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ diff->mcu_ctr = 0;
+ }
+
+ /* Completed the iMCU row, advance counters for next one */
+ diff->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the image.
+ * This amount of data is read from the source buffer and saved into the
+ * virtual arrays.
+ *
+ * We must also emit the data to the compressor. This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image. All components
+ * are loaded into the virtual arrays in this pass. However, it may be that
+ * only a subset of the components are emitted to the compressor during
+ * this first pass; be careful about looking at the scan-dependent variables
+ * (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION samps_across;
+ int ci, samp_row, samp_rows;
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Align the virtual buffers for this component. */
+ buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, diff->whole_image[ci],
+ diff->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+
+ /* Count non-dummy sample rows in this iMCU row. */
+ if (diff->iMCU_row_num < last_iMCU_row)
+ samp_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here, since may not be set! */
+ samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+ }
+ samps_across = compptr->width_in_data_units;
+
+ /* Perform point transform scaling and prediction/differencing for all
+ * non-dummy rows in this iMCU row. Each call on these functions
+ * process a complete row of samples.
+ */
+ for (samp_row = 0; samp_row < samp_rows; samp_row++) {
+ MEMCOPY(buffer[ci][samp_row], input_buf[ci][samp_row],
+ samps_across * SIZEOF(JSAMPLE));
+ }
+ }
+
+ /* NB: compress_output will increment iMCU_row_num if successful.
+ * A suspension return will result in redoing all the work above next time.
+ */
+
+ /* Emit data to the compressor, sharing code with subsequent passes */
+ return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the compressor.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff = (c_diff_ptr) losslsc->diff_private;
+ //JDIMENSION MCU_col_num; /* index of current MCU within row */
+ //JDIMENSION MCU_count; /* number of MCUs encoded */
+ int comp, ci; //, yoffset;
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan.
+ * NB: during first pass, this is safe only because the buffers will
+ * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+ */
+ for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+ compptr = cinfo->cur_comp_info[comp];
+ ci = compptr->component_index;
+ buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, diff->whole_image[ci],
+ diff->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ return compress_data(cinfo, buffer);
+}
+
+#endif /* FULL_SAMP_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize difference buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_diff_ptr diff;
+ int ci, row;
+ jpeg_component_info *compptr;
+
+ diff = (c_diff_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_diff_controller));
+ losslsc->diff_private = (void *) diff;
+ losslsc->diff_start_pass = start_pass_diff;
+
+ /* Create the prediction row buffers. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ diff->cur_row[ci] = *(*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) 1);
+ diff->prev_row[ci] = *(*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) 1);
+ }
+
+ /* Create the difference buffer. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ /* Prefill difference rows with zeros. We do this because only actual
+ * data is placed in the buffers during prediction/differencing, leaving
+ * any dummy differences at the right edge as zeros, which will encode
+ * to the smallest amount of data.
+ */
+ for (row = 0; row < compptr->v_samp_factor; row++)
+ MEMZERO(diff->diff_buf[ci][row],
+ jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor) * SIZEOF(JDIFF));
+ }
+
+ /* Create the sample buffer. */
+ if (need_full_buffer) {
+#ifdef FULL_SAMP_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor differences in each direction. */
+ int ci;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else
+ diff->whole_image[0] = NULL; /* flag for no virtual arrays */
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.h
new file mode 100644
index 00000000..4e98071e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcdiffct.h
@@ -0,0 +1 @@
+GLOBAL(void) jinit_c_diff_controller (j_compress_ptr cinfo, boolean need_full_buffer); \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.cpp
new file mode 100644
index 00000000..ae862ca9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.cpp
@@ -0,0 +1,274 @@
+/*
+ * jchuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines which are shared
+ * by the sequential, progressive and lossless decoders.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jchuff.h" /* Declarations shared with jc*huff.c */
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+GLOBAL(void)
+jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ c_derived_tbl *dtbl;
+ int p, i, l, lastp, si, maxsymbol;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (c_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_derived_tbl));
+ dtbl = *pdtbl;
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ lastp = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure C.3: generate encoding tables */
+ /* These are code and size indexed by symbol value */
+
+ /* Set all codeless symbols to have code length 0;
+ * this lets us detect duplicate VAL entries here, and later
+ * allows emit_bits to detect any attempt to emit such symbols.
+ */
+ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
+
+ /* This is also a convenient place to check for out-of-range
+ * and duplicated VAL entries. We allow 0..255 for AC symbols
+ * but only 0..16 for DC. (We could constrain them further
+ * based on data depth and mode, but this seems enough.)
+ */
+ maxsymbol = isDC ? 16 : 255;
+
+ for (p = 0; p < lastp; p++) {
+ i = htbl->huffval[p];
+ if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ dtbl->ehufco[i] = huffcode[p];
+ dtbl->ehufsi[i] = huffsize[p];
+ }
+}
+
+
+/*
+ * Generate the best Huffman code table for the given counts, fill htbl.
+ *
+ * The JPEG standard requires that no symbol be assigned a codeword of all
+ * one bits (so that padding bits added at the end of a compressed segment
+ * can't look like a valid code). Because of the canonical ordering of
+ * codewords, this just means that there must be an unused slot in the
+ * longest codeword length category. Section K.2 of the JPEG spec suggests
+ * reserving such a slot by pretending that symbol 256 is a valid symbol
+ * with count 1. In theory that's not optimal; giving it count zero but
+ * including it in the symbol set anyway should give a better Huffman code.
+ * But the theoretically better code actually seems to come out worse in
+ * practice, because it produces more all-ones bytes (which incur stuffed
+ * zero bytes in the final file). In any case the difference is tiny.
+ *
+ * The JPEG standard requires Huffman codes to be no more than 16 bits long.
+ * If some symbols have a very small but nonzero probability, the Huffman tree
+ * must be adjusted to meet the code length restriction. We currently use
+ * the adjustment method suggested in JPEG section K.2. This method is *not*
+ * optimal; it may not choose the best possible limited-length code. But
+ * typically only very-low-frequency symbols will be given less-than-optimal
+ * lengths, so the code is almost optimal. Experimental comparisons against
+ * an optimal limited-length-code algorithm indicate that the difference is
+ * microscopic --- usually less than a hundredth of a percent of total size.
+ * So the extra complexity of an optimal algorithm doesn't seem worthwhile.
+ */
+
+GLOBAL(void)
+jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
+{
+#define MAX_CLEN 32 /* assumed maximum initial code length */
+ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
+ int codesize[257]; /* codesize[k] = code length of symbol k */
+ int others[257]; /* next symbol in current branch of tree */
+ int c1, c2;
+ int p, i, j;
+ long v;
+
+ /* This algorithm is explained in section K.2 of the JPEG standard */
+
+ MEMZERO(bits, SIZEOF(bits));
+ MEMZERO(codesize, SIZEOF(codesize));
+ for (i = 0; i < 257; i++)
+ others[i] = -1; /* init links to empty */
+
+ freq[256] = 1; /* make sure 256 has a nonzero count */
+ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
+ * that no real symbol is given code-value of all ones, because 256
+ * will be placed last in the largest codeword category.
+ */
+
+ /* Huffman's basic algorithm to assign optimal code lengths to symbols */
+
+ for (;;) {
+ /* Find the smallest nonzero frequency, set c1 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c1 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v) {
+ v = freq[i];
+ c1 = i;
+ }
+ }
+
+ /* Find the next smallest nonzero frequency, set c2 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c2 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v && i != c1) {
+ v = freq[i];
+ c2 = i;
+ }
+ }
+
+ /* Done if we've merged everything into one frequency */
+ if (c2 < 0)
+ break;
+
+ /* Else merge the two counts/trees */
+ freq[c1] += freq[c2];
+ freq[c2] = 0;
+
+ /* Increment the codesize of everything in c1's tree branch */
+ codesize[c1]++;
+ while (others[c1] >= 0) {
+ c1 = others[c1];
+ codesize[c1]++;
+ }
+
+ others[c1] = c2; /* chain c2 onto c1's tree branch */
+
+ /* Increment the codesize of everything in c2's tree branch */
+ codesize[c2]++;
+ while (others[c2] >= 0) {
+ c2 = others[c2];
+ codesize[c2]++;
+ }
+ }
+
+ /* Now count the number of symbols of each code length */
+ for (i = 0; i <= 256; i++) {
+ if (codesize[i]) {
+ /* The JPEG standard seems to think that this can't happen, */
+ /* but I'm paranoid... */
+ if (codesize[i] > MAX_CLEN)
+ ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
+
+ bits[codesize[i]]++;
+ }
+ }
+
+ /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+ * Huffman procedure assigned any such lengths, we must adjust the coding.
+ * Here is what the JPEG spec says about how this next bit works:
+ * Since symbols are paired for the longest Huffman code, the symbols are
+ * removed from this length category two at a time. The prefix for the pair
+ * (which is one bit shorter) is allocated to one of the pair; then,
+ * skipping the BITS entry for that prefix length, a code word from the next
+ * shortest nonzero BITS entry is converted into a prefix for two code words
+ * one bit longer.
+ */
+
+ for (i = MAX_CLEN; i > 16; i--) {
+ while (bits[i] > 0) {
+ j = i - 2; /* find length of new prefix to be used */
+ while (bits[j] == 0)
+ j--;
+
+ bits[i] -= 2; /* remove two symbols */
+ bits[i-1]++; /* one goes in this length */
+ bits[j+1] += 2; /* two new symbols in this length */
+ bits[j]--; /* symbol of this length is now a prefix */
+ }
+ }
+
+ /* Remove the count for the pseudo-symbol 256 from the largest codelength */
+ while (bits[i] == 0) /* find largest codelength still in use */
+ i--;
+ bits[i]--;
+
+ /* Return final symbol counts (only for lengths 0..16) */
+ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
+
+ /* Return a list of the symbols sorted by code length */
+ /* It's not real clear to me why we don't need to consider the codelength
+ * changes made above, but the JPEG spec seems to think this works.
+ */
+ p = 0;
+ for (i = 1; i <= MAX_CLEN; i++) {
+ for (j = 0; j <= 255; j++) {
+ if (codesize[j] == i) {
+ htbl->huffval[p] = (UINT8) j;
+ p++;
+ }
+ }
+ }
+
+ /* Set sent_table FALSE so updated table will be written to JPEG file. */
+ htbl->sent_table = FALSE;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.h
new file mode 100644
index 00000000..b4db2b57
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jchuff.h
@@ -0,0 +1,54 @@
+/*
+ * jchuff.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy encoding routines
+ * that are shared between the sequential encoder (jchuff.c) and the
+ * progressive encoder (jcphuff.c). No other modules need to see these.
+ */
+
+/* The legal range of a DCT coefficient is
+ * -1024 .. +1023 for 8-bit data;
+ * -16384 .. +16383 for 12-bit data.
+ * Hence the magnitude should always fit in 10 or 14 bits respectively.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MAX_COEF_BITS 10
+#else
+#define MAX_COEF_BITS 14
+#endif
+
+/* The legal range of a spatial difference is
+ * -32767 .. +32768.
+ * Hence the magnitude should always fit in 16 bits.
+ */
+
+#define MAX_DIFF_BITS 16
+
+/* Derived data constructed for each Huffman table */
+
+typedef struct {
+ unsigned int ehufco[256]; /* code for each symbol */
+ char ehufsi[256]; /* length of code for each symbol */
+ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
+} c_derived_tbl;
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_c_derived_tbl jMkCDerived
+#define jpeg_gen_optimal_table jGenOptTbl
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_c_derived_tbl
+ JPP((j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl ** pdtbl));
+
+/* Generate an optimal table definition given the specified counts */
+EXTERN(void) jpeg_gen_optimal_table
+ JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]));
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcinit.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcinit.cpp
new file mode 100644
index 00000000..321001f1
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcinit.cpp
@@ -0,0 +1,58 @@
+/*
+ * jcinit.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains initialization logic for the JPEG compressor.
+ * This routine is in charge of selecting the modules to be executed and
+ * making an initialization call to each one.
+ *
+ * Logically, this code belongs in jcmaster.c. It's split out because
+ * linking this routine implies linking the entire compression library.
+ * For a transcoding-only application, we want to be able to use jcmaster.c
+ * without linking in the whole library.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * Master selection of compression modules.
+ * This is done once at the start of processing an image. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ */
+
+GLOBAL(void)
+jinit_compress_master (j_compress_ptr cinfo)
+{
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, FALSE /* full compression */);
+
+ /* Initialize compression codec */
+ jinit_c_codec(cinfo);
+
+ /* Preprocessing */
+ if (! cinfo->raw_data_in) {
+ jinit_color_converter(cinfo);
+ jinit_downsampler(cinfo);
+ jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
+ }
+
+ jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jclhuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclhuff.cpp
new file mode 100644
index 00000000..9b422f72
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclhuff.cpp
@@ -0,0 +1,600 @@
+/*
+ * jclhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for lossless JPEG.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU. To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+//#include "jchuff.h" /* Declarations shared with jc*huff.c */
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#define ASSIGN_STATE(dest,src) \
+ ((dest).put_buffer = (src).put_buffer, \
+ (dest).put_bits = (src).put_bits)
+#endif
+
+
+typedef struct {
+ int ci, yoffset, MCU_width;
+} lhe_input_ptr_info;
+
+
+typedef struct {
+ savable_state saved; /* Bit buffer at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ /* Pointers to derived tables to be used for each data unit within an MCU */
+ c_derived_tbl * cur_tbls[C_MAX_DATA_UNITS_IN_MCU];
+
+#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
+ long * count_ptrs[NUM_HUFF_TBLS];
+
+ /* Pointers to stats tables to be used for each data unit within an MCU */
+ long * cur_counts[C_MAX_DATA_UNITS_IN_MCU];
+#endif
+
+ /* Pointers to the proper input difference row for each group of data units
+ * within an MCU. For each component, there are Vi groups of Hi data units.
+ */
+ JDIFFROW input_ptr[C_MAX_DATA_UNITS_IN_MCU];
+
+ /* Number of input pointers in use for the current MCU. This is the sum
+ * of all Vi in the MCU.
+ */
+ int num_input_ptrs;
+
+ /* Information used for positioning the input pointers within the input
+ * difference rows.
+ */
+ lhe_input_ptr_info input_ptr_info[C_MAX_DATA_UNITS_IN_MCU];
+
+ /* Index of the proper input pointer for each data unit within an MCU */
+ int input_ptr_index[C_MAX_DATA_UNITS_IN_MCU];
+
+} lhuff_entropy_encoder;
+
+typedef lhuff_entropy_encoder * lhuff_entropy_ptr;
+
+/* Working state while writing an MCU.
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ savable_state cur; /* Current bit buffer & DC state */
+ j_compress_ptr cinfo; /* dump_buffer needs access to this */
+} working_state;
+
+
+/* Forward declarations */
+METHODDEF(JDIMENSION) encode_mcus_huff (j_compress_ptr cinfo,
+ JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num,
+ JDIMENSION MCU_col_num,
+ JDIMENSION nMCU);
+METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
+#ifdef ENTROPY_OPT_SUPPORTED
+METHODDEF(JDIMENSION) encode_mcus_gather (j_compress_ptr cinfo,
+ JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num,
+ JDIMENSION MCU_col_num,
+ JDIMENSION nMCU);
+METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
+#endif
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+ int ci, dctbl, sampn, ptrn, yoffset, xoffset;
+ jpeg_component_info * compptr;
+
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ losslsc->entropy_encode_mcus = encode_mcus_gather;
+ losslsc->pub.entropy_finish_pass = finish_pass_gather;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ losslsc->entropy_encode_mcus = encode_mcus_huff;
+ losslsc->pub.entropy_finish_pass = finish_pass_huff;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ /* Check for invalid table indexes */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->count_ptrs[dctbl] == NULL)
+ entropy->count_ptrs[dctbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->count_ptrs[dctbl], 257 * SIZEOF(long));
+#endif
+ } else {
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->derived_tbls[dctbl]);
+ }
+ }
+
+ /* Precalculate encoding info for each sample in an MCU of this scan */
+ for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
+ compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
+ ci = compptr->component_index;
+ /* ci = cinfo->MCU_membership[sampn];
+ compptr = cinfo->cur_comp_info[ci];*/
+ for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
+ /* Precalculate the setup info for each input pointer */
+ entropy->input_ptr_info[ptrn].ci = ci;
+ entropy->input_ptr_info[ptrn].yoffset = yoffset;
+ entropy->input_ptr_info[ptrn].MCU_width = compptr->MCU_width;
+ for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
+ /* Precalculate the input pointer index for each sample */
+ entropy->input_ptr_index[sampn] = ptrn;
+ /* Precalculate which tables to use for each sample */
+ entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
+ entropy->cur_counts[sampn] = entropy->count_ptrs[compptr->dc_tbl_no];
+ }
+ }
+ }
+ entropy->num_input_ptrs = ptrn;
+
+ /* Initialize bit buffer to empty */
+ entropy->saved.put_buffer = 0;
+ entropy->saved.put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte(state,val,action) \
+ { *(state)->next_output_byte++ = (JOCTET) (val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (! dump_buffer(state)) \
+ { action; } }
+
+
+LOCAL(boolean)
+dump_buffer (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+ struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (state->cinfo))
+ return FALSE;
+ /* After a successful buffer dump, must reset buffer pointers */
+ state->next_output_byte = dest->next_output_byte;
+ state->free_in_buffer = dest->free_in_buffer;
+ return TRUE;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = state->cur.put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte(state, c, return FALSE);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte(state, 0, return FALSE);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ state->cur.put_buffer = put_buffer; /* update state variables */
+ state->cur.put_bits = put_bits;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+flush_bits (working_state * state)
+{
+ if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
+ return FALSE;
+ state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
+ state->cur.put_bits = 0;
+ return TRUE;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart (working_state * state, int restart_num)
+{
+ //int ci;
+
+ if (! flush_bits(state))
+ return FALSE;
+
+ emit_byte(state, 0xFF, return FALSE);
+ emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
+
+ /* The restart counter is not updated until we successfully write the MCU. */
+
+ return TRUE;
+}
+
+
+/*
+ * Encode and output one nMCU's worth of Huffman-compressed differences.
+ */
+
+METHODDEF(JDIMENSION)
+encode_mcus_huff (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
+ JDIMENSION nMCU)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+ working_state state;
+ int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
+ //jpeg_component_info * compptr;
+
+ /* Load up working state */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! emit_restart(&state, entropy->next_restart_num))
+ return 0;
+ }
+
+ /* Set input pointer locations based on MCU_col_num */
+ for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
+ ci = entropy->input_ptr_info[ptrn].ci;
+ yoffset = entropy->input_ptr_info[ptrn].yoffset;
+ MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
+ entropy->input_ptr[ptrn] =
+ diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+ }
+
+ for (mcu_num = 0; mcu_num < (int)nMCU; mcu_num++) {
+
+ /* Inner loop handles the samples in the MCU */
+ for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+ register int temp, temp2; //, temp3;
+ register int nbits;
+ c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
+
+ /* Encode the difference per section H.1.2.2 */
+
+ /* Input the sample difference */
+ temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
+
+ if (temp & 0x8000) { /* instead of temp < 0 */
+ temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
+ if (temp == 0) /* special case: magnitude = 32768 */
+ temp2 = temp = 0x8000;
+ temp2 = ~ temp; /* one's complement of magnitude */
+ } else {
+ temp &= 0x7FFF; /* abs value mod 2^16 */
+ temp2 = temp; /* magnitude */
+ }
+
+ /* Find the number of bits needed for the magnitude of the difference */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range difference values.
+ */
+ if (nbits > MAX_DIFF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DIFF);
+
+ /* Emit the Huffman-coded symbol for the number of bits */
+ if (! emit_bits(&state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+ return mcu_num;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits && /* emit_bits rejects calls with size 0 */
+ nbits != 16) /* special case: no bits should be emitted */
+ if (! emit_bits(&state, (unsigned int) temp2, nbits))
+ return mcu_num;
+ }
+
+ /* Completed MCU, so update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ }
+
+ return nMCU;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+ working_state state;
+
+ /* Load up working state ... flush_bits needs it */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Flush out the last data */
+ if (! flush_bits(&state))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+ /* Update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+/*
+ * Trial-encode one nMCU's worth of Huffman-compressed differences.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(JDIMENSION)
+encode_mcus_gather (j_compress_ptr cinfo, JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num, JDIMENSION MCU_col_num,
+ JDIMENSION nMCU)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+ int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
+ //jpeg_component_info * compptr;
+
+ /* Take care of restart intervals if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ /* Update restart state */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ /* Set input pointer locations based on MCU_col_num */
+ for (ptrn = 0; ptrn < entropy->num_input_ptrs; ptrn++) {
+ ci = entropy->input_ptr_info[ptrn].ci;
+ yoffset = entropy->input_ptr_info[ptrn].yoffset;
+ MCU_width = entropy->input_ptr_info[ptrn].MCU_width;
+ entropy->input_ptr[ptrn] =
+ diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+ }
+
+ for (mcu_num = 0; mcu_num < (int)nMCU; mcu_num++) {
+
+ /* Inner loop handles the samples in the MCU */
+ for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+ register int temp;
+ register int nbits;
+ c_derived_tbl *dctbl = entropy->cur_tbls[sampn];
+ long * counts = entropy->cur_counts[sampn];
+
+ /* Encode the difference per section H.1.2.2 */
+
+ /* Input the sample difference */
+ temp = *entropy->input_ptr[entropy->input_ptr_index[sampn]]++;
+
+ if (temp & 0x8000) { /* instead of temp < 0 */
+ temp = (-temp) & 0x7FFF; /* absolute value, mod 2^16 */
+ if (temp == 0) /* special case: magnitude = 32768 */
+ temp = 0x8000;
+ } else
+ temp &= 0x7FFF; /* abs value mod 2^16 */
+
+ /* Find the number of bits needed for the magnitude of the difference */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range difference values.
+ */
+ if (nbits > MAX_DIFF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DIFF);
+
+ /* Count the Huffman symbol for the number of bits */
+ counts[nbits]++;
+ }
+ }
+
+ return nMCU;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsc->entropy_private;
+ int ci, dctbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did_dc[NUM_HUFF_TBLS];
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ MEMZERO(did_dc, SIZEOF(did_dc));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ if (! did_dc[dctbl]) {
+ htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[dctbl]);
+ did_dc[dctbl] = TRUE;
+ }
+ }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+ return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_lhuff_encoder (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (lhuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(lhuff_entropy_encoder));
+ losslsc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+ losslsc->pub.entropy_start_pass = start_pass_huff;
+ losslsc->pub.need_optimization_pass = need_optimization_pass;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+#ifdef ENTROPY_OPT_SUPPORTED
+ entropy->count_ptrs[i] = NULL;
+#endif
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossls.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossls.cpp
new file mode 100644
index 00000000..7ef1d771
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossls.cpp
@@ -0,0 +1,79 @@
+/*
+ * jclossls.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossless JPEG compressor.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h"
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+ (*losslsc->scaler_start_pass) (cinfo);
+ (*losslsc->predict_start_pass) (cinfo);
+ (*losslsc->diff_start_pass) (cinfo, pass_mode);
+}
+
+
+/*
+ * Initialize the lossless compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossless_c_codec(j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc;
+
+ /* Create subobject in permanent pool */
+ losslsc = (j_lossless_c_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(jpeg_lossless_c_codec));
+ cinfo->codec = (struct jpeg_c_codec *) losslsc;
+
+ /* Initialize sub-modules */
+
+ /* Scaler */
+ jinit_c_scaler(cinfo);
+
+ /* Differencer */
+ jinit_differencer(cinfo);
+
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ jinit_lhuff_encoder(cinfo);
+ }
+
+ /* Need a full-image difference buffer in any multi-pass mode. */
+ jinit_c_diff_controller(cinfo,
+ (boolean) (cinfo->num_scans > 1 ||
+ cinfo->optimize_coding));
+
+ /* Initialize method pointers.
+ *
+ * Note: entropy_start_pass and entropy_finish_pass are assigned in
+ * jclhuff.c and compress_data is assigned in jcdiffct.c.
+ */
+ losslsc->pub.start_pass = start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossy.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossy.cpp
new file mode 100644
index 00000000..de4b3e14
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jclossy.cpp
@@ -0,0 +1,77 @@
+/*
+ * jclossy.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossy JPEG compressor.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h"
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+
+ (*lossyc->fdct_start_pass) (cinfo);
+ (*lossyc->coef_start_pass) (cinfo, pass_mode);
+}
+
+
+/*
+ * Initialize the lossy compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossy_c_codec (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc;
+
+ /* Create subobject in permanent pool */
+ lossyc = (j_lossy_c_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(jpeg_lossy_c_codec));
+ cinfo->codec = (struct jpeg_c_codec *) lossyc;
+
+ /* Initialize sub-modules */
+
+ /* Forward DCT */
+ jinit_forward_dct(cinfo);
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ jinit_phuff_encoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_shuff_encoder(cinfo);
+ }
+
+ /* Need a full-image coefficient buffer in any multi-pass mode. */
+ jinit_c_coef_controller(cinfo,
+ (boolean) (cinfo->num_scans > 1 ||
+ cinfo->optimize_coding));
+
+ /* Initialize method pointers.
+ *
+ * Note: entropy_start_pass and entropy_finish_pass are assigned in
+ * jcshuff.c or jcphuff.c and compress_data is assigned in jccoefct.c.
+ */
+ lossyc->pub.start_pass = start_pass;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmainct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmainct.cpp
new file mode 100644
index 00000000..cbf09bfd
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmainct.cpp
@@ -0,0 +1,297 @@
+/*
+ * jcmainct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for compression.
+ * The main buffer lies between the pre-processor and the JPEG
+ * compressor proper; it holds downsampled data in the JPEG colorspace.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Note: currently, there is no operating mode in which a full-image buffer
+ * is needed at this step. If there were, that mode could not be used with
+ * "raw data" input, since this module is bypassed in that case. However,
+ * we've left the code here for possible use in special applications.
+ */
+#undef FULL_MAIN_BUFFER_SUPPORTED
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_main_controller pub; /* public fields */
+
+ JDIMENSION cur_iMCU_row; /* number of current iMCU row */
+ JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
+ boolean suspended; /* remember if we suspended output */
+ J_BUF_MODE pass_mode; /* current operating mode */
+
+ /* If using just a strip buffer, this points to the entire set of buffers
+ * (we allocate one for each component). In the full-image case, this
+ * points to the currently accessible strips of the virtual arrays.
+ */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* If using full-image storage, this array holds pointers to virtual-array
+ * control blocks for each component. Unused if not full-image storage.
+ */
+ jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+METHODDEF(void) process_data_buffer_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Do nothing in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ main->cur_iMCU_row = 0; /* initialize counters */
+ main->rowgroup_ctr = 0;
+ main->suspended = FALSE;
+ main->pass_mode = pass_mode; /* save mode for use by process_data */
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ if (main->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ main->pub.process_data = process_data_simple_main;
+ break;
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ case JBUF_SAVE_SOURCE:
+ case JBUF_CRANK_DEST:
+ case JBUF_SAVE_AND_PASS:
+ if (main->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ main->pub.process_data = process_data_buffer_main;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This routine handles the simple pass-through mode,
+ * where we have only a strip buffer.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int data_unit = cinfo->data_unit;
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Read input data if we haven't filled the main buffer yet */
+ if (((int)main->rowgroup_ctr) < data_unit)
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) data_unit);
+
+ /* If we don't have a full iMCU row buffered, return to application for
+ * more data. Note that preprocessor will always pad to fill the iMCU row
+ * at the bottom of the image.
+ */
+ if (main->rowgroup_ctr != data_unit)
+ return;
+
+ /* Send the completed row to the compressor */
+ if (! (*cinfo->codec->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+
+/*
+ * Process some data.
+ * This routine handles all of the modes that use a full-size buffer.
+ */
+
+METHODDEF(void)
+process_data_buffer_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci;
+ jpeg_component_info *compptr;
+ boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
+ int data_unit = cinfo->data_unit;
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Realign the virtual buffers if at the start of an iMCU row. */
+ if (main->rowgroup_ctr == 0) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, main->whole_image[ci],
+ main->cur_iMCU_row * (compptr->v_samp_factor * data_unit),
+ (JDIMENSION) (compptr->v_samp_factor * data_unit), writing);
+ }
+ /* In a read pass, pretend we just read some source data. */
+ if (! writing) {
+ *in_row_ctr += cinfo->max_v_samp_factor * data_unit;
+ main->rowgroup_ctr = data_unit;
+ }
+ }
+
+ /* If a write pass, read input data until the current iMCU row is full. */
+ /* Note: preprocessor will pad if necessary to fill the last iMCU row. */
+ if (writing) {
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) data_unit);
+ /* Return to application if we need more data to fill the iMCU row. */
+ if (main->rowgroup_ctr < data_unit)
+ return;
+ }
+
+ /* Emit data, unless this is a sink-only pass. */
+ if (main->pass_mode != JBUF_SAVE_SOURCE) {
+ if (! (*cinfo->codec->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ }
+
+ /* If get here, we are done with this iMCU row. Mark buffer empty. */
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+#endif /* FULL_MAIN_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci;
+ jpeg_component_info *compptr;
+ int data_unit = cinfo->data_unit;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_c_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ /* We don't need to create a buffer in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ /* Create the buffer. It holds downsampled data, so each component
+ * may be of a different size.
+ */
+ if (need_full_buffer) {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component */
+ /* Note we pad the bottom to a multiple of the iMCU height */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ compptr->width_in_data_units * data_unit,
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor) * data_unit,
+ (JDIMENSION) (compptr->v_samp_factor * data_unit));
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ main->whole_image[0] = NULL; /* flag for no virtual arrays */
+#endif
+ /* Allocate a strip buffer for each component */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_data_units * data_unit,
+ (JDIMENSION) (compptr->v_samp_factor * data_unit));
+ }
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmarker.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmarker.cpp
new file mode 100644
index 00000000..e108da76
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmarker.cpp
@@ -0,0 +1,672 @@
+/*
+ * jcmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write JPEG datastream markers.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_writer pub; /* public fields */
+
+ unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
+} my_marker_writer;
+
+typedef my_marker_writer * my_marker_ptr;
+
+
+/*
+ * Basic output routines.
+ *
+ * Note that we do not support suspension while writing a marker.
+ * Therefore, an application using suspension must ensure that there is
+ * enough buffer space for the initial markers (typ. 600-700 bytes) before
+ * calling jpeg_start_compress, and enough space to write the trailing EOI
+ * (a few bytes) before calling jpeg_finish_compress. Multipass compression
+ * modes are not supported at all with suspension, so those two are the only
+ * points where markers will be written.
+ */
+
+LOCAL(void)
+emit_byte (j_compress_ptr cinfo, int val)
+/* Emit a byte */
+{
+ struct jpeg_destination_mgr * dest = cinfo->dest;
+
+ *(dest->next_output_byte)++ = (JOCTET) val;
+ if (--dest->free_in_buffer == 0) {
+ if (! (*dest->empty_output_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+}
+
+
+LOCAL(void)
+emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+/* Emit a marker code */
+{
+ emit_byte(cinfo, 0xFF);
+ emit_byte(cinfo, (int) mark);
+}
+
+
+LOCAL(void)
+emit_2bytes (j_compress_ptr cinfo, int value)
+/* Emit a 2-byte integer; these are always MSB first in JPEG files */
+{
+ emit_byte(cinfo, (value >> 8) & 0xFF);
+ emit_byte(cinfo, value & 0xFF);
+}
+
+
+/*
+ * Routines to write specific marker types.
+ */
+
+LOCAL(int)
+emit_dqt (j_compress_ptr cinfo, int index)
+/* Emit a DQT marker */
+/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
+{
+ JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+ int prec;
+ int i;
+
+ if (qtbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
+
+ prec = 0;
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (qtbl->quantval[i] > 255)
+ prec = 1;
+ }
+
+ if (! qtbl->sent_table) {
+ emit_marker(cinfo, M_DQT);
+
+ emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+
+ emit_byte(cinfo, index + (prec<<4));
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* The table entries must be emitted in zigzag order. */
+ unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
+ if (prec)
+ emit_byte(cinfo, (int) (qval >> 8));
+ emit_byte(cinfo, (int) (qval & 0xFF));
+ }
+
+ qtbl->sent_table = TRUE;
+ }
+
+ return prec;
+}
+
+
+LOCAL(void)
+emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+/* Emit a DHT marker */
+{
+ JHUFF_TBL * htbl;
+ int length, i;
+
+ if (is_ac) {
+ htbl = cinfo->ac_huff_tbl_ptrs[index];
+ index += 0x10; /* output index has AC bit set */
+ } else {
+ htbl = cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
+
+ if (! htbl->sent_table) {
+ emit_marker(cinfo, M_DHT);
+
+ length = 0;
+ for (i = 1; i <= 16; i++)
+ length += htbl->bits[i];
+
+ emit_2bytes(cinfo, length + 2 + 1 + 16);
+ emit_byte(cinfo, index);
+
+ for (i = 1; i <= 16; i++)
+ emit_byte(cinfo, htbl->bits[i]);
+
+ for (i = 0; i < length; i++)
+ emit_byte(cinfo, htbl->huffval[i]);
+
+ htbl->sent_table = TRUE;
+ }
+}
+
+
+LOCAL(void)
+emit_dac (j_compress_ptr cinfo)
+/* Emit a DAC marker */
+/* Since the useful info is so small, we want to emit all the tables in */
+/* one DAC marker. Therefore this routine does its own scan of the table. */
+{
+#ifdef C_ARITH_CODING_SUPPORTED
+ char dc_in_use[NUM_ARITH_TBLS];
+ char ac_in_use[NUM_ARITH_TBLS];
+ int length, i;
+ jpeg_component_info *compptr;
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ dc_in_use[i] = ac_in_use[i] = 0;
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ dc_in_use[compptr->dc_tbl_no] = 1;
+ ac_in_use[compptr->ac_tbl_no] = 1;
+ }
+
+ length = 0;
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ length += dc_in_use[i] + ac_in_use[i];
+
+ emit_marker(cinfo, M_DAC);
+
+ emit_2bytes(cinfo, length*2 + 2);
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ if (dc_in_use[i]) {
+ emit_byte(cinfo, i);
+ emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+ }
+ if (ac_in_use[i]) {
+ emit_byte(cinfo, i + 0x10);
+ emit_byte(cinfo, cinfo->arith_ac_K[i]);
+ }
+ }
+#endif /* C_ARITH_CODING_SUPPORTED */
+}
+
+
+LOCAL(void)
+emit_dri (j_compress_ptr cinfo)
+/* Emit a DRI marker */
+{
+ emit_marker(cinfo, M_DRI);
+
+ emit_2bytes(cinfo, 4); /* fixed length */
+
+ emit_2bytes(cinfo, (int) cinfo->restart_interval);
+}
+
+
+LOCAL(void)
+emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+/* Emit a SOF marker */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, code);
+
+ emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
+
+ /* Make sure image isn't bigger than SOF field can handle */
+ if ((long) cinfo->image_height > 65535L ||
+ (long) cinfo->image_width > 65535L)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+
+ emit_byte(cinfo, cinfo->data_precision);
+ emit_2bytes(cinfo, (int) cinfo->image_height);
+ emit_2bytes(cinfo, (int) cinfo->image_width);
+
+ emit_byte(cinfo, cinfo->num_components);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ emit_byte(cinfo, compptr->component_id);
+ emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
+ emit_byte(cinfo, compptr->quant_tbl_no);
+ }
+}
+
+
+LOCAL(void)
+emit_sos (j_compress_ptr cinfo)
+/* Emit a SOS marker */
+{
+ int i, td, ta;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, M_SOS);
+
+ emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
+
+ emit_byte(cinfo, cinfo->comps_in_scan);
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ emit_byte(cinfo, compptr->component_id);
+ td = compptr->dc_tbl_no;
+ ta = compptr->ac_tbl_no;
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+ /* Progressive mode: only DC or only AC tables are used in one scan;
+ * furthermore, Huffman coding of DC refinement uses no table at all.
+ * We emit 0 for unused field(s); this is recommended by the P&M text
+ * but does not seem to be specified in the standard.
+ */
+ if (cinfo->Ss == 0) {
+ ta = 0; /* DC scan */
+ if (cinfo->Ah != 0 && !cinfo->arith_code)
+ td = 0; /* no DC table either */
+ } else {
+ td = 0; /* AC scan */
+ }
+ }
+ emit_byte(cinfo, (td << 4) + ta);
+ }
+
+ emit_byte(cinfo, cinfo->Ss);
+ emit_byte(cinfo, cinfo->Se);
+ emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
+}
+
+
+LOCAL(void)
+emit_jfif_app0 (j_compress_ptr cinfo)
+/* Emit a JFIF-compliant APP0 marker */
+{
+ /*
+ * Length of APP0 block (2 bytes)
+ * Block ID (4 bytes - ASCII "JFIF")
+ * Zero byte (1 byte to terminate the ID string)
+ * Version Major, Minor (2 bytes - major first)
+ * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
+ * Xdpu (2 bytes - dots per unit horizontal)
+ * Ydpu (2 bytes - dots per unit vertical)
+ * Thumbnail X size (1 byte)
+ * Thumbnail Y size (1 byte)
+ */
+
+ emit_marker(cinfo, M_APP0);
+
+ emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
+
+ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0x49);
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0);
+ emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
+ emit_byte(cinfo, cinfo->JFIF_minor_version);
+ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
+ emit_2bytes(cinfo, (int) cinfo->X_density);
+ emit_2bytes(cinfo, (int) cinfo->Y_density);
+ emit_byte(cinfo, 0); /* No thumbnail image */
+ emit_byte(cinfo, 0);
+}
+
+
+LOCAL(void)
+emit_adobe_app14 (j_compress_ptr cinfo)
+/* Emit an Adobe APP14 marker */
+{
+ /*
+ * Length of APP14 block (2 bytes)
+ * Block ID (5 bytes - ASCII "Adobe")
+ * Version Number (2 bytes - currently 100)
+ * Flags0 (2 bytes - currently 0)
+ * Flags1 (2 bytes - currently 0)
+ * Color transform (1 byte)
+ *
+ * Although Adobe TN 5116 mentions Version = 101, all the Adobe files
+ * now in circulation seem to use Version = 100, so that's what we write.
+ *
+ * We write the color transform byte as 1 if the JPEG color space is
+ * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
+ * whether the encoder performed a transformation, which is pretty useless.
+ */
+
+ emit_marker(cinfo, M_APP14);
+
+ emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
+
+ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
+ emit_byte(cinfo, 0x64);
+ emit_byte(cinfo, 0x6F);
+ emit_byte(cinfo, 0x62);
+ emit_byte(cinfo, 0x65);
+ emit_2bytes(cinfo, 100); /* Version */
+ emit_2bytes(cinfo, 0); /* Flags0 */
+ emit_2bytes(cinfo, 0); /* Flags1 */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_YCbCr:
+ emit_byte(cinfo, 1); /* Color transform = 1 */
+ break;
+ case JCS_YCCK:
+ emit_byte(cinfo, 2); /* Color transform = 2 */
+ break;
+ default:
+ emit_byte(cinfo, 0); /* Color transform = 0 */
+ break;
+ }
+}
+
+
+/*
+ * These routines allow writing an arbitrary marker with parameters.
+ * The only intended use is to emit COM or APPn markers after calling
+ * write_file_header and before calling write_frame_header.
+ * Other uses are not guaranteed to produce desirable results.
+ * Counting the parameter bytes properly is the caller's responsibility.
+ */
+
+METHODDEF(void)
+write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+/* Emit an arbitrary marker header */
+{
+ if (datalen > (unsigned int) 65533) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ emit_marker(cinfo, (JPEG_MARKER) marker);
+
+ emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
+}
+
+METHODDEF(void)
+write_marker_byte (j_compress_ptr cinfo, int val)
+/* Emit one byte of marker parameters following write_marker_header */
+{
+ emit_byte(cinfo, val);
+}
+
+
+/*
+ * Write datastream header.
+ * This consists of an SOI and optional APPn markers.
+ * We recommend use of the JFIF marker, but not the Adobe marker,
+ * when using YCbCr or grayscale data. The JFIF marker should NOT
+ * be used for any other JPEG colorspace. The Adobe marker is helpful
+ * to distinguish RGB, CMYK, and YCCK colorspaces.
+ * Note that an application can write additional header markers after
+ * jpeg_start_compress returns.
+ */
+
+METHODDEF(void)
+write_file_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ emit_marker(cinfo, M_SOI); /* first the SOI */
+
+ /* SOI is defined to reset restart interval to 0 */
+ marker->last_restart_interval = 0;
+
+ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
+ emit_jfif_app0(cinfo);
+ if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
+ emit_adobe_app14(cinfo);
+}
+
+
+/*
+ * Write frame header.
+ * This consists of DQT and SOFn markers.
+ * Note that we do not emit the SOF until we have emitted the DQT(s).
+ * This avoids compatibility problems with incorrect implementations that
+ * try to error-check the quant table numbers as soon as they see the SOF.
+ */
+
+METHODDEF(void)
+write_frame_header (j_compress_ptr cinfo)
+{
+ int ci, prec;
+ boolean is_baseline;
+ jpeg_component_info *compptr;
+
+ if (cinfo->process != JPROC_LOSSLESS) {
+ /* Emit DQT for each quantization table.
+ * Note that emit_dqt() suppresses any duplicate tables.
+ */
+ prec = 0;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prec += emit_dqt(cinfo, compptr->quant_tbl_no);
+ }
+ /* now prec is nonzero iff there are any 16-bit quant tables. */
+ }
+
+ /* Check for a non-baseline specification.
+ * Note we assume that Huffman table numbers won't be changed later.
+ */
+ if (cinfo->arith_code || cinfo->process != JPROC_SEQUENTIAL ||
+ cinfo->data_precision != 8) {
+ is_baseline = FALSE;
+ } else {
+ is_baseline = TRUE;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+ is_baseline = FALSE;
+ }
+ if (prec && is_baseline) {
+ is_baseline = FALSE;
+ /* If it's baseline except for quantizer size, warn the user */
+ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+ }
+ }
+
+ /* Emit the proper SOF marker */
+ if (cinfo->arith_code) {
+ emit_sof(cinfo, M_SOF9); /* SOF code for arithmetic coding */
+ } else {
+ if (cinfo->process == JPROC_PROGRESSIVE)
+ emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
+ else if (cinfo->process == JPROC_LOSSLESS)
+ emit_sof(cinfo, M_SOF3); /* SOF code for lossless Huffman */
+ else if (is_baseline)
+ emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
+ else
+ emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
+ }
+}
+
+
+/*
+ * Write scan header.
+ * This consists of DHT or DAC markers, optional DRI, and SOS.
+ * Compressed data will be written following the SOS.
+ */
+
+METHODDEF(void)
+write_scan_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ int i;
+ jpeg_component_info *compptr;
+
+ if (cinfo->arith_code) {
+ /* Emit arith conditioning info. We may have some duplication
+ * if the file has multiple scans, but it's so small it's hardly
+ * worth worrying about.
+ */
+ emit_dac(cinfo);
+ } else {
+ /* Emit Huffman tables.
+ * Note that emit_dht() suppresses any duplicate tables.
+ */
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+ /* Progressive mode: only DC or only AC tables are used in one scan */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ } else {
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ } else if (cinfo->process == JPROC_LOSSLESS) {
+ /* Lossless mode: only DC tables are used */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ } else {
+ /* Sequential mode: need both DC and AC tables */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ }
+ }
+
+ /* Emit DRI if required --- note that DRI value could change for each scan.
+ * We avoid wasting space with unnecessary DRIs, however.
+ */
+ if (cinfo->restart_interval != marker->last_restart_interval) {
+ emit_dri(cinfo);
+ marker->last_restart_interval = cinfo->restart_interval;
+ }
+
+ emit_sos(cinfo);
+}
+
+
+/*
+ * Write datastream trailer.
+ */
+
+METHODDEF(void)
+write_file_trailer (j_compress_ptr cinfo)
+{
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Write an abbreviated table-specification datastream.
+ * This consists of SOI, DQT and DHT tables, and EOI.
+ * Any table that is defined and not marked sent_table = TRUE will be
+ * emitted. Note that all tables will be marked sent_table = TRUE at exit.
+ */
+
+METHODDEF(void)
+write_tables_only (j_compress_ptr cinfo)
+{
+ int i;
+
+ emit_marker(cinfo, M_SOI);
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if (cinfo->quant_tbl_ptrs[i] != NULL)
+ (void) emit_dqt(cinfo, i);
+ }
+
+ if (! cinfo->arith_code) {
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, FALSE);
+ if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, TRUE);
+ }
+ }
+
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Initialize the marker writer module.
+ */
+
+GLOBAL(void)
+jinit_marker_writer (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker;
+
+ /* Create the subobject */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_marker_writer));
+ cinfo->marker = (struct jpeg_marker_writer *) marker;
+ /* Initialize method pointers */
+ marker->pub.write_file_header = write_file_header;
+ marker->pub.write_frame_header = write_frame_header;
+ marker->pub.write_scan_header = write_scan_header;
+ marker->pub.write_file_trailer = write_file_trailer;
+ marker->pub.write_tables_only = write_tables_only;
+ marker->pub.write_marker_header = write_marker_header;
+ marker->pub.write_marker_byte = write_marker_byte;
+ /* Initialize private state */
+ marker->last_restart_interval = 0;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmaster.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmaster.cpp
new file mode 100644
index 00000000..c977ee07
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcmaster.cpp
@@ -0,0 +1,648 @@
+/*
+ * jcmaster.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG compressor.
+ * These routines are concerned with parameter validation, initial setup,
+ * and inter-pass control (determining the number of passes and the work
+ * to be done in each pass).
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+
+
+/* Private state */
+
+typedef enum {
+ main_pass, /* input data, also do first output step */
+ huff_opt_pass, /* Huffman code optimization pass */
+ output_pass /* data output pass */
+} c_pass_type;
+
+typedef struct {
+ struct jpeg_comp_master pub; /* public fields */
+
+ c_pass_type pass_type; /* the type of the current pass */
+
+ int pass_number; /* # of passes completed */
+ int total_passes; /* total # of passes needed */
+
+ int scan_number; /* current index in scan_info[] */
+} my_comp_master;
+
+typedef my_comp_master * my_master_ptr;
+
+
+/*
+ * Support routines that do various essential calculations.
+ */
+
+LOCAL(void)
+initial_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+ int ci;
+ jpeg_component_info *compptr;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+ int data_unit = cinfo->data_unit;
+
+ /* Sanity check on image dimensions */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+ || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ /* Width of an input scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Fill in the correct component_index value; don't rely on application */
+ compptr->component_index = ci;
+ /* For compression, we never do any codec-based processing. */
+ compptr->codec_data_unit = data_unit;
+ /* Size in data units */
+ compptr->width_in_data_units = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * data_unit));
+ compptr->height_in_data_units = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * data_unit));
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) cinfo->max_h_samp_factor);
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) cinfo->max_v_samp_factor);
+ /* Mark component needed (this flag isn't actually used for compression) */
+ compptr->component_needed = TRUE;
+ }
+
+ /* Compute number of fully interleaved MCU rows (number of times that
+ * main controller will call coefficient controller).
+ */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*data_unit));
+}
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define NEED_SCAN_SCRIPT
+#else
+#ifdef C_LOSSLESS_SUPPORTED
+#define NEED_SCAN_SCRIPT
+#endif
+#endif
+
+#ifdef NEED_SCAN_SCRIPT
+
+LOCAL(void)
+validate_script (j_compress_ptr cinfo)
+/* Verify that the scan script in cinfo->scan_info[] is valid; also
+ * determine whether it uses progressive JPEG, and set cinfo->process.
+ */
+{
+ const jpeg_scan_info * scanptr;
+ int scanno, ncomps, ci, coefi, thisi;
+ int Ss, Se, Ah, Al;
+ boolean component_sent[MAX_COMPONENTS];
+#ifdef C_PROGRESSIVE_SUPPORTED
+ int * last_bitpos_ptr;
+ int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
+ /* -1 until that coefficient has been seen; then last Al for it */
+#endif
+
+ if (cinfo->num_scans <= 0)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
+
+#ifndef C_MULTISCAN_FILES_SUPPORTED
+ if (cinfo->num_scans > 1)
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+
+ scanptr = cinfo->scan_info;
+ if (cinfo->lossless) {
+#ifdef C_LOSSLESS_SUPPORTED
+ cinfo->process = JPROC_LOSSLESS;
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ component_sent[ci] = FALSE;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+ /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
+ * for progressive JPEG, no scan can have this.
+ */
+ else if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ cinfo->process = JPROC_PROGRESSIVE;
+ last_bitpos_ptr = & last_bitpos[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (coefi = 0; coefi < DCTSIZE2; coefi++)
+ *last_bitpos_ptr++ = -1;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->process = JPROC_SEQUENTIAL;
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ component_sent[ci] = FALSE;
+ }
+
+ for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
+ /* Validate component indexes */
+ ncomps = scanptr->comps_in_scan;
+ if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (thisi < 0 || thisi >= cinfo->num_components)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ /* Components must appear in SOF order within each scan */
+ if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ }
+ /* Validate progression parameters */
+ Ss = scanptr->Ss;
+ Se = scanptr->Se;
+ Ah = scanptr->Ah;
+ Al = scanptr->Al;
+ if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef C_LOSSLESS_SUPPORTED
+ /* The JPEG spec simply gives the range 0..15 for Al (Pt), but that
+ * seems wrong: the upper bound ought to depend on data precision.
+ * Perhaps they really meant 0..N-1 for N-bit precision, which is what
+ * we allow here.
+ */
+ if (Ss < 1 || Ss > 7 || /* predictor selector */
+ Se != 0 || Ah != 0 ||
+ Al < 0 || Al >= cinfo->data_precision) /* point transform */
+ ERREXIT1(cinfo, JERR_BAD_LOSSLESS_SCRIPT, scanno);
+ /* Make sure components are not sent twice */
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (component_sent[thisi])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ component_sent[thisi] = TRUE;
+ }
+#endif
+ } else if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
+ * seems wrong: the upper bound ought to depend on data precision.
+ * Perhaps they really meant 0..N+1 for N-bit precision.
+ * Here we allow 0..10 for 8-bit data; Al larger than 10 results in
+ * out-of-range reconstructed DC values during the first DC scan,
+ * which might cause problems for some decoders.
+ */
+#if BITS_IN_JSAMPLE == 8
+#define MAX_AH_AL 10
+#else
+#define MAX_AH_AL 13
+#endif
+ if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
+ Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ if (Ss == 0) {
+ if (Se != 0) /* DC and AC together not OK */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ if (ncomps != 1) /* AC scans must be for only one component */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ for (ci = 0; ci < ncomps; ci++) {
+ last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+ if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ for (coefi = Ss; coefi <= Se; coefi++) {
+ if (last_bitpos_ptr[coefi] < 0) {
+ /* first scan of this coefficient */
+ if (Ah != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ /* not first scan */
+ if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ last_bitpos_ptr[coefi] = Al;
+ }
+ }
+#endif
+ } else {
+ /* For sequential JPEG, all progression parameters must be these: */
+ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ /* Make sure components are not sent twice */
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (component_sent[thisi])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ component_sent[thisi] = TRUE;
+ }
+ }
+ }
+
+ /* Now verify that everything got sent. */
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* For progressive mode, we only check that at least some DC data
+ * got sent for each component; the spec does not require that all bits
+ * of all coefficients be transmitted. Would it be wiser to enforce
+ * transmission of all coefficient bits??
+ */
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (last_bitpos[ci][0] < 0)
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+#endif
+ } else {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (! component_sent[ci])
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+ }
+}
+
+#endif /* NEED_SCAN_SCRIPT */
+
+
+LOCAL(void)
+select_scan_parameters (j_compress_ptr cinfo)
+/* Set up the scan parameters for the current scan */
+{
+ int ci;
+
+#ifdef NEED_SCAN_SCRIPT
+ if (cinfo->scan_info != NULL) {
+ /* Prepare for current scan --- the script is already validated */
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
+
+ cinfo->comps_in_scan = scanptr->comps_in_scan;
+ for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
+ cinfo->cur_comp_info[ci] =
+ &cinfo->comp_info[scanptr->component_index[ci]];
+ }
+ cinfo->Ss = scanptr->Ss;
+ cinfo->Se = scanptr->Se;
+ cinfo->Ah = scanptr->Ah;
+ cinfo->Al = scanptr->Al;
+ } else
+#endif
+ {
+ /* Prepare for single sequential-JPEG scan containing all components */
+ if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPS_IN_SCAN);
+ cinfo->comps_in_scan = cinfo->num_components;
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+ }
+ if (cinfo->lossless) {
+#ifdef C_LOSSLESS_SUPPORTED
+ /* If we fall through to here, the user specified lossless, but did not
+ * provide a scan script.
+ */
+ ERREXIT(cinfo, JERR_NO_LOSSLESS_SCRIPT);
+#endif
+ } else {
+ cinfo->process = JPROC_SEQUENTIAL;
+ cinfo->Ss = 0;
+ cinfo->Se = DCTSIZE2-1;
+ cinfo->Ah = 0;
+ cinfo->Al = 0;
+ }
+ }
+}
+
+
+LOCAL(void)
+per_scan_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+ int data_unit = cinfo->data_unit;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_data_units;
+ cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
+
+ /* For noninterleaved scan, always one block per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_data_units = 1;
+ compptr->MCU_sample_width = data_unit;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of block rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->data_units_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width,
+ (long) (cinfo->max_h_samp_factor*data_unit));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*data_unit));
+
+ cinfo->data_units_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of blocks of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * data_unit;
+ /* Figure number of non-dummy blocks in last MCU column & row */
+ tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_data_units;
+ if (cinfo->data_units_in_MCU + mcublks > C_MAX_DATA_UNITS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
+ }
+ }
+
+ }
+
+ /* Convert restart specified in rows to actual MCU count. */
+ /* Note that count must fit in 16 bits, so we provide limiting. */
+ if (cinfo->restart_in_rows > 0) {
+ long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
+ cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+ }
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each pass. We determine which modules
+ * will be active during this pass and give them appropriate start_pass calls.
+ * We also set is_last_pass to indicate whether any more passes will be
+ * required.
+ */
+
+METHODDEF(void)
+prepare_for_pass (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ switch (master->pass_type) {
+ case main_pass:
+ /* Initial pass: will collect input data, and do either Huffman
+ * optimization or data output for the first scan.
+ */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if (! cinfo->raw_data_in) {
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->downsample->start_pass) (cinfo);
+ (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ (*cinfo->codec->entropy_start_pass) (cinfo, cinfo->optimize_coding);
+ (*cinfo->codec->start_pass) (cinfo,
+ (master->total_passes > 1 ?
+ JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ if (cinfo->optimize_coding) {
+ /* No immediate data output; postpone writing frame/scan headers */
+ master->pub.call_pass_startup = FALSE;
+ } else {
+ /* Will write frame/scan headers at first jpeg_write_scanlines call */
+ master->pub.call_pass_startup = TRUE;
+ }
+ break;
+#ifdef ENTROPY_OPT_SUPPORTED
+ case huff_opt_pass:
+ /* Do Huffman optimization for a scan after the first one. */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if ((*cinfo->codec->need_optimization_pass) (cinfo) || cinfo->arith_code) {
+ (*cinfo->codec->entropy_start_pass) (cinfo, TRUE);
+ (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ }
+ /* Special case: Huffman DC refinement scans need no Huffman table
+ * and therefore we can skip the optimization pass for them.
+ */
+ master->pass_type = output_pass;
+ master->pass_number++;
+ /*FALLTHROUGH*/
+#endif
+ case output_pass:
+ /* Do a data-output pass. */
+ /* We need not repeat per-scan setup if prior optimization pass did it. */
+ if (! cinfo->optimize_coding) {
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ }
+ (*cinfo->codec->entropy_start_pass) (cinfo, FALSE);
+ (*cinfo->codec->start_pass) (cinfo, JBUF_CRANK_DEST);
+ /* We emit frame/scan headers now */
+ if (master->scan_number == 0)
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ }
+
+ master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->total_passes;
+ }
+}
+
+
+/*
+ * Special start-of-pass hook.
+ * This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
+ * In single-pass processing, we need this hook because we don't want to
+ * write frame/scan headers during jpeg_start_compress; we want to let the
+ * application write COM markers etc. between jpeg_start_compress and the
+ * jpeg_write_scanlines loop.
+ * In multi-pass processing, this routine is not used.
+ */
+
+METHODDEF(void)
+pass_startup (j_compress_ptr cinfo)
+{
+ cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
+
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+}
+
+
+/*
+ * Finish up at end of pass.
+ */
+
+METHODDEF(void)
+finish_pass_master (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* The entropy coder always needs an end-of-pass call,
+ * either to analyze statistics or to flush its output buffer.
+ */
+ (*lossyc->pub.entropy_finish_pass) (cinfo);
+
+ /* Update state for next pass */
+ switch (master->pass_type) {
+ case main_pass:
+ /* next pass is either output of scan 0 (after optimization)
+ * or output of scan 1 (if no optimization).
+ */
+ master->pass_type = output_pass;
+ if (! cinfo->optimize_coding)
+ master->scan_number++;
+ break;
+ case huff_opt_pass:
+ /* next pass is always output of current scan */
+ master->pass_type = output_pass;
+ break;
+ case output_pass:
+ /* next pass is either optimization or output of next scan */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ master->scan_number++;
+ break;
+ }
+
+ master->pass_number++;
+}
+
+
+/*
+ * Initialize master compression control.
+ */
+
+GLOBAL(void)
+jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_comp_master));
+ cinfo->master = (struct jpeg_comp_master *) master;
+ master->pub.prepare_for_pass = prepare_for_pass;
+ master->pub.pass_startup = pass_startup;
+ master->pub.finish_pass = finish_pass_master;
+ master->pub.is_last_pass = FALSE;
+
+ cinfo->data_unit = cinfo->lossless ? 1 : DCTSIZE;
+
+ /* Validate parameters, determine derived values */
+ initial_setup(cinfo);
+
+ if (cinfo->scan_info != NULL) {
+#ifdef NEED_SCAN_SCRIPT
+ validate_script(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->process = JPROC_SEQUENTIAL;
+ cinfo->num_scans = 1;
+ }
+
+ if (cinfo->process == JPROC_PROGRESSIVE || /* TEMPORARY HACK ??? */
+ cinfo->process == JPROC_LOSSLESS)
+ cinfo->optimize_coding = TRUE; /* assume default tables no good for
+ * progressive mode or lossless mode */
+
+ /* Initialize my private state */
+ if (transcode_only) {
+ /* no main pass in transcoding */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ else
+ master->pass_type = output_pass;
+ } else {
+ /* for normal compression, first pass is always this type: */
+ master->pass_type = main_pass;
+ }
+ master->scan_number = 0;
+ master->pass_number = 0;
+ if (cinfo->optimize_coding)
+ master->total_passes = cinfo->num_scans * 2;
+ else
+ master->total_passes = cinfo->num_scans;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.cpp
new file mode 100644
index 00000000..01761343
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.cpp
@@ -0,0 +1,53 @@
+/*
+ * jcodec.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains utility functions for the JPEG codec(s).
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h"
+//#include "jlossls.h"
+
+
+/*
+ * Initialize the compression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void) jinit_c_codec (j_compress_ptr cinfo)
+{
+ if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef C_LOSSLESS_SUPPORTED
+ jinit_lossless_c_codec(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_lossy_c_codec(cinfo);
+}
+
+
+/*
+ * Initialize the decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_d_codec (j_decompress_ptr cinfo)
+{
+ if (cinfo->process == JPROC_LOSSLESS) {
+#ifdef D_LOSSLESS_SUPPORTED
+ jinit_lossless_d_codec(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_lossy_d_codec(cinfo);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.h
new file mode 100644
index 00000000..631f1d77
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcodec.h
@@ -0,0 +1,2 @@
+GLOBAL(void) jinit_c_codec (j_compress_ptr cinfo);
+GLOBAL(void) jinit_d_codec (j_decompress_ptr cinfo); \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcomapi.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcomapi.cpp
new file mode 100644
index 00000000..be24fd80
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcomapi.cpp
@@ -0,0 +1,107 @@
+/*
+ * jcomapi.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface routines that are used for both
+ * compression and decompression.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * Abort processing of a JPEG compression or decompression operation,
+ * but don't destroy the object itself.
+ *
+ * For this, we merely clean up all the nonpermanent memory pools.
+ * Note that temp files (virtual arrays) are not allowed to belong to
+ * the permanent pool, so we will be able to close all temp files here.
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_abort (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Do nothing if called on a not-initialized or destroyed JPEG object. */
+ if (cinfo->mem == NULL)
+ return;
+
+ /* Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+ (*cinfo->mem->free_pool) (cinfo, pool);
+ }
+
+ /* Reset overall state for possible reuse of object */
+ if (cinfo->is_decompressor) {
+ cinfo->global_state = DSTATE_START;
+ /* Try to keep application from accessing now-deleted marker list.
+ * A bit kludgy to do it here, but this is the most central place.
+ */
+ ((j_decompress_ptr) cinfo)->marker_list = NULL;
+ } else {
+ cinfo->global_state = CSTATE_START;
+ }
+}
+
+
+/*
+ * Destruction of a JPEG object.
+ *
+ * Everything gets deallocated except the master jpeg_compress_struct itself
+ * and the error manager struct. Both of these are supplied by the application
+ * and must be freed, if necessary, by the application. (Often they are on
+ * the stack and so don't need to be freed anyway.)
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_destroy (j_common_ptr cinfo)
+{
+ /* We need only tell the memory manager to release everything. */
+ /* NB: mem pointer is NULL if memory mgr failed to initialize. */
+ if (cinfo->mem != NULL)
+ (*cinfo->mem->self_destruct) (cinfo);
+ cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
+ cinfo->global_state = 0; /* mark it destroyed */
+}
+
+
+/*
+ * Convenience routines for allocating quantization and Huffman tables.
+ * (Would jutils.c be a more reasonable place to put these?)
+ */
+
+GLOBAL(JQUANT_TBL *)
+jpeg_alloc_quant_table (j_common_ptr cinfo)
+{
+ JQUANT_TBL *tbl;
+
+ tbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
+
+
+GLOBAL(JHUFF_TBL *)
+jpeg_alloc_huff_table (j_common_ptr cinfo)
+{
+ JHUFF_TBL *tbl;
+
+ tbl = (JHUFF_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jconfig.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jconfig.h
new file mode 100644
index 00000000..77a0f0ec
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jconfig.h
@@ -0,0 +1,47 @@
+/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
+/* see jconfig.doc for explanations */
+
+#define USE_WINDOWS_MESSAGEBOX
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+/* #define void char */
+/* #define const */
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
+#undef NEED_SHORT_EXTERNAL_NAMES
+#undef INCOMPLETE_TYPES_BROKEN
+
+/* Define "boolean" as unsigned char, not int, per Windows custom */
+#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+typedef unsigned char boolean;
+#endif
+#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+#define TWO_FILE_COMMANDLINE /* optional */
+#define USE_SETMODE /* Microsoft has setmode() */
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+#undef PROGRESS_REPORT /* optional */
+
+#endif /* JPEG_CJPEG_DJPEG */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcparam.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcparam.cpp
new file mode 100644
index 00000000..de2009ed
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcparam.cpp
@@ -0,0 +1,688 @@
+/*
+ * jcparam.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains optional default-setting code for the JPEG compressor.
+ * Applications do not have to use this file, but those that don't use it
+ * must know a lot more about the innards of the JPEG code.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * Quantization table setup routines
+ */
+
+GLOBAL(void)
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline)
+/* Define a quantization table equal to the basic_table times
+ * a scale factor (given as a percentage).
+ * If force_baseline is TRUE, the computed quantization table entries
+ * are limited to 1..255 for JPEG baseline compatibility.
+ */
+{
+ JQUANT_TBL ** qtblptr;
+ int i;
+ long temp;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
+
+ qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+ /* limit the values to the valid range */
+ if (temp <= 0L) temp = 1L;
+ if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
+ if (force_baseline && temp > 255L)
+ temp = 255L; /* limit to baseline range if requested */
+ (*qtblptr)->quantval[i] = (UINT16) temp;
+ }
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*qtblptr)->sent_table = FALSE;
+}
+
+
+GLOBAL(void)
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables
+ * and a straight percentage-scaling quality scale. In most cases it's better
+ * to use jpeg_set_quality (below); this entry point is provided for
+ * applications that insist on a linear percentage scaling.
+ */
+{
+ /* These are the sample quantization tables given in JPEG spec section K.1.
+ * The spec says that the values given produce "good" quality, and
+ * when divided by 2, "very good" quality.
+ */
+ static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+ };
+ static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+ };
+
+ /* Set up two quantization tables using the specified scaling */
+ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
+ scale_factor, force_baseline);
+ jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
+ scale_factor, force_baseline);
+}
+
+
+GLOBAL(int)
+jpeg_quality_scaling (int quality)
+/* Convert a user-specified quality rating to a percentage scaling factor
+ * for an underlying quantization table, using our recommended scaling curve.
+ * The input 'quality' factor should be 0 (terrible) to 100 (very good).
+ */
+{
+ /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
+ if (quality <= 0) quality = 1;
+ if (quality > 100) quality = 100;
+
+ /* The basic table is used as-is (scaling 100) for a quality of 50.
+ * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
+ * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
+ * to make all the table entries 1 (hence, minimum quantization loss).
+ * Qualities 1..50 are converted to scaling percentage 5000/Q.
+ */
+ if (quality < 50)
+ quality = 5000 / quality;
+ else
+ quality = 200 - quality*2;
+
+ return quality;
+}
+
+
+GLOBAL(void)
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables.
+ * This is the standard quality-adjusting entry point for typical user
+ * interfaces; only those who want detailed control over quantization tables
+ * would use the preceding three routines directly.
+ */
+{
+ /* Convert user 0-100 rating to percentage scaling */
+ quality = jpeg_quality_scaling(quality);
+
+ /* Set up standard quality tables */
+ jpeg_set_linear_quality(cinfo, quality, force_baseline);
+}
+
+
+/*
+ * Huffman table setup routines
+ */
+
+LOCAL(void)
+add_huff_table (j_compress_ptr cinfo,
+ JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+ int nsymbols, len;
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ /* Copy the number-of-symbols-of-each-code-length counts */
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+
+ /* Validate the counts. We do this here mainly so we can copy the right
+ * number of symbols from the val[] array, without risking marching off
+ * the end of memory. jchuff.c will do a more thorough test later.
+ */
+ nsymbols = 0;
+ for (len = 1; len <= 16; len++)
+ nsymbols += bits[len];
+ if (nsymbols < 1 || nsymbols > 256)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*htblptr)->sent_table = FALSE;
+}
+
+
+LOCAL(void)
+std_huff_tables (j_compress_ptr cinfo)
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+ static const UINT8 bits_dc_luminance[17] =
+ { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_luminance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_dc_chrominance[17] =
+ { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_chrominance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_ac_luminance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+ static const UINT8 val_ac_luminance[] =
+ { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ static const UINT8 bits_ac_chrominance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+ static const UINT8 val_ac_chrominance[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+ bits_dc_luminance, val_dc_luminance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+ bits_ac_luminance, val_ac_luminance);
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+ bits_dc_chrominance, val_dc_chrominance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+ bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+/*
+ * Default parameter setup for compression.
+ *
+ * Applications that don't choose to use this routine must do their
+ * own setup of all these parameters. Alternately, you can call this
+ * to establish defaults and then alter parameters selectively. This
+ * is the recommended approach since, if we add any new parameters,
+ * your code will still work (they'll be set to reasonable defaults).
+ */
+
+GLOBAL(void)
+jpeg_set_defaults (j_compress_ptr cinfo)
+{
+ int i;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Allocate comp_info array large enough for maximum component count.
+ * Array is made permanent in case application wants to compress
+ * multiple images at same param settings.
+ */
+ if (cinfo->comp_info == NULL)
+ cinfo->comp_info = (jpeg_component_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ MAX_COMPONENTS * SIZEOF(jpeg_component_info));
+
+ /* Initialize everything not dependent on the color space */
+
+ cinfo->lossless = FALSE;
+ cinfo->data_precision = BITS_IN_JSAMPLE;
+ /* Set up two quantization tables using default quality of 75 */
+ jpeg_set_quality(cinfo, 75, TRUE);
+ /* Set up two Huffman tables */
+ std_huff_tables(cinfo);
+
+ /* Initialize default arithmetic coding conditioning */
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+
+ /* Default is no multiple-scan output */
+ cinfo->scan_info = NULL;
+ cinfo->num_scans = 0;
+
+ /* Expect normal source image, not raw downsampled data */
+ cinfo->raw_data_in = FALSE;
+
+ /* Use Huffman coding, not arithmetic coding, by default */
+ cinfo->arith_code = FALSE;
+
+ /* By default, don't do extra passes to optimize entropy coding */
+ cinfo->optimize_coding = FALSE;
+ /* The standard Huffman tables are only valid for 8-bit data precision.
+ * If the precision is higher, force optimization on so that usable
+ * tables will be computed. This test can be removed if default tables
+ * are supplied that are valid for the desired precision.
+ */
+ if (cinfo->data_precision > 8)
+ cinfo->optimize_coding = TRUE;
+
+ /* By default, use the simpler non-cosited sampling alignment */
+ cinfo->CCIR601_sampling = FALSE;
+
+ /* No input smoothing */
+ cinfo->smoothing_factor = 0;
+
+ /* DCT algorithm preference */
+ cinfo->dct_method = JDCT_DEFAULT;
+
+ /* No restart markers */
+ cinfo->restart_interval = 0;
+ cinfo->restart_in_rows = 0;
+
+ /* Fill in default JFIF marker parameters. Note that whether the marker
+ * will actually be written is determined by jpeg_set_colorspace.
+ *
+ * By default, the library emits JFIF version code 1.01.
+ * An application that wants to emit JFIF 1.02 extension markers should set
+ * JFIF_minor_version to 2. We could probably get away with just defaulting
+ * to 1.02, but there may still be some decoders in use that will complain
+ * about that; saying 1.01 should minimize compatibility problems.
+ */
+ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0; /* Pixel size is unknown by default */
+ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
+ cinfo->Y_density = 1;
+
+ /* Choose JPEG colorspace based on input space, set defaults accordingly */
+
+ jpeg_default_colorspace(cinfo);
+}
+
+
+/*
+ * Select an appropriate JPEG colorspace for in_color_space.
+ */
+
+GLOBAL(void)
+jpeg_default_colorspace (j_compress_ptr cinfo)
+{
+ if (cinfo->lossless)
+ jpeg_set_colorspace(cinfo, cinfo->in_color_space);
+ else { /* lossy */
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+ break;
+ case JCS_RGB:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_YCbCr:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_CMYK:
+ jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
+ break;
+ case JCS_YCCK:
+ jpeg_set_colorspace(cinfo, JCS_YCCK);
+ break;
+ case JCS_UNKNOWN:
+ jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ }
+ }
+}
+
+
+/*
+ * Set the JPEG colorspace, and choose colorspace-dependent default values.
+ */
+
+GLOBAL(void)
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+{
+ jpeg_component_info * compptr;
+ int ci;
+
+#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
+ (compptr = &cinfo->comp_info[index], \
+ compptr->component_id = (id), \
+ compptr->h_samp_factor = (hsamp), \
+ compptr->v_samp_factor = (vsamp), \
+ compptr->quant_tbl_no = (quant), \
+ compptr->dc_tbl_no = (dctbl), \
+ compptr->ac_tbl_no = (actbl) )
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* For all colorspaces, we use Q and Huff tables 0 for luminance components,
+ * tables 1 for chrominance components.
+ */
+
+ cinfo->jpeg_color_space = colorspace;
+
+ cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
+ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
+
+ switch (colorspace) {
+ case JCS_GRAYSCALE:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 1;
+ /* JFIF specifies component ID 1 */
+ SET_COMP(0, 1, 1,1, 0, 0,0);
+ break;
+ case JCS_RGB:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
+ cinfo->num_components = 3;
+ SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCbCr:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 3;
+ /* JFIF specifies component IDs 1,2,3 */
+ if (cinfo->lossless) {
+ SET_COMP(0, 1, 1,1, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ } else { /* lossy */
+ /* We default to 2x2 subsamples of chrominance */
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ }
+ break;
+ case JCS_CMYK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
+ cinfo->num_components = 4;
+ SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
+ SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCCK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
+ cinfo->num_components = 4;
+ if (cinfo->lossless) {
+ SET_COMP(0, 1, 1,1, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(3, 4, 1,1, 0, 0,0);
+ } else { /* lossy */
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(3, 4, 2,2, 0, 0,0);
+ }
+ break;
+ case JCS_UNKNOWN:
+ cinfo->num_components = cinfo->input_components;
+ if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ SET_COMP(ci, ci, 1,1, 0, 0,0);
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ }
+}
+
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+LOCAL(jpeg_scan_info *)
+fill_scans (jpeg_scan_info * scanptr, int ncomps,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for each component */
+{
+ int ci;
+
+ for (ci = 0; ci < ncomps; ci++) {
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ }
+ return scanptr;
+}
+
+
+LOCAL(jpeg_scan_info *)
+fill_a_scan (jpeg_scan_info * scanptr, int ci,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for specified component */
+{
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
+/* Support routine: generate interleaved DC scan if possible, else N scans */
+{
+ int ci;
+
+ if (ncomps <= MAX_COMPS_IN_SCAN) {
+ /* Single interleaved DC scan */
+ scanptr->comps_in_scan = ncomps;
+ for (ci = 0; ci < ncomps; ci++)
+ scanptr->component_index[ci] = ci;
+ scanptr->Ss = scanptr->Se = 0;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ } else {
+ /* Noninterleaved DC scan for each component */
+ scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
+ }
+ return scanptr;
+}
+
+
+/*
+ * Create a recommended progressive-JPEG script.
+ * cinfo->num_components and cinfo->jpeg_color_space must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_progression (j_compress_ptr cinfo)
+{
+ int ncomps = cinfo->num_components;
+ int nscans;
+ jpeg_scan_info * scanptr;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Figure space needed for script. Calculation must match code below! */
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ nscans = 10;
+ } else {
+ /* All-purpose script for other color spaces. */
+ if (ncomps > MAX_COMPS_IN_SCAN)
+ nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
+ else
+ nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
+ }
+
+ /* Allocate space for script.
+ * We need to put it in the permanent pool in case the application performs
+ * multiple compressions without changing the settings. To avoid a memory
+ * leak if jpeg_simple_progression is called repeatedly for the same JPEG
+ * object, we try to re-use previously allocated space, and we allocate
+ * enough space to handle YCbCr even if initially asked for grayscale.
+ */
+ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+ cinfo->script_space_size = MAX(nscans, 10);
+ cinfo->script_space = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+ }
+ scanptr = cinfo->script_space;
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = nscans;
+
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ /* Initial DC scan */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ /* Initial AC scan: get some luma data out in a hurry */
+ scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
+ /* Chroma data is too small to be worth expending many scans on */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
+ /* Complete spectral selection for luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
+ /* Refine next bit of luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
+ /* Finish DC successive approximation */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ /* Finish AC successive approximation */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
+ /* Luma bottom bit comes last since it's usually largest scan */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
+ } else {
+ /* All-purpose script for other color spaces. */
+ /* Successive approximation first pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
+ scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
+ /* Successive approximation second pass */
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
+ /* Successive approximation final pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
+ }
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/*
+ * Create a single-entry lossless-JPEG script containing all components.
+ * cinfo->num_components must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_lossless (j_compress_ptr cinfo, int predictor, int point_transform)
+{
+ int ncomps = cinfo->num_components;
+ int nscans = 1;
+ int ci;
+ jpeg_scan_info * scanptr;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ cinfo->lossless = TRUE;
+
+ /* Set jpeg_color_space. */
+ jpeg_default_colorspace(cinfo);
+
+ /* Check to ensure that all components will fit in one scan. */
+ if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPS_IN_SCAN);
+
+ /* Allocate space for script.
+ * We need to put it in the permanent pool in case the application performs
+ * multiple compressions without changing the settings. To avoid a memory
+ * leak if jpeg_simple_lossless is called repeatedly for the same JPEG
+ * object, we try to re-use previously allocated space.
+ */
+ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+ cinfo->script_space_size = nscans;
+ cinfo->script_space = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+ }
+ scanptr = cinfo->script_space;
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = nscans;
+
+ /* Fill the script. */
+ scanptr->comps_in_scan = ncomps;
+ for (ci = 0; ci < ncomps; ci++)
+ scanptr->component_index[ci] = ci;
+ scanptr->Ss = predictor;
+ scanptr->Se = 0;
+ scanptr->Ah = 0;
+ scanptr->Al = point_transform;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcphuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcphuff.cpp
new file mode 100644
index 00000000..fc6a6973
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcphuff.cpp
@@ -0,0 +1,849 @@
+/*
+ * jcphuff.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for progressive JPEG.
+ *
+ * We do not support output suspension in this module, since the library
+ * currently does not allow multiple-scan files to be written with output
+ * suspension.
+ */
+#include "stdafx.h"
+
+//#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+//#include "jchuff.h" /* Declarations shared with jc*huff.c */
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+/* Expanded entropy encoder object for progressive Huffman encoding. */
+
+typedef struct {
+ /* Mode flag: TRUE for optimization, FALSE for actual data output */
+ boolean gather_statistics;
+
+ /* Bit-level coding status.
+ * next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
+ */
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */
+
+ /* Coding status for DC components */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+
+ /* Coding status for AC components */
+ int ac_tbl_no; /* the table number of the single component */
+ unsigned int EOBRUN; /* run length of EOBs */
+ unsigned int BE; /* # of buffered correction bits before MCU */
+ char * bit_buffer; /* buffer for correction bits (1 per char) */
+ /* packing correction bits tightly would save some space but cost time... */
+
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to derived tables (these workspaces have image lifespan).
+ * Since any one scan codes only DC or only AC, we only need one set
+ * of tables, not one for DC and one for AC.
+ */
+ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ /* Statistics tables for optimization; again, one set is enough */
+ long * count_ptrs[NUM_HUFF_TBLS];
+} phuff_entropy_encoder;
+
+typedef phuff_entropy_encoder * phuff_entropy_ptr;
+
+/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
+ * buffer can hold. Larger sizes may slightly improve compression, but
+ * 1000 is already well into the realm of overkill.
+ * The minimum safe size is 64 bits.
+ */
+
+#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */
+
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
+ * We assume that int right shift is unsigned if INT32 right shift is,
+ * which should be safe.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS int ishift_temp;
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo));
+METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo));
+
+
+/*
+ * Initialize for a Huffman-compressed scan using progressive JPEG.
+ */
+
+METHODDEF(void)
+start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ boolean is_DC_band;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+
+ entropy->cinfo = cinfo;
+ entropy->gather_statistics = gather_statistics;
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* We assume jcmaster.c already validated the scan parameters. */
+
+ /* Select execution routines */
+ if (cinfo->Ah == 0) {
+ if (is_DC_band)
+ lossyc->entropy_encode_mcu = encode_mcu_DC_first;
+ else
+ lossyc->entropy_encode_mcu = encode_mcu_AC_first;
+ } else {
+ if (is_DC_band)
+ lossyc->entropy_encode_mcu = encode_mcu_DC_refine;
+ else {
+ lossyc->entropy_encode_mcu = encode_mcu_AC_refine;
+ /* AC refinement needs a correction bit buffer */
+ if (entropy->bit_buffer == NULL)
+ entropy->bit_buffer = (char *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ MAX_CORR_BITS * SIZEOF(char));
+ }
+ }
+ if (gather_statistics)
+ lossyc->pub.entropy_finish_pass = finish_pass_gather_phuff;
+ else
+ lossyc->pub.entropy_finish_pass = finish_pass_phuff;
+
+ /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
+ * for AC coefficients.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Initialize DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ /* Get table index */
+ if (is_DC_band) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
+ }
+ if (gather_statistics) {
+ /* Check for invalid table index */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->count_ptrs[tbl] == NULL)
+ entropy->count_ptrs[tbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
+ } else {
+ /* Compute derived values for Huffman table */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl,
+ & entropy->derived_tbls[tbl]);
+ }
+ }
+
+ /* Initialize AC stuff */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+
+ /* Initialize bit buffer to empty */
+ entropy->put_buffer = 0;
+ entropy->put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file.
+ * NB: these must be called only when actually outputting,
+ * that is, entropy->gather_statistics == FALSE.
+ */
+
+/* Emit a byte */
+#define emit_byte(entropy,val) \
+ { *(entropy)->next_output_byte++ = (JOCTET) (val); \
+ if (--(entropy)->free_in_buffer == 0) \
+ dump_buffer(entropy); }
+
+
+LOCAL(void)
+dump_buffer (phuff_entropy_ptr entropy)
+/* Empty the output buffer; we do not support suspension in this module. */
+{
+ struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (entropy->cinfo))
+ ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
+ /* After a successful buffer dump, must reset buffer pointers */
+ entropy->next_output_byte = dest->next_output_byte;
+ entropy->free_in_buffer = dest->free_in_buffer;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(void)
+emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size)
+/* Emit some bits, unless we are in gather mode */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = entropy->put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ if (entropy->gather_statistics)
+ return; /* do nothing if we're only getting stats */
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte(entropy, c);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte(entropy, 0);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ entropy->put_buffer = put_buffer; /* update variables */
+ entropy->put_bits = put_bits;
+}
+
+
+LOCAL(void)
+flush_bits (phuff_entropy_ptr entropy)
+{
+ emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */
+ entropy->put_buffer = 0; /* and reset bit-buffer to empty */
+ entropy->put_bits = 0;
+}
+
+
+/*
+ * Emit (or just count) a Huffman symbol.
+ */
+
+INLINE
+LOCAL(void)
+emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol)
+{
+ if (entropy->gather_statistics)
+ entropy->count_ptrs[tbl_no][symbol]++;
+ else {
+ c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
+ emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
+ }
+}
+
+
+/*
+ * Emit bits from a correction bit buffer.
+ */
+
+LOCAL(void)
+emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart,
+ unsigned int nbits)
+{
+ if (entropy->gather_statistics)
+ return; /* no real work */
+
+ while (nbits > 0) {
+ emit_bits(entropy, (unsigned int) (*bufstart), 1);
+ bufstart++;
+ nbits--;
+ }
+}
+
+
+/*
+ * Emit any pending EOBRUN symbol.
+ */
+
+LOCAL(void)
+emit_eobrun (phuff_entropy_ptr entropy)
+{
+ register int temp, nbits;
+
+ if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
+ temp = entropy->EOBRUN;
+ nbits = 0;
+ while ((temp >>= 1))
+ nbits++;
+ /* safety check: shouldn't happen given limited correction-bit buffer */
+ if (nbits > 14)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
+ if (nbits)
+ emit_bits(entropy, entropy->EOBRUN, nbits);
+
+ entropy->EOBRUN = 0;
+
+ /* Emit any buffered correction bits */
+ emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(void)
+emit_restart (phuff_entropy_ptr entropy, int restart_num)
+{
+ int ci;
+
+ emit_eobrun(entropy);
+
+ if (! entropy->gather_statistics) {
+ flush_bits(entropy);
+ emit_byte(entropy, 0xFF);
+ emit_byte(entropy, JPEG_RST0 + restart_num);
+ }
+
+ if (entropy->cinfo->Ss == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
+ entropy->last_dc_val[ci] = 0;
+ } else {
+ /* Re-initialize all AC-related fields to 0 */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * MCU encoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ register int temp, temp2;
+ register int nbits;
+ int blkn, ci;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ jpeg_component_info * compptr;
+ ISHIFT_TEMPS
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+
+ /* Compute the DC value after the required point transform by Al.
+ * This is simply an arithmetic right shift.
+ */
+ temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+
+ /* DC differences are figured on the point-transformed values. */
+ temp = temp2 - entropy->last_dc_val[ci];
+ entropy->last_dc_val[ci] = temp2;
+
+ /* Encode the DC coefficient difference per section G.1.2.1 */
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit the Huffman-coded symbol for the number of bits */
+ emit_symbol(entropy, compptr->dc_tbl_no, nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ emit_bits(entropy, (unsigned int) temp2, nbits);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ register int temp, temp2;
+ register int nbits;
+ register int r, k;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
+ r++;
+ continue;
+ }
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value; so the code is
+ * interwoven with finding the abs value (temp) and output bits (temp2).
+ */
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
+ temp2 = ~temp;
+ } else {
+ temp >>= Al; /* apply the point transform */
+ temp2 = temp;
+ }
+ /* Watch out for case that nonzero coef is zero after point transform */
+ if (temp == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any pending EOBRUN */
+ if (entropy->EOBRUN > 0)
+ emit_eobrun(entropy);
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ emit_bits(entropy, (unsigned int) temp2, nbits);
+
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ if (entropy->EOBRUN == 0x7FFF)
+ emit_eobrun(entropy); /* force it out to avoid overflow */
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ register int temp;
+ int blkn;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* We simply emit the Al'th bit of the DC coefficient value. */
+ temp = (*block)[0];
+ emit_bits(entropy, (unsigned int) (temp >> Al), 1);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ register int temp;
+ register int r, k;
+ int EOB;
+ char *BR_buffer;
+ unsigned int BR;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ int absvalues[DCTSIZE2];
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* It is convenient to make a pre-pass to determine the transformed
+ * coefficients' absolute values and the EOB position.
+ */
+ EOB = 0;
+ for (k = cinfo->Ss; k <= Se; k++) {
+ temp = (*block)[jpeg_natural_order[k]];
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value.
+ */
+ if (temp < 0)
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ absvalues[k] = temp; /* save abs value for main pass */
+ if (temp == 1)
+ EOB = k; /* EOB = index of last newly-nonzero coef */
+ }
+
+ /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
+
+ r = 0; /* r = run length of zeros */
+ BR = 0; /* BR = count of buffered bits added now */
+ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = absvalues[k]) == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any required ZRLs, but not if they can be folded into EOB */
+ while (r > 15 && k <= EOB) {
+ /* emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+ /* Emit ZRL */
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ /* Emit buffered correction bits that must be associated with ZRL */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ }
+
+ /* If the coef was previously nonzero, it only needs a correction bit.
+ * NOTE: a straight translation of the spec's figure G.7 would suggest
+ * that we also need to test r > 15. But if r > 15, we can only get here
+ * if k > EOB, which implies that this coefficient is not 1.
+ */
+ if (temp > 1) {
+ /* The correction bit is the next bit of the absolute value. */
+ BR_buffer[BR++] = (char) (temp & 1);
+ continue;
+ }
+
+ /* Emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+
+ /* Emit output bit for newly-nonzero coef */
+ temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
+ emit_bits(entropy, (unsigned int) temp, 1);
+
+ /* Emit buffered correction bits that must be associated with this code */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ entropy->BE += BR; /* concat my correction bits to older ones */
+ /* We force out the EOB if we risk either:
+ * 1. overflow of the EOB counter;
+ * 2. overflow of the correction bit buffer during the next MCU.
+ */
+ if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+ emit_eobrun(entropy);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed progressive scan.
+ */
+
+METHODDEF(void)
+finish_pass_phuff (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Flush out any buffered data */
+ emit_eobrun(entropy);
+ flush_bits(entropy);
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather_phuff (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyc->entropy_private;
+ boolean is_DC_band;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did[NUM_HUFF_TBLS];
+
+ /* Flush out buffered data (all we care about is counting the EOB symbol) */
+ emit_eobrun(entropy);
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ MEMZERO(did, SIZEOF(did));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ if (is_DC_band) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ tbl = compptr->ac_tbl_no;
+ }
+ if (! did[tbl]) {
+ if (is_DC_band)
+ htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+ else
+ htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
+ did[tbl] = TRUE;
+ }
+ }
+}
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+ return (cinfo->Ss != 0 || cinfo->Ah == 0);
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_encoder (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (phuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(phuff_entropy_encoder));
+ lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+ lossyc->pub.entropy_start_pass = start_pass_phuff;
+ lossyc->pub.need_optimization_pass = need_optimization_pass;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ entropy->count_ptrs[i] = NULL;
+ }
+ entropy->bit_buffer = NULL; /* needed only in AC refinement scan */
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcpred.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcpred.cpp
new file mode 100644
index 00000000..70c70050
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcpred.cpp
@@ -0,0 +1,298 @@
+/*
+ * jcpred.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample differencing for lossless JPEG.
+ *
+ * In order to avoid paying the performance penalty of having to check the
+ * predictor being used and the row being processed for each call of the
+ * undifferencer, and to promote optimization, we have separate differencing
+ * functions for each case.
+ *
+ * We are able to avoid duplicating source code by implementing the predictors
+ * and differencers as macros. Each of the differencing functions are
+ * simply wrappers around a DIFFERENCE macro with the appropriate PREDICTOR
+ * macro passed as an argument.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+/* Private predictor object */
+
+typedef struct {
+ /* MCU-rows left in the restart interval for each component */
+ unsigned int restart_rows_to_go[MAX_COMPONENTS];
+} c_predictor;
+
+typedef c_predictor * c_pred_ptr;
+
+/* Forward declarations */
+LOCAL(void) reset_predictor
+ JPP((j_compress_ptr cinfo, int ci));
+METHODDEF(void) start_pass
+ JPP((j_compress_ptr cinfo));
+
+
+/* Predictor for the first column of the first row: 2^(P-Pt-1) */
+#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
+
+/* Predictor for the first column of the remaining rows: Rb */
+#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
+
+
+/*
+ * 1-Dimensional differencer routine.
+ *
+ * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
+ * is used as the special case predictor for the first column, which must be
+ * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
+ * use PREDICTOR1.
+ */
+
+#define DIFFERENCE_1D(INITIAL_PREDICTOR) \
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
+ c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
+ boolean restart = FALSE; \
+ int xindex; \
+ int samp, Ra; \
+ \
+ samp = GETJSAMPLE(input_buf[0]); \
+ diff_buf[0] = samp - INITIAL_PREDICTOR; \
+ \
+ for (xindex = 1; xindex < (int)width; xindex++) { \
+ Ra = samp; \
+ samp = GETJSAMPLE(input_buf[xindex]); \
+ diff_buf[xindex] = samp - PREDICTOR1; \
+ } \
+ \
+ /* Account for restart interval (no-op if not using restarts) */ \
+ if (cinfo->restart_interval) { \
+ if (--(pred->restart_rows_to_go[ci]) == 0) { \
+ reset_predictor(cinfo, ci); \
+ restart = TRUE; \
+ } \
+ }
+
+
+/*
+ * 2-Dimensional differencer routine.
+ *
+ * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
+ * used as the special case predictor for the first column. The remaining
+ * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
+ *
+ * Because prev_row and output_buf may point to the same storage area (in an
+ * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
+ * before writing the current reconstructed sample value into output_buf.
+ */
+
+#define DIFFERENCE_2D(PREDICTOR) \
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec; \
+ c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private; \
+ int xindex; \
+ int samp, Ra, Rb, Rc; \
+ \
+ Rb = GETJSAMPLE(prev_row[0]); \
+ samp = GETJSAMPLE(input_buf[0]); \
+ diff_buf[0] = samp - PREDICTOR2; \
+ \
+ for (xindex = 1; xindex < (int)width; xindex++) { \
+ Rc = Rb; \
+ Rb = GETJSAMPLE(prev_row[xindex]); \
+ Ra = samp; \
+ samp = GETJSAMPLE(input_buf[xindex]); \
+ diff_buf[xindex] = samp - PREDICTOR; \
+ } \
+ \
+ /* Account for restart interval (no-op if not using restarts) */ \
+ if (cinfo->restart_interval) { \
+ if (--pred->restart_rows_to_go[ci] == 0) \
+ reset_predictor(cinfo, ci); \
+ }
+
+
+/*
+ * Differencers for the all rows but the first in a scan or restart interval.
+ * The first sample in the row is differenced using the vertical
+ * predictor (2). The rest of the samples are differenced using the
+ * predictor specified in the scan header.
+ */
+
+METHODDEF(void)
+jpeg_difference1(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_1D(INITIAL_PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_difference2(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_difference3(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR3);
+}
+
+METHODDEF(void)
+jpeg_difference4(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR4);
+}
+
+METHODDEF(void)
+jpeg_difference5(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR5);
+}
+
+METHODDEF(void)
+jpeg_difference6(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR6);
+}
+
+METHODDEF(void)
+jpeg_difference7(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_2D(PREDICTOR7);
+}
+
+
+/*
+ * Differencer for the first row in a scan or restart interval. The first
+ * sample in the row is differenced using the special predictor constant
+ * x=2^(P-Pt-1). The rest of the samples are differenced using the
+ * 1-D horizontal predictor (1).
+ */
+
+METHODDEF(void)
+jpeg_difference_first_row(j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width)
+{
+ DIFFERENCE_1D(INITIAL_PREDICTORx);
+
+ /*
+ * Now that we have differenced the first row, we want to use the
+ * differencer which corresponds to the predictor specified in the
+ * scan header.
+ *
+ * Note that we don't to do this if we have just reset the predictor
+ * for a new restart interval.
+ */
+ if (!restart) {
+ switch (cinfo->Ss) {
+ case 1:
+ losslsc->predict_difference[ci] = jpeg_difference1;
+ break;
+ case 2:
+ losslsc->predict_difference[ci] = jpeg_difference2;
+ break;
+ case 3:
+ losslsc->predict_difference[ci] = jpeg_difference3;
+ break;
+ case 4:
+ losslsc->predict_difference[ci] = jpeg_difference4;
+ break;
+ case 5:
+ losslsc->predict_difference[ci] = jpeg_difference5;
+ break;
+ case 6:
+ losslsc->predict_difference[ci] = jpeg_difference6;
+ break;
+ case 7:
+ losslsc->predict_difference[ci] = jpeg_difference7;
+ break;
+ }
+ }
+}
+
+/*
+ * Reset predictor at the start of a pass or restart interval.
+ */
+
+LOCAL(void)
+reset_predictor (j_compress_ptr cinfo, int ci)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
+
+ /* Initialize restart counter */
+ pred->restart_rows_to_go[ci] =
+ cinfo->restart_interval / cinfo->MCUs_per_row;
+
+ /* Set difference function to first row function */
+ losslsc->predict_difference[ci] = jpeg_difference_first_row;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_pred_ptr pred = (c_pred_ptr) losslsc->pred_private;
+ int ci;
+
+ /* Check that the restart interval is an integer multiple of the number
+ * of MCU in an MCU-row.
+ */
+ if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
+ ERREXIT2(cinfo, JERR_BAD_RESTART,
+ cinfo->restart_interval, cinfo->MCUs_per_row);
+
+ /* Set predictors for start of pass */
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ reset_predictor(cinfo, ci);
+}
+
+
+/*
+ * Module initialization routine for the differencer.
+ */
+
+GLOBAL(void)
+jinit_differencer (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ c_pred_ptr pred;
+
+ pred = (c_pred_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_predictor));
+ losslsc->pred_private = (void *) pred;
+ losslsc->predict_start_pass = start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
+
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcprepct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcprepct.cpp
new file mode 100644
index 00000000..28b0a031
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcprepct.cpp
@@ -0,0 +1,355 @@
+/*
+ * jcprepct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the compression preprocessing controller.
+ * This controller manages the color conversion, downsampling,
+ * and edge expansion steps.
+ *
+ * Most of the complexity here is associated with buffering input rows
+ * as required by the downsampler. See the comments at the head of
+ * jcsample.c for the downsampler's needs.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* At present, jcsample.c can request context rows only for smoothing.
+ * In the future, we might also need context rows for CCIR601 sampling
+ * or other more-complex downsampling procedures. The code to support
+ * context rows should be compiled only if needed.
+ */
+#ifdef INPUT_SMOOTHING_SUPPORTED
+#define CONTEXT_ROWS_SUPPORTED
+#endif
+
+
+/*
+ * For the simple (no-context-row) case, we just need to buffer one
+ * row group's worth of pixels for the downsampling step. At the bottom of
+ * the image, we pad to a full row group by replicating the last pixel row.
+ * The downsampler's last output row is then replicated if needed to pad
+ * out to a full iMCU row.
+ *
+ * When providing context rows, we must buffer three row groups' worth of
+ * pixels. Three row groups are physically allocated, but the row pointer
+ * arrays are made five row groups high, with the extra pointers above and
+ * below "wrapping around" to point to the last and first real row groups.
+ * This allows the downsampler to access the proper context rows.
+ * At the top and bottom of the image, we create dummy context rows by
+ * copying the first or last real pixel row. This copying could be avoided
+ * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
+ * trouble on the compression side.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_prep_controller pub; /* public fields */
+
+ /* Downsampling input buffer. This buffer holds color-converted data
+ * until we have enough to do a downsample step.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ JDIMENSION rows_to_go; /* counts rows remaining in source image */
+ int next_buf_row; /* index of next row to store in color_buf */
+
+#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
+ int this_row_group; /* starting row index of group to process */
+ int next_buf_stop; /* downsample when we reach this index */
+#endif
+} my_prep_controller;
+
+typedef my_prep_controller * my_prep_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+
+ if (pass_mode != JBUF_PASS_THRU)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Initialize total-height counter for detecting bottom of image */
+ prep->rows_to_go = cinfo->image_height;
+ /* Mark the conversion buffer empty */
+ prep->next_buf_row = 0;
+#ifdef CONTEXT_ROWS_SUPPORTED
+ /* Preset additional state variables for context mode.
+ * These aren't used in non-context mode, so we needn't test which mode.
+ */
+ prep->this_row_group = 0;
+ /* Set next_buf_stop to stop after two row groups have been read in. */
+ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
+#endif
+}
+
+
+/*
+ * Expand an image vertically from height input_rows to height output_rows,
+ * by duplicating the bottom row.
+ */
+
+LOCAL(void)
+expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
+ int input_rows, int output_rows)
+{
+ register int row;
+
+ for (row = input_rows; row < output_rows; row++) {
+ jcopy_sample_rows(image_data, input_rows-1, image_data, row,
+ 1, num_cols);
+ }
+}
+
+
+/*
+ * Process some data in the simple no-context case.
+ *
+ * Preprocessor output data is counted in "row groups". A row group
+ * is defined to be v_samp_factor sample rows of each component.
+ * Downsampling will produce this much data from each max_v_samp_factor
+ * input rows.
+ */
+
+METHODDEF(void)
+pre_process_data (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ JDIMENSION inrows;
+ jpeg_component_info * compptr;
+
+ while (*in_row_ctr < in_rows_avail &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ /* If at bottom of image, pad to fill the conversion buffer. */
+ if (prep->rows_to_go == 0 &&
+ prep->next_buf_row < cinfo->max_v_samp_factor) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, cinfo->max_v_samp_factor);
+ }
+ prep->next_buf_row = cinfo->max_v_samp_factor;
+ }
+ /* If we've filled the conversion buffer, empty it. */
+ if (prep->next_buf_row == cinfo->max_v_samp_factor) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf, (JDIMENSION) 0,
+ output_buf, *out_row_group_ctr);
+ prep->next_buf_row = 0;
+ (*out_row_group_ctr)++;
+ }
+ /* If at bottom of image, pad the output to a full iMCU height.
+ * Note we assume the caller is providing a one-iMCU-height output buffer!
+ */
+ if (prep->rows_to_go == 0 &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ expand_bottom_edge(output_buf[ci],
+ compptr->width_in_data_units * cinfo->data_unit,
+ (int) (*out_row_group_ctr * compptr->v_samp_factor),
+ (int) (out_row_groups_avail * compptr->v_samp_factor));
+ }
+ *out_row_group_ctr = out_row_groups_avail;
+ break; /* can exit outer loop without test */
+ }
+ }
+}
+
+
+#ifdef CONTEXT_ROWS_SUPPORTED
+
+/*
+ * Process some data in the context case.
+ */
+
+METHODDEF(void)
+pre_process_context (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ int buf_height = cinfo->max_v_samp_factor * 3;
+ JDIMENSION inrows;
+
+ while (*out_row_group_ctr < out_row_groups_avail) {
+ if (*in_row_ctr < in_rows_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = prep->next_buf_stop - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ /* Pad at top of image, if first time through */
+ if (prep->rows_to_go == cinfo->image_height) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ int row;
+ for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
+ jcopy_sample_rows(prep->color_buf[ci], 0,
+ prep->color_buf[ci], -row,
+ 1, cinfo->image_width);
+ }
+ }
+ }
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ } else {
+ /* Return for more data, unless we are at the bottom of the image. */
+ if (prep->rows_to_go != 0)
+ break;
+ /* When at bottom of image, pad to fill the conversion buffer. */
+ if (prep->next_buf_row < prep->next_buf_stop) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, prep->next_buf_stop);
+ }
+ prep->next_buf_row = prep->next_buf_stop;
+ }
+ }
+ /* If we've gotten enough data, downsample a row group. */
+ if (prep->next_buf_row == prep->next_buf_stop) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf,
+ (JDIMENSION) prep->this_row_group,
+ output_buf, *out_row_group_ctr);
+ (*out_row_group_ctr)++;
+ /* Advance pointers with wraparound as necessary. */
+ prep->this_row_group += cinfo->max_v_samp_factor;
+ if (prep->this_row_group >= buf_height)
+ prep->this_row_group = 0;
+ if (prep->next_buf_row >= buf_height)
+ prep->next_buf_row = 0;
+ prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
+ }
+ }
+}
+
+
+/*
+ * Create the wrapped-around downsampling input buffer needed for context mode.
+ */
+
+LOCAL(void)
+create_context_buffer (j_compress_ptr cinfo)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int rgroup_height = cinfo->max_v_samp_factor;
+ int ci, i;
+ jpeg_component_info * compptr;
+ JSAMPARRAY true_buffer, fake_buffer;
+
+ /* Grab enough space for fake row pointers for all the components;
+ * we need five row groups' worth of pointers for each component.
+ */
+ fake_buffer = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (cinfo->num_components * 5 * rgroup_height) *
+ SIZEOF(JSAMPROW));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate the actual buffer space (3 row groups) for this component.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ true_buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) (3 * rgroup_height));
+ /* Copy true buffer row pointers into the middle of the fake row array */
+ MEMCOPY(fake_buffer + rgroup_height, true_buffer,
+ 3 * rgroup_height * SIZEOF(JSAMPROW));
+ /* Fill in the above and below wraparound pointers */
+ for (i = 0; i < rgroup_height; i++) {
+ fake_buffer[i] = true_buffer[2 * rgroup_height + i];
+ fake_buffer[4 * rgroup_height + i] = true_buffer[i];
+ }
+ prep->color_buf[ci] = fake_buffer + rgroup_height;
+ fake_buffer += 5 * rgroup_height; /* point to space for next component */
+ }
+}
+
+#endif /* CONTEXT_ROWS_SUPPORTED */
+
+
+/*
+ * Initialize preprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_prep_ptr prep;
+ int ci;
+ jpeg_component_info * compptr;
+
+ if (need_full_buffer) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ prep = (my_prep_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_prep_controller));
+ cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+ prep->pub.start_pass = start_pass_prep;
+
+ /* Allocate the color conversion buffer.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ if (cinfo->downsample->need_context_rows) {
+ /* Set up to provide context rows */
+#ifdef CONTEXT_ROWS_SUPPORTED
+ prep->pub.pre_process_data = pre_process_context;
+ create_context_buffer(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* No context, just make it tall enough for one row group */
+ prep->pub.pre_process_data = pre_process_data;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_data_units * cinfo->data_unit *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcsample.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcsample.cpp
new file mode 100644
index 00000000..e0359b71
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcsample.cpp
@@ -0,0 +1,520 @@
+/*
+ * jcsample.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains downsampling routines.
+ *
+ * Downsampling input data is counted in "row groups". A row group
+ * is defined to be max_v_samp_factor pixel rows of each component,
+ * from which the downsampler produces v_samp_factor sample rows.
+ * A single row group is processed in each call to the downsampler module.
+ *
+ * The downsampler is responsible for edge-expansion of its output data
+ * to fill an integral number of DCT blocks horizontally. The source buffer
+ * may be modified if it is helpful for this purpose (the source buffer is
+ * allocated wide enough to correspond to the desired output width).
+ * The caller (the prep controller) is responsible for vertical padding.
+ *
+ * The downsampler may request "context rows" by setting need_context_rows
+ * during startup. In this case, the input arrays will contain at least
+ * one row group's worth of pixels above and below the passed-in data;
+ * the caller will create dummy rows at image top and bottom by replicating
+ * the first or last real pixel row.
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ *
+ * The downsampling algorithm used here is a simple average of the source
+ * pixels covered by the output pixel. The hi-falutin sampling literature
+ * refers to this as a "box filter". In general the characteristics of a box
+ * filter are not very good, but for the specific cases we normally use (1:1
+ * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
+ * nearly so bad. If you intend to use other sampling ratios, you'd be well
+ * advised to improve this code.
+ *
+ * A simple input-smoothing capability is provided. This is mainly intended
+ * for cleaning up color-dithered GIF input files (if you find it inadequate,
+ * we suggest using an external filtering program such as pnmconvol). When
+ * enabled, each input pixel P is replaced by a weighted sum of itself and its
+ * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
+ * where SF = (smoothing_factor / 1024).
+ * Currently, smoothing is only supported for 2h2v sampling factors.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Pointer to routine to downsample a single component */
+typedef JMETHOD(void, downsample1_ptr,
+ (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_downsampler pub; /* public fields */
+
+ /* Downsampling method pointers, one per component */
+ downsample1_ptr methods[MAX_COMPONENTS];
+} my_downsampler;
+
+typedef my_downsampler * my_downsample_ptr;
+
+
+/*
+ * Initialize for a downsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_downsample (j_compress_ptr cinfo)
+{
+ /* no work for now */
+}
+
+
+/*
+ * Expand a component horizontally from width input_cols to width output_cols,
+ * by duplicating the rightmost samples.
+ */
+
+LOCAL(void)
+expand_right_edge (JSAMPARRAY image_data, int num_rows,
+ JDIMENSION input_cols, JDIMENSION output_cols)
+{
+ register JSAMPROW ptr;
+ register JSAMPLE pixval;
+ register int count;
+ int row;
+ int numcols = (int) (output_cols - input_cols);
+
+ if (numcols > 0) {
+ for (row = 0; row < num_rows; row++) {
+ ptr = image_data[row] + input_cols;
+ pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
+ for (count = numcols; count > 0; count--)
+ *ptr++ = pixval;
+ }
+ }
+}
+
+
+/*
+ * Do downsampling for a whole row group (all components).
+ *
+ * In this version we simply downsample each component independently.
+ */
+
+METHODDEF(void)
+sep_downsample (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+{
+ my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JSAMPARRAY in_ptr, out_ptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ in_ptr = input_buf[ci] + in_row_index;
+ out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor);
+ (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * One row group is processed per call.
+ * This version handles arbitrary integral sampling ratios, without smoothing.
+ * Note that this version is not actually used for customary sampling ratios.
+ */
+
+METHODDEF(void)
+int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
+ JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
+ JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+ JSAMPROW inptr, outptr;
+ INT32 outvalue;
+
+ h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor;
+ v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor;
+ numpix = h_expand * v_expand;
+ numpix2 = numpix/2;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * h_expand);
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ for (outcol = 0, outcol_h = 0; outcol < output_cols;
+ outcol++, outcol_h += h_expand) {
+ outvalue = 0;
+ for (v = 0; v < v_expand; v++) {
+ inptr = input_data[inrow+v] + outcol_h;
+ for (h = 0; h < h_expand; h++) {
+ outvalue += (INT32) GETJSAMPLE(*inptr++);
+ }
+ }
+ *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+ }
+ inrow += v_expand;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ /* Copy the data */
+ jcopy_sample_rows(input_data, 0, output_data, 0,
+ cinfo->max_v_samp_factor, cinfo->image_width);
+ /* Edge-expand */
+ expand_right_edge(output_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, compptr->width_in_data_units * cinfo->data_unit);
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the common case of 2:1 horizontal and 1:1 vertical,
+ * without smoothing.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int outrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+ register JSAMPROW inptr, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr = input_data[outrow];
+ bias = 0; /* bias = 0,1,0,1,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ + bias) >> 1);
+ bias ^= 1; /* 0=>1, 1=>0 */
+ inptr += 2;
+ }
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+ register JSAMPROW inptr0, inptr1, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ bias = 1; /* bias = 1,2,1,2,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ + bias) >> 2);
+ bias ^= 3; /* 1=>2, 2=>1 */
+ inptr0 += 2; inptr1 += 2;
+ }
+ inrow += 2;
+ }
+}
+
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+ register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols * 2);
+
+ /* We don't bother to form the individual "smoothed" input pixel values;
+ * we can directly compute the output which is the average of the four
+ * smoothed values. Each of the four member pixels contributes a fraction
+ * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
+ * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
+ * output. The four corner-adjacent neighbor pixels contribute a fraction
+ * SF to just one smoothed pixel, or SF/4 to the final output; while the
+ * eight edge-adjacent neighbors contribute SF to each of two smoothed
+ * pixels, or SF/2 overall. In order to use integer arithmetic, these
+ * factors are scaled by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
+ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
+
+ inrow = 0;
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ above_ptr = input_data[inrow-1];
+ below_ptr = input_data[inrow+2];
+
+ /* Special case for first column: pretend column -1 is same as column 0 */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ /* sum of pixels directly mapped to this output element */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ /* sum of edge-neighbor pixels */
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
+ /* The edge-neighbors count twice as much as corner-neighbors */
+ neighsum += neighsum;
+ /* Add in the corner-neighbors */
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
+ /* form final output scaled up by 2^16 */
+ membersum = membersum * memberscale + neighsum * neighscale;
+ /* round, descale and output it */
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ inrow += 2;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int outrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_data_units * cinfo->data_unit;
+ register JSAMPROW inptr, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+ int colsum, lastcolsum, nextcolsum;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols);
+
+ /* Each of the eight neighbor pixels contributes a fraction SF to the
+ * smoothed pixel, while the main pixel contributes (1-8*SF). In order
+ * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
+ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
+
+ for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) {
+ outptr = output_data[outrow];
+ inptr = input_data[outrow];
+ above_ptr = input_data[outrow-1];
+ below_ptr = input_data[outrow+1];
+
+ /* Special case for first column */
+ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
+ GETJSAMPLE(*inptr);
+ membersum = GETJSAMPLE(*inptr++);
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = colsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ membersum = GETJSAMPLE(*inptr++);
+ above_ptr++; below_ptr++;
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + colsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ }
+}
+
+#endif /* INPUT_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Module initialization routine for downsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL(void)
+jinit_downsampler (j_compress_ptr cinfo)
+{
+ my_downsample_ptr downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean smoothok = TRUE;
+
+ downsample = (my_downsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_downsampler));
+ cinfo->downsample = (struct jpeg_downsampler *) downsample;
+ downsample->pub.start_pass = start_pass_downsample;
+ downsample->pub.downsample = sep_downsample;
+ downsample->pub.need_context_rows = FALSE;
+
+ if (cinfo->CCIR601_sampling)
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* Verify we can handle the sampling factors, and set up method pointers */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = fullsize_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = fullsize_downsample;
+ } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor == cinfo->max_v_samp_factor) {
+ smoothok = FALSE;
+ downsample->methods[ci] = h2v1_downsample;
+ } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor &&
+ compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = h2v2_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = h2v2_downsample;
+ } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 &&
+ (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) {
+ smoothok = FALSE;
+ downsample->methods[ci] = int_downsample;
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ }
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor && !smoothok)
+ TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
+#endif
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcscale.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcscale.cpp
new file mode 100644
index 00000000..6ab20e24
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcscale.cpp
@@ -0,0 +1,63 @@
+/*
+ * jcscale.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample downscaling by 2^Pt for lossless JPEG.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+METHODDEF(void)
+simple_downscale(j_compress_ptr cinfo,
+ JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+ int xindex;
+
+ for (xindex = 0; xindex < (int)width; xindex++)
+ output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(GETJSAMPLE(input_buf[xindex]),
+ cinfo->Al);
+}
+
+
+METHODDEF(void)
+noscale(j_compress_ptr cinfo,
+ JSAMPROW input_buf, JSAMPROW output_buf, JDIMENSION width)
+{
+ MEMCOPY(output_buf, input_buf, width * SIZEOF(JSAMPLE));
+ return;
+}
+
+
+METHODDEF(void)
+scaler_start_pass (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+ /* Set scaler function based on Pt */
+ if (cinfo->Al)
+ losslsc->scaler_scale = simple_downscale;
+ else
+ losslsc->scaler_scale = noscale;
+}
+
+
+GLOBAL(void)
+jinit_c_scaler (j_compress_ptr cinfo)
+{
+ j_lossless_c_ptr losslsc = (j_lossless_c_ptr) cinfo->codec;
+
+ losslsc->scaler_start_pass = scaler_start_pass;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jcshuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcshuff.cpp
new file mode 100644
index 00000000..71d8c39e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jcshuff.cpp
@@ -0,0 +1,662 @@
+/*
+ * jcshuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines for sequential JPEG.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU. To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+//#include "jchuff.h" /* Declarations shared with jc*huff.c */
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).put_buffer = (src).put_buffer, \
+ (dest).put_bits = (src).put_bits, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ savable_state saved; /* Bit buffer & DC state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+#ifdef ENTROPY_OPT_SUPPORTED /* Statistics tables for optimization */
+ long * dc_count_ptrs[NUM_HUFF_TBLS];
+ long * ac_count_ptrs[NUM_HUFF_TBLS];
+#endif
+} shuff_entropy_encoder;
+
+typedef shuff_entropy_encoder * shuff_entropy_ptr;
+
+/* Working state while writing an MCU.
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ savable_state cur; /* Current bit buffer & DC state */
+ j_compress_ptr cinfo; /* dump_buffer needs access to this */
+} working_state;
+
+
+/* Forward declarations */
+METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo));
+#ifdef ENTROPY_OPT_SUPPORTED
+METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo));
+#endif
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+ int ci, dctbl, actbl;
+ jpeg_component_info * compptr;
+
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ lossyc->entropy_encode_mcu = encode_mcu_gather;
+ lossyc->pub.entropy_finish_pass = finish_pass_gather;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ lossyc->entropy_encode_mcu = encode_mcu_huff;
+ lossyc->pub.entropy_finish_pass = finish_pass_huff;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (gather_statistics) {
+#ifdef ENTROPY_OPT_SUPPORTED
+ /* Check for invalid table indexes */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+ if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->dc_count_ptrs[dctbl] == NULL)
+ entropy->dc_count_ptrs[dctbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
+ if (entropy->ac_count_ptrs[actbl] == NULL)
+ entropy->ac_count_ptrs[actbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
+#endif
+ } else {
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Initialize bit buffer to empty */
+ entropy->saved.put_buffer = 0;
+ entropy->saved.put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/* Outputting bytes to the file */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte(state,val,action) \
+ { *(state)->next_output_byte++ = (JOCTET) (val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (! dump_buffer(state)) \
+ { action; } }
+
+
+LOCAL(boolean)
+dump_buffer (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+ struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (state->cinfo))
+ return FALSE;
+ /* After a successful buffer dump, must reset buffer pointers */
+ state->next_output_byte = dest->next_output_byte;
+ state->free_in_buffer = dest->free_in_buffer;
+ return TRUE;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = state->cur.put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte(state, c, return FALSE);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte(state, 0, return FALSE);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ state->cur.put_buffer = put_buffer; /* update state variables */
+ state->cur.put_bits = put_bits;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+flush_bits (working_state * state)
+{
+ if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */
+ return FALSE;
+ state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
+ state->cur.put_bits = 0;
+ return TRUE;
+}
+
+
+/* Encode a single block's worth of coefficients */
+
+LOCAL(boolean)
+encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl, c_derived_tbl *actbl)
+{
+ register int temp, temp2;
+ register int nbits;
+ register int k, r, i;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = temp2 = block[0] - last_dc_val;
+
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit the Huffman-coded symbol for the number of bits */
+ if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ if (! emit_bits(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
+ return FALSE;
+ r -= 16;
+ }
+
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit Huffman symbol for run length / number of bits */
+ i = (r << 4) + nbits;
+ if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (! emit_bits(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0]))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart (working_state * state, int restart_num)
+{
+ int ci;
+
+ if (! flush_bits(state))
+ return FALSE;
+
+ emit_byte(state, 0xFF, return FALSE);
+ emit_byte(state, JPEG_RST0 + restart_num, return FALSE);
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
+ state->cur.last_dc_val[ci] = 0;
+
+ /* The restart counter is not updated until we successfully write the MCU. */
+
+ return TRUE;
+}
+
+
+/*
+ * Encode and output one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+ working_state state;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Load up working state */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! emit_restart(&state, entropy->next_restart_num))
+ return FALSE;
+ }
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ if (! encode_one_block(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ return FALSE;
+ /* Update last_dc_val */
+ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ /* Completed MCU, so update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+ working_state state;
+
+ /* Load up working state ... flush_bits needs it */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Flush out the last data */
+ if (! flush_bits(&state))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+ /* Update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+#ifdef ENTROPY_OPT_SUPPORTED
+
+
+/* Process a single block's worth of coefficients */
+
+LOCAL(void)
+htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+ long dc_counts[], long ac_counts[])
+{
+ register int temp;
+ register int nbits;
+ register int k, r;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = block[0] - last_dc_val;
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count the Huffman symbol for the number of bits */
+ dc_counts[nbits]++;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ ac_counts[0xF0]++;
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count Huffman symbol for run length / number of bits */
+ ac_counts[(r << 4) + nbits]++;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ ac_counts[0]++;
+}
+
+
+/*
+ * Trial-encode one MCU's worth of Huffman-compressed coefficients.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(boolean)
+encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Take care of restart intervals if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Update restart state */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
+ entropy->dc_count_ptrs[compptr->dc_tbl_no],
+ entropy->ac_count_ptrs[compptr->ac_tbl_no]);
+ entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyc->entropy_private;
+ int ci, dctbl, actbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did_dc[NUM_HUFF_TBLS];
+ boolean did_ac[NUM_HUFF_TBLS];
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ MEMZERO(did_dc, SIZEOF(did_dc));
+ MEMZERO(did_ac, SIZEOF(did_ac));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (! did_dc[dctbl]) {
+ htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
+ did_dc[dctbl] = TRUE;
+ }
+ if (! did_ac[actbl]) {
+ htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
+ did_ac[actbl] = TRUE;
+ }
+ }
+}
+
+
+#endif /* ENTROPY_OPT_SUPPORTED */
+
+
+METHODDEF(boolean)
+need_optimization_pass (j_compress_ptr cinfo)
+{
+ return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_shuff_encoder (j_compress_ptr cinfo)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (shuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(shuff_entropy_encoder));
+ lossyc->entropy_private = (struct jpeg_entropy_encoder *) entropy;
+ lossyc->pub.entropy_start_pass = start_pass_huff;
+ lossyc->pub.need_optimization_pass = need_optimization_pass;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+#ifdef ENTROPY_OPT_SUPPORTED
+ entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
+#endif
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jctrans.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jctrans.cpp
new file mode 100644
index 00000000..64f54fff
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jctrans.cpp
@@ -0,0 +1,421 @@
+/*
+ * jctrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding compression,
+ * that is, writing raw DCT coefficient arrays to an output JPEG file.
+ * The routines in jcapimin.c will also be needed by a transcoder.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+
+
+/* Forward declarations */
+LOCAL(void) transencode_master_selection
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_codec
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_coef_controller
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+
+
+/*
+ * Compression initialization for writing raw-coefficient data.
+ * Before calling this, all parameters and a data destination must be set up.
+ * Call jpeg_finish_compress() to actually write the data.
+ *
+ * The number of passed virtual arrays must match cinfo->num_components.
+ * Note that the virtual arrays need not be filled or even realized at
+ * the time write_coefficients is called; indeed, if the virtual arrays
+ * were requested from this compression object's memory manager, they
+ * typically will be realized during this routine and filled afterwards.
+ */
+
+GLOBAL(void)
+jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Mark all tables to be written */
+ jpeg_suppress_tables(cinfo, FALSE);
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ transencode_master_selection(cinfo, coef_arrays);
+ /* Wait for jpeg_finish_compress() call */
+ cinfo->next_scanline = 0; /* so jpeg_write_marker works */
+ cinfo->global_state = CSTATE_WRCOEFS;
+}
+
+
+/*
+ * Initialize the compression object with default parameters,
+ * then copy from the source object all parameters needed for lossless
+ * transcoding. Parameters that can be varied without loss (such as
+ * scan script and Huffman optimization) are left in their default states.
+ */
+
+GLOBAL(void)
+jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo)
+{
+ JQUANT_TBL ** qtblptr;
+ jpeg_component_info *incomp, *outcomp;
+ JQUANT_TBL *c_quant, *slot_quant;
+ int tblno, ci, coefi;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (dstinfo->global_state != CSTATE_START)
+ ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
+ /* Copy fundamental image dimensions */
+ dstinfo->image_width = srcinfo->image_width;
+ dstinfo->image_height = srcinfo->image_height;
+ dstinfo->input_components = srcinfo->num_components;
+ dstinfo->in_color_space = srcinfo->jpeg_color_space;
+ /* Initialize all parameters to default values */
+ jpeg_set_defaults(dstinfo);
+ /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
+ * Fix it to get the right header markers for the image colorspace.
+ */
+ jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
+ dstinfo->data_precision = srcinfo->data_precision;
+ dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
+ /* Copy the source's quantization tables. */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
+ qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
+ MEMCOPY((*qtblptr)->quantval,
+ srcinfo->quant_tbl_ptrs[tblno]->quantval,
+ SIZEOF((*qtblptr)->quantval));
+ (*qtblptr)->sent_table = FALSE;
+ }
+ }
+ /* Copy the source's per-component info.
+ * Note we assume jpeg_set_defaults has allocated the dest comp_info array.
+ */
+ dstinfo->num_components = srcinfo->num_components;
+ if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
+ ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
+ outcomp->component_id = incomp->component_id;
+ outcomp->h_samp_factor = incomp->h_samp_factor;
+ outcomp->v_samp_factor = incomp->v_samp_factor;
+ outcomp->quant_tbl_no = incomp->quant_tbl_no;
+ /* Make sure saved quantization table for component matches the qtable
+ * slot. If not, the input file re-used this qtable slot.
+ * IJG encoder currently cannot duplicate this.
+ */
+ tblno = outcomp->quant_tbl_no;
+ if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
+ srcinfo->quant_tbl_ptrs[tblno] == NULL)
+ ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
+ slot_quant = srcinfo->quant_tbl_ptrs[tblno];
+ c_quant = incomp->quant_table;
+ if (c_quant != NULL) {
+ for (coefi = 0; coefi < DCTSIZE2; coefi++) {
+ if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
+ ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
+ }
+ }
+ /* Note: we do not copy the source's Huffman table assignments;
+ * instead we rely on jpeg_set_colorspace to have made a suitable choice.
+ */
+ }
+ /* Also copy JFIF version and resolution information, if available.
+ * Strictly speaking this isn't "critical" info, but it's nearly
+ * always appropriate to copy it if available. In particular,
+ * if the application chooses to copy JFIF 1.02 extension markers from
+ * the source file, we need to copy the version to make sure we don't
+ * emit a file that has 1.02 extensions but a claimed version of 1.01.
+ * We will *not*, however, copy version info from mislabeled "2.01" files.
+ */
+ if (srcinfo->saw_JFIF_marker) {
+ if (srcinfo->JFIF_major_version == 1) {
+ dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
+ dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
+ }
+ dstinfo->density_unit = srcinfo->density_unit;
+ dstinfo->X_density = srcinfo->X_density;
+ dstinfo->Y_density = srcinfo->Y_density;
+ }
+}
+
+
+/*
+ * Master selection of compression modules for transcoding.
+ * This substitutes for jcinit.c's initialization of the full compressor.
+ */
+
+LOCAL(void)
+transencode_master_selection (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ cinfo->data_unit = DCTSIZE;
+ /* Although we don't actually use input_components for transcoding,
+ * jcmaster.c's initial_setup will complain if input_components is 0.
+ */
+ cinfo->input_components = 1;
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, TRUE /* transcode only */);
+
+ /* We need a special compression codec. */
+ transencode_codec(cinfo, coef_arrays);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI, JFIF) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
+
+
+/*
+ * The rest of this file is a special implementation of the coefficient
+ * buffer controller. This is similar to jccoefct.c, but it handles only
+ * output from presupplied virtual arrays. Furthermore, we generate any
+ * dummy padding blocks on-the-fly rather than expecting them to be present
+ * in the arrays.
+ */
+
+/* Private buffer controller object */
+
+typedef struct {
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* Virtual block array for each component. */
+ jvirt_barray_ptr * whole_image;
+
+ /* Workspace for constructing dummy blocks at right/bottom edges. */
+ JBLOCKROW dummy_buffer[C_MAX_DATA_UNITS_IN_MCU];
+} c_coef_controller;
+
+typedef c_coef_controller * c_coef_ptr;
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+
+ if (pass_mode != JBUF_CRANK_DEST)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Process some data.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef = (c_coef_ptr) lossyc->coef_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, blockcnt;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW MCU_buffer[C_MAX_DATA_UNITS_IN_MCU];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yindex+yoffset < compptr->last_row_height) {
+ /* Fill in pointers to real blocks in this row */
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < blockcnt; xindex++)
+ MCU_buffer[blkn++] = buffer_ptr++;
+ } else {
+ /* At bottom of image, need a whole row of dummy blocks */
+ xindex = 0;
+ }
+ /* Fill in any dummy blocks needed in this row.
+ * Dummy blocks are filled in the same way as in jccoefct.c:
+ * all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. The init routine has already zeroed the
+ * AC entries, so we need only set the DC entries correctly.
+ */
+ for (; xindex < compptr->MCU_width; xindex++) {
+ MCU_buffer[blkn] = coef->dummy_buffer[blkn];
+ MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+ blkn++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*lossyc->entropy_encode_mcu) (cinfo, MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Initialize coefficient buffer controller.
+ *
+ * Each passed coefficient array must be the right size for that
+ * coefficient: width_in_data_units wide and height_in_data_units high,
+ * with unitheight at least v_samp_factor.
+ */
+
+LOCAL(void)
+transencode_coef_controller (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ j_lossy_c_ptr lossyc = (j_lossy_c_ptr) cinfo->codec;
+ c_coef_ptr coef;
+ JBLOCKROW buffer;
+ int i;
+
+ coef = (c_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_coef_controller));
+ lossyc->coef_private = (struct jpeg_c_coef_controller *) coef;
+
+ /* Save pointer to virtual arrays */
+ coef->whole_image = coef_arrays;
+
+ /* Allocate and pre-zero space for dummy DCT blocks. */
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+ jzero_far((void FAR *) buffer, C_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_DATA_UNITS_IN_MCU; i++) {
+ coef->dummy_buffer[i] = buffer + i;
+ }
+}
+
+
+/*
+ * Initialize the transencoer codec.
+ * This is called only once, during master selection.
+ */
+
+LOCAL(void)
+transencode_codec (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ j_lossy_c_ptr lossyc;
+
+ /* Create subobject in permanent pool */
+ lossyc = (j_lossy_c_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(jpeg_lossy_c_codec));
+ cinfo->codec = (struct jpeg_c_codec *) lossyc;
+
+ /* Initialize sub-modules */
+
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ jinit_phuff_encoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_shuff_encoder(cinfo);
+ }
+
+ /* We need a special coefficient buffer controller. */
+ transencode_coef_controller(cinfo, coef_arrays);
+
+ /* Initialize method pointers */
+ lossyc->pub.start_pass = start_pass_coef;
+ lossyc->pub.compress_data = compress_output;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapimin.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapimin.cpp
new file mode 100644
index 00000000..5f5b7135
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapimin.cpp
@@ -0,0 +1,402 @@
+/*
+ * jdapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-decompression case or the
+ * transcoding-only case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jdapistd.c. But also see jcomapi.c for routines
+ * shared by compression and decompression, and jdtrans.c for the transcoding
+ * case.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG decompression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_decompress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = TRUE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->src = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++)
+ cinfo->quant_tbl_ptrs[i] = NULL;
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ /* Initialize marker processor so application can override methods
+ * for COM, APPn markers before calling jpeg_read_header.
+ */
+ cinfo->marker_list = NULL;
+ jinit_marker_reader(cinfo);
+
+ /* And initialize the overall input controller. */
+ jinit_input_controller(cinfo);
+
+ /* OK, I'm ready */
+ cinfo->global_state = DSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG decompression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG decompression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Set default decompression parameters.
+ */
+
+LOCAL(void)
+default_decompress_parms (j_decompress_ptr cinfo)
+{
+ /* Guess the input colorspace, and set output colorspace accordingly. */
+ /* (Wish JPEG committee had provided a real way to specify this...) */
+ /* Note application may override our guesses. */
+ switch (cinfo->num_components) {
+ case 1:
+ cinfo->jpeg_color_space = JCS_GRAYSCALE;
+ cinfo->out_color_space = JCS_GRAYSCALE;
+ break;
+
+ case 3:
+ if (cinfo->saw_JFIF_marker) {
+ cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
+ } else if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_RGB;
+ break;
+ case 1:
+ cinfo->jpeg_color_space = JCS_YCbCr;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ break;
+ }
+ } else {
+ /* Saw no special markers, try to guess from the component IDs */
+ int cid0 = cinfo->comp_info[0].component_id;
+ int cid1 = cinfo->comp_info[1].component_id;
+ int cid2 = cinfo->comp_info[2].component_id;
+
+ if (cid0 == 1 && cid1 == 2 && cid2 == 3)
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+ else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
+ cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+ else {
+ if (cinfo->process == JPROC_LOSSLESS) {
+ TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSLESS_IDS, cid0, cid1, cid2);
+ cinfo->jpeg_color_space = JCS_RGB; /* assume it's RGB */
+ }
+ else { /* Lossy processes */
+ TRACEMS3(cinfo, 1, JTRC_UNKNOWN_LOSSY_IDS, cid0, cid1, cid2);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ }
+ }
+ }
+ /* Always guess RGB is proper output colorspace. */
+ cinfo->out_color_space = JCS_RGB;
+ break;
+
+ case 4:
+ if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_CMYK;
+ break;
+ case 2:
+ cinfo->jpeg_color_space = JCS_YCCK;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+ break;
+ }
+ } else {
+ /* No special markers, assume straight CMYK. */
+ cinfo->jpeg_color_space = JCS_CMYK;
+ }
+ cinfo->out_color_space = JCS_CMYK;
+ break;
+
+ default:
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->out_color_space = JCS_UNKNOWN;
+ break;
+ }
+
+ /* Set defaults for other decompression parameters. */
+ cinfo->scale_num = 1; /* 1:1 scaling */
+ cinfo->scale_denom = 1;
+ cinfo->output_gamma = 1.0;
+ cinfo->buffered_image = FALSE;
+ cinfo->raw_data_out = FALSE;
+ cinfo->dct_method = JDCT_DEFAULT;
+ cinfo->do_fancy_upsampling = TRUE;
+ cinfo->do_block_smoothing = TRUE;
+ cinfo->quantize_colors = FALSE;
+ /* We set these in case application only sets quantize_colors. */
+ cinfo->dither_mode = JDITHER_FS;
+#ifdef QUANT_2PASS_SUPPORTED
+ cinfo->two_pass_quantize = TRUE;
+#else
+ cinfo->two_pass_quantize = FALSE;
+#endif
+ cinfo->desired_number_of_colors = 256;
+ cinfo->colormap = NULL;
+ /* Initialize for no mode change in buffered-image mode. */
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+}
+
+
+/*
+ * Decompression startup: read start of JPEG datastream to see what's there.
+ * Need only initialize JPEG object and supply a data source before calling.
+ *
+ * This routine will read as far as the first SOS marker (ie, actual start of
+ * compressed data), and will save all tables and parameters in the JPEG
+ * object. It will also initialize the decompression parameters to default
+ * values, and finally return JPEG_HEADER_OK. On return, the application may
+ * adjust the decompression parameters and then call jpeg_start_decompress.
+ * (Or, if the application only wanted to determine the image parameters,
+ * the data need not be decompressed. In that case, call jpeg_abort or
+ * jpeg_destroy to release any temporary space.)
+ * If an abbreviated (tables only) datastream is presented, the routine will
+ * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
+ * re-use the JPEG object to read the abbreviated image datastream(s).
+ * It is unnecessary (but OK) to call jpeg_abort in this case.
+ * The JPEG_SUSPENDED return code only occurs if the data source module
+ * requests suspension of the decompressor. In this case the application
+ * should load more source data and then re-call jpeg_read_header to resume
+ * processing.
+ * If a non-suspending data source is used and require_image is TRUE, then the
+ * return code need not be inspected since only JPEG_HEADER_OK is possible.
+ *
+ * This routine is now just a front end to jpeg_consume_input, with some
+ * extra error checking.
+ */
+
+GLOBAL(int)
+jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+{
+ int retcode;
+
+ if (cinfo->global_state != DSTATE_START &&
+ cinfo->global_state != DSTATE_INHEADER)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ retcode = jpeg_consume_input(cinfo);
+
+ switch (retcode) {
+ case JPEG_REACHED_SOS:
+ retcode = JPEG_HEADER_OK;
+ break;
+ case JPEG_REACHED_EOI:
+ if (require_image) /* Complain if application wanted an image */
+ ERREXIT(cinfo, JERR_NO_IMAGE);
+ /* Reset to start state; it would be safer to require the application to
+ * call jpeg_abort, but we can't change it now for compatibility reasons.
+ * A side effect is to free any temporary memory (there shouldn't be any).
+ */
+ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+ retcode = JPEG_HEADER_TABLES_ONLY;
+ break;
+ case JPEG_SUSPENDED:
+ /* no work */
+ break;
+ }
+
+ return retcode;
+}
+
+
+/*
+ * Consume data in advance of what the decompressor requires.
+ * This can be called at any time once the decompressor object has
+ * been created and a data source has been set up.
+ *
+ * This routine is essentially a state machine that handles a couple
+ * of critical state-transition actions, namely initial setup and
+ * transition from header scanning to ready-for-start_decompress.
+ * All the actual input is done via the input controller's consume_input
+ * method.
+ */
+
+GLOBAL(int)
+jpeg_consume_input (j_decompress_ptr cinfo)
+{
+ int retcode = JPEG_SUSPENDED;
+
+ /* NB: every possible DSTATE value should be listed in this switch */
+ switch (cinfo->global_state) {
+ case DSTATE_START:
+ /* Start-of-datastream actions: reset appropriate modules */
+ (*cinfo->inputctl->reset_input_controller) (cinfo);
+ /* Initialize application's data source module */
+ (*cinfo->src->init_source) (cinfo);
+ cinfo->global_state = DSTATE_INHEADER;
+ /*FALLTHROUGH*/
+ case DSTATE_INHEADER:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
+ /* Set up default parameters based on header data */
+ default_decompress_parms(cinfo);
+ /* Set global state: ready for start_decompress */
+ cinfo->global_state = DSTATE_READY;
+ }
+ break;
+ case DSTATE_READY:
+ /* Can't advance past first SOS until start_decompress is called */
+ retcode = JPEG_REACHED_SOS;
+ break;
+ case DSTATE_PRELOAD:
+ case DSTATE_PRESCAN:
+ case DSTATE_SCANNING:
+ case DSTATE_RAW_OK:
+ case DSTATE_BUFIMAGE:
+ case DSTATE_BUFPOST:
+ case DSTATE_STOPPING:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ break;
+ default:
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ return retcode;
+}
+
+
+/*
+ * Have we finished reading the input file?
+ */
+
+GLOBAL(boolean)
+jpeg_input_complete (j_decompress_ptr cinfo)
+{
+ /* Check for valid jpeg object */
+ if (cinfo->global_state < DSTATE_START ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->eoi_reached;
+}
+
+
+/*
+ * Is there more than one scan?
+ */
+
+GLOBAL(boolean)
+jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+{
+ /* Only valid after jpeg_read_header completes */
+ if (cinfo->global_state < DSTATE_READY ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->has_multiple_scans;
+}
+
+
+/*
+ * Finish JPEG decompression.
+ *
+ * This will normally just verify the file trailer and release temp storage.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_decompress (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+ /* Terminate final pass of non-buffered mode */
+ if (cinfo->output_scanline < cinfo->output_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state == DSTATE_BUFIMAGE) {
+ /* Finishing after a buffered-image operation */
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state != DSTATE_STOPPING) {
+ /* STOPPING = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read until EOI */
+ while (! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ /* Do final cleanup */
+ (*cinfo->src->term_source) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+ return TRUE;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapistd.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapistd.cpp
new file mode 100644
index 00000000..1d09b49e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdapistd.cpp
@@ -0,0 +1,276 @@
+/*
+ * jdapistd.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-decompression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_decompress, it will end up linking in the entire decompressor.
+ * We thus must separate this file from jdapimin.c to avoid linking the
+ * whole decompression library into a transcoder.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Decompression initialization.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * If a multipass operating mode was selected, this will do all but the
+ * last pass, and thus may take a great deal of time.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_start_decompress (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize master control, select active modules */
+ jinit_master_decompress(cinfo);
+ if (cinfo->buffered_image) {
+ /* No more work here; expecting jpeg_start_output next */
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+ }
+ cinfo->global_state = DSTATE_PRELOAD;
+ }
+ if (cinfo->global_state == DSTATE_PRELOAD) {
+ /* If file has multiple scans, absorb them all into the coef buffer */
+ if (cinfo->inputctl->has_multiple_scans) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return FALSE;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* jdmaster underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+ }
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ } else if (cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any dummy output passes, and set up for the final pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Set up for an output pass, and perform any dummy pass(es) needed.
+ * Common subroutine for jpeg_start_decompress and jpeg_start_output.
+ * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
+ * Exit: If done, returns TRUE and sets global_state for proper output mode.
+ * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
+ */
+
+LOCAL(boolean)
+output_pass_setup (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state != DSTATE_PRESCAN) {
+ /* First call: do pass setup */
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+ cinfo->global_state = DSTATE_PRESCAN;
+ }
+ /* Loop over any required dummy passes */
+ while (cinfo->master->is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Crank through the dummy pass */
+ while (cinfo->output_scanline < cinfo->output_height) {
+ JDIMENSION last_scanline;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* Process some data */
+ last_scanline = cinfo->output_scanline;
+ (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
+ &cinfo->output_scanline, (JDIMENSION) 0);
+ if (cinfo->output_scanline == last_scanline)
+ return FALSE; /* No progress made, must suspend */
+ }
+ /* Finish up dummy pass, and set up for another one */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ }
+ /* Ready for application to drive output pass through
+ * jpeg_read_scanlines or jpeg_read_raw_data.
+ */
+ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
+ return TRUE;
+}
+
+
+/*
+ * Read some scanlines of data from the JPEG decompressor.
+ *
+ * The return value will be the number of lines actually read.
+ * This may be less than the number requested in several cases,
+ * including bottom of image, data source suspension, and operating
+ * modes that emit multiple scanlines at a time.
+ *
+ * Note: we warn about excess calls to jpeg_read_scanlines() since
+ * this likely signals an application programmer error. However,
+ * an oversize buffer (max_lines > scanlines remaining) is not an error.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION max_lines)
+{
+ JDIMENSION row_ctr;
+
+ if (cinfo->global_state != DSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Process some data */
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
+ cinfo->output_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to read raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != DSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Verify that at least one iMCU row can be returned. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_codec_data_unit;
+ if (max_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Decompress directly into user's buffer. */
+ if (! (*cinfo->codec->decompress_data) (cinfo, data))
+ return 0; /* suspension forced, can do nothing more */
+
+ /* OK, we processed one iMCU row. */
+ cinfo->output_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
+
+
+/* Additional entry points for buffered-image mode. */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Initialize for an output pass in buffered-image mode.
+ */
+
+GLOBAL(boolean)
+jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+{
+ if (cinfo->global_state != DSTATE_BUFIMAGE &&
+ cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Limit scan number to valid range */
+ if (scan_number <= 0)
+ scan_number = 1;
+ if (cinfo->inputctl->eoi_reached &&
+ scan_number > cinfo->input_scan_number)
+ scan_number = cinfo->input_scan_number;
+ cinfo->output_scan_number = scan_number;
+ /* Perform any dummy output passes, and set up for the real pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Finish up after an output pass in buffered-image mode.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_output (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
+ /* Terminate this pass. */
+ /* We do not require the whole pass to have been completed. */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_BUFPOST;
+ } else if (cinfo->global_state != DSTATE_BUFPOST) {
+ /* BUFPOST = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read markers looking for SOS or EOI */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatadst.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatadst.cpp
new file mode 100644
index 00000000..ae3a213e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatadst.cpp
@@ -0,0 +1,152 @@
+/*
+ * jdatadst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression data destination routines for the case of
+ * emitting JPEG data to a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * destination manager.
+ * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
+ * JOCTETs into 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+#include "stdafx.h"
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jerror.h"
+
+
+/* Expanded data destination object for stdio output */
+
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ FILE * outfile; /* target stream */
+ JOCTET * buffer; /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines). The
+ * application should resume compression after it has made more room in the
+ * output buffer. Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
+ (size_t) OUTPUT_BUF_SIZE)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written. Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ fflush(dest->outfile);
+ /* Make sure we wrote the output file OK */
+ if (ferror(dest->outfile))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
+{
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatasrc.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatasrc.cpp
new file mode 100644
index 00000000..20f665e4
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdatasrc.cpp
@@ -0,0 +1,213 @@
+/*
+ * jdatasrc.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression data source routines for the case of
+ * reading JPEG data from a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * source manager.
+ * IMPORTANT: we assume that fread() will correctly transcribe an array of
+ * JOCTETs from 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+#include "stdafx.h"
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jerror.h"
+
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ FILE * infile; /* source stream */
+ JOCTET * buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
+
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = TRUE;
+}
+
+
+/*
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded. It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return. If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer. In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there. However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later. In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any). The application should resume
+ * decompression after it has loaded more data into the input buffer. Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ */
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return. If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ */
+
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ /* note we assume that fill_input_buffer will never return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+
+/*
+ * An additional method that can be provided by data source modules is the
+ * resync_to_restart method for error recovery in the presence of RST markers.
+ * For the moment, this source module just uses the default resync method
+ * provided by the JPEG library. That method assumes that no backtracking
+ * is possible.
+ */
+
+
+/*
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read. Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo)
+{
+ /* no work necessary here */
+}
+
+
+/*
+ * Prepare for input from a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing decompression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
+{
+ my_src_ptr src;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ INPUT_BUF_SIZE * SIZEOF(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcoefct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcoefct.cpp
new file mode 100644
index 00000000..a2f479b9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcoefct.cpp
@@ -0,0 +1,744 @@
+/*
+ * jdcoefct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for decompression.
+ * This controller is the top level of the lossy JPEG decompressor proper.
+ * The coefficient buffer lies between entropy decoding and inverse-DCT steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ * Also, the input side (only) is used when reading a file for transcoding.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h"
+
+/* Block smoothing is only applicable for progressive JPEG, so: */
+#ifndef D_PROGRESSIVE_SUPPORTED
+#undef BLOCK_SMOOTHING_SUPPORTED
+#endif
+
+/* Private buffer controller object */
+
+typedef struct {
+ /* These variables keep track of the current location of the input side. */
+ /* cinfo->input_iMCU_row is also used for this. */
+ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+ /* In single-pass modes, it's sufficient to buffer just one MCU.
+ * We allocate a workspace of D_MAX_DATA_UNITS_IN_MCU coefficient blocks,
+ * and let the entropy decoder write into that workspace each time.
+ * (On 80x86, the workspace is FAR even though it's not really very big;
+ * this is to keep the module interfaces unchanged when a large coefficient
+ * buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays; it is used only by the input side.
+ */
+ JBLOCKROW MCU_buffer[D_MAX_DATA_UNITS_IN_MCU];
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+#endif
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* When doing block smoothing, we latch coefficient Al values here */
+ int * coef_bits_latch;
+#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
+#endif
+} d_coef_controller;
+
+typedef d_coef_controller * d_coef_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_onepass
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) decompress_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
+METHODDEF(int) decompress_smooth_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->MCU_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->input_iMCU_row = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+
+ /* If multipass, check to see whether to use block smoothing on this pass */
+ if (lossyd->coef_arrays != NULL) {
+ if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
+ lossyd->pub.decompress_data = decompress_smooth_data;
+ else
+ lossyd->pub.decompress_data = decompress_data;
+ }
+#endif
+ cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the single-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, useful_width;
+ JSAMPARRAY output_ptr;
+ JDIMENSION start_col, output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Loop to process as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
+ jzero_far((void FAR *) coef->MCU_buffer[0],
+ (size_t) (cinfo->data_units_in_MCU * SIZEOF(JBLOCK)));
+ if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ /* Determine where data should go in output_buf and do the IDCT thing.
+ * We skip dummy blocks at the right and bottom edges (but blkn gets
+ * incremented past them!). Note the inner loop relies on having
+ * allocated the MCU_buffer[] blocks sequentially.
+ */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed) {
+ blkn += compptr->MCU_data_units;
+ continue;
+ }
+ inverse_DCT = lossyd->inverse_DCT[compptr->component_index];
+ useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ output_ptr = output_buf[compptr->component_index] +
+ yoffset * compptr->codec_data_unit;
+ start_col = MCU_col_num * compptr->MCU_sample_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (cinfo->input_iMCU_row < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ output_col = start_col;
+ for (xindex = 0; xindex < useful_width; xindex++) {
+ (*inverse_DCT) (cinfo, compptr,
+ (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ output_ptr, output_col);
+ output_col += compptr->codec_data_unit;
+ }
+ }
+ blkn += compptr->MCU_width;
+ output_ptr += compptr->codec_data_unit;
+ }
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ cinfo->output_iMCU_row++;
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+ return JPEG_SUSPENDED; /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image coefficient buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor block rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ cinfo->input_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Note: entropy decoder expects buffer to be zeroed,
+ * but this is handled automatically by the memory manager
+ * because we requested a pre-zeroed array.
+ */
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to fetch the MCU. */
+ if (! (*lossyd->entropy_decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Decompress and return some data in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num;
+ int ci, block_row, block_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number < cinfo->output_scan_number ||
+ (cinfo->input_scan_number == cinfo->output_scan_number &&
+ cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ cinfo->output_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ inverse_DCT = lossyd->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ output_col = 0;
+ for (block_num = 0; block_num < compptr->width_in_data_units; block_num++) {
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
+ output_ptr, output_col);
+ buffer_ptr++;
+ output_col += compptr->codec_data_unit;
+ }
+ output_ptr += compptr->codec_data_unit;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+/*
+ * This code applies interblock smoothing as described by section K.8
+ * of the JPEG standard: the first 5 AC coefficients are estimated from
+ * the DC values of a DCT block and its 8 neighboring blocks.
+ * We apply smoothing only for progressive JPEG decoding, and only if
+ * the coefficients it can estimate are not yet known to full precision.
+ */
+
+/* Natural-order array positions of the first 5 zigzag-order coefficients */
+#define Q01_POS 1
+#define Q10_POS 8
+#define Q20_POS 16
+#define Q11_POS 9
+#define Q02_POS 2
+
+/*
+ * Determine whether block smoothing is applicable and safe.
+ * We also latch the current states of the coef_bits[] entries for the
+ * AC coefficients; otherwise, if the input side of the decompressor
+ * advances into a new scan, we might think the coefficients are known
+ * more accurately than they really are.
+ */
+
+LOCAL(boolean)
+smoothing_ok (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+ boolean smoothing_useful = FALSE;
+ int ci, coefi;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtable;
+ int * coef_bits;
+ int * coef_bits_latch;
+
+ if (! cinfo->process == JPROC_PROGRESSIVE || cinfo->coef_bits == NULL)
+ return FALSE;
+
+ /* Allocate latch area if not already done */
+ if (coef->coef_bits_latch == NULL)
+ coef->coef_bits_latch = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components *
+ (SAVED_COEFS * SIZEOF(int)));
+ coef_bits_latch = coef->coef_bits_latch;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* All components' quantization values must already be latched. */
+ if ((qtable = compptr->quant_table) == NULL)
+ return FALSE;
+ /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+ if (qtable->quantval[0] == 0 ||
+ qtable->quantval[Q01_POS] == 0 ||
+ qtable->quantval[Q10_POS] == 0 ||
+ qtable->quantval[Q20_POS] == 0 ||
+ qtable->quantval[Q11_POS] == 0 ||
+ qtable->quantval[Q02_POS] == 0)
+ return FALSE;
+ /* DC values must be at least partly known for all components. */
+ coef_bits = cinfo->coef_bits[ci];
+ if (coef_bits[0] < 0)
+ return FALSE;
+ /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
+ for (coefi = 1; coefi <= 5; coefi++) {
+ coef_bits_latch[coefi] = coef_bits[coefi];
+ if (coef_bits[coefi] != 0)
+ smoothing_useful = TRUE;
+ }
+ coef_bits_latch += SAVED_COEFS;
+ }
+
+ return smoothing_useful;
+}
+
+
+/*
+ * Variant of decompress_data for use when doing block smoothing.
+ */
+
+METHODDEF(int)
+decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef = (d_coef_ptr) lossyd->coef_private;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num, last_block_column;
+ int ci, block_row, block_rows, access_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+ boolean first_row, last_row;
+ JBLOCK workspace;
+ int *coef_bits;
+ JQUANT_TBL *quanttbl;
+ INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
+ int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+ int Al, pred;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if (cinfo->input_scan_number == cinfo->output_scan_number) {
+ /* If input is working on current scan, we ordinarily want it to
+ * have completed the current row. But if input scan is DC,
+ * we want it to keep one row ahead so that next block row's DC
+ * values are up to date.
+ */
+ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
+ if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+ break;
+ }
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row) {
+ block_rows = compptr->v_samp_factor;
+ access_rows = block_rows * 2; /* this and next iMCU row */
+ last_row = FALSE;
+ } else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ access_rows = block_rows; /* this iMCU row only */
+ last_row = TRUE;
+ }
+ /* Align the virtual buffer for this component. */
+ if (cinfo->output_iMCU_row > 0) {
+ access_rows += compptr->v_samp_factor; /* prior iMCU row too */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
+ (JDIMENSION) access_rows, FALSE);
+ buffer += compptr->v_samp_factor; /* point to current iMCU row */
+ first_row = FALSE;
+ } else {
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
+ first_row = TRUE;
+ }
+ /* Fetch component-dependent info */
+ coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
+ quanttbl = compptr->quant_table;
+ Q00 = quanttbl->quantval[0];
+ Q01 = quanttbl->quantval[Q01_POS];
+ Q10 = quanttbl->quantval[Q10_POS];
+ Q20 = quanttbl->quantval[Q20_POS];
+ Q11 = quanttbl->quantval[Q11_POS];
+ Q02 = quanttbl->quantval[Q02_POS];
+ inverse_DCT = lossyd->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ if (first_row && block_row == 0)
+ prev_block_row = buffer_ptr;
+ else
+ prev_block_row = buffer[block_row-1];
+ if (last_row && block_row == block_rows-1)
+ next_block_row = buffer_ptr;
+ else
+ next_block_row = buffer[block_row+1];
+ /* We fetch the surrounding DC values using a sliding-register approach.
+ * Initialize all nine here so as to do the right thing on narrow pics.
+ */
+ DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
+ DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
+ DC7 = DC8 = DC9 = (int) next_block_row[0][0];
+ output_col = 0;
+ last_block_column = compptr->width_in_data_units - 1;
+ for (block_num = 0; block_num <= last_block_column; block_num++) {
+ /* Fetch current DCT block into workspace so we can modify it. */
+ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+ /* Update DC values */
+ if (block_num < last_block_column) {
+ DC3 = (int) prev_block_row[1][0];
+ DC6 = (int) buffer_ptr[1][0];
+ DC9 = (int) next_block_row[1][0];
+ }
+ /* Compute coefficient estimates per K.8.
+ * An estimate is applied only if coefficient is still zero,
+ * and is not known to be fully accurate.
+ */
+ /* AC01 */
+ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+ num = 36 * Q00 * (DC4 - DC6);
+ if (num >= 0) {
+ pred = (int) (((Q01<<7) + num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q01<<7) - num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[1] = (JCOEF) pred;
+ }
+ /* AC10 */
+ if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+ num = 36 * Q00 * (DC2 - DC8);
+ if (num >= 0) {
+ pred = (int) (((Q10<<7) + num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q10<<7) - num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[8] = (JCOEF) pred;
+ }
+ /* AC20 */
+ if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
+ num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q20<<7) + num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q20<<7) - num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[16] = (JCOEF) pred;
+ }
+ /* AC11 */
+ if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+ num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
+ if (num >= 0) {
+ pred = (int) (((Q11<<7) + num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q11<<7) - num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[9] = (JCOEF) pred;
+ }
+ /* AC02 */
+ if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
+ num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q02<<7) + num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q02<<7) - num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[2] = (JCOEF) pred;
+ }
+ /* OK, do the IDCT */
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
+ output_ptr, output_col);
+ /* Advance for next column */
+ DC1 = DC2; DC2 = DC3;
+ DC4 = DC5; DC5 = DC6;
+ DC7 = DC8; DC8 = DC9;
+ buffer_ptr++, prev_block_row++, next_block_row++;
+ output_col += compptr->codec_data_unit;
+ }
+ output_ptr += compptr->codec_data_unit;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ d_coef_ptr coef;
+
+ coef = (d_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(d_coef_controller));
+ lossyd->coef_private = (void *) coef;
+ lossyd->coef_start_input_pass = start_input_pass;
+ lossyd->coef_start_output_pass = start_output_pass;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ coef->coef_bits_latch = NULL;
+#endif
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ /* Note we ask for a pre-zeroed array. */
+ int ci, access_rows;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ access_rows = compptr->v_samp_factor;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* If block smoothing could be used, need a bigger window */
+ if (cinfo->process == JPROC_PROGRESSIVE)
+ access_rows *= 3;
+#endif
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) access_rows);
+ }
+ lossyd->pub.consume_data = consume_data;
+ lossyd->pub.decompress_data = decompress_data;
+ lossyd->coef_arrays = coef->whole_image; /* link to virtual arrays */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ D_MAX_DATA_UNITS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < D_MAX_DATA_UNITS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ lossyd->pub.consume_data = dummy_consume_data;
+ lossyd->pub.decompress_data = decompress_onepass;
+ lossyd->coef_arrays = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcolor.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcolor.cpp
new file mode 100644
index 00000000..c176dbd2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdcolor.cpp
@@ -0,0 +1,397 @@
+/*
+ * jdcolor.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains output colorspace conversion routines.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_deconverter pub; /* public fields */
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+} my_color_deconverter;
+
+typedef my_color_deconverter * my_cconvert_ptr;
+
+
+/**************** YCbCr -> RGB conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * R = Y + 1.40200 * Cr
+ * G = Y - 0.34414 * Cb - 0.71414 * Cr
+ * B = Y + 1.77200 * Cb
+ * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ * Notice that Y, being an integral input, does not contribute any fraction
+ * so it need not participate in the rounding.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times Cb and Cr for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+ * values for the G calculation are left scaled up, since we must add them
+ * together before rounding.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX_JDCOLOR(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ cconvert->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ cconvert->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ cconvert->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX_JDCOLOR(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ cconvert->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX_JDCOLOR(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ cconvert->Cr_g_tab[i] = (- FIX_JDCOLOR(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ cconvert->Cb_g_tab[i] = (- FIX_JDCOLOR(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the output colorspace.
+ *
+ * Note that we change from noninterleaved, one-plane-per-component format
+ * to interleaved-pixel format. The output buffer is therefore three times
+ * as wide as the input buffer.
+ * A starting row offset is provided only for the input buffer. The caller
+ * can easily adjust the passed output_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+ycc_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
+ outptr[RGB_GREEN] = range_limit[y +
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS))];
+ outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/**************** Cases other than YCbCr -> RGB **************/
+
+
+/*
+ * Color conversion for no colorspace change: just copy the data,
+ * converting from separate-planes to interleaved representation.
+ */
+
+METHODDEF(void)
+null_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION count;
+ register int num_components = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->output_width;
+ int ci;
+
+ while (--num_rows >= 0) {
+ for (ci = 0; ci < num_components; ci++) {
+ inptr = input_buf[ci][input_row];
+ outptr = output_buf[0] + ci;
+ for (count = num_cols; count > 0; count--) {
+ *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
+ outptr += num_components;
+ }
+ }
+ input_row++;
+ output_buf++;
+ }
+}
+
+
+/*
+ * Color conversion for grayscale: just copy the data.
+ * This also works for YCbCr -> grayscale conversion, in which
+ * we just copy the Y (luminance) component and ignore chrominance.
+ */
+
+METHODDEF(void)
+grayscale_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
+ num_rows, cinfo->output_width);
+}
+
+
+/*
+ * Convert grayscale to RGB: just duplicate the graylevel three times.
+ * This is provided to support applications that don't want to cope
+ * with grayscale as a separate case.
+ */
+
+METHODDEF(void)
+gray_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+
+ while (--num_rows >= 0) {
+ inptr = input_buf[0][input_row++];
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ /* We can dispense with GETJSAMPLE() here */
+ outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/*
+ * Adobe-style YCCK->CMYK conversion.
+ * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume build_ycc_rgb_table has been called.
+ */
+
+METHODDEF(void)
+ycck_cmyk_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2, inptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ inptr3 = input_buf[3][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
+ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS)))];
+ outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
+ /* K passes through unchanged */
+ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
+ outptr += 4;
+ }
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+start_pass_dcolor (j_decompress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for output colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_deconverter (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+ int ci;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_deconverter));
+ cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+ cconvert->pub.start_pass = start_pass_dcolor;
+
+ /* Make sure num_components agrees with jpeg_color_space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->num_components < 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+ }
+
+ /* Set out_color_components and conversion method based on requested space.
+ * Also clear the component_needed flags for any unused components,
+ * so that earlier pipeline stages can avoid useless computation.
+ */
+
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+ cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = grayscale_convert;
+ /* For color->grayscale conversion, only the Y (0) component is needed */
+ for (ci = 1; ci < cinfo->num_components; ci++)
+ cinfo->comp_info[ci].component_needed = FALSE;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ if (cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = ycc_rgb_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
+ cconvert->pub.color_convert = gray_rgb_convert;
+ } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ cinfo->out_color_components = 4;
+ if (cinfo->jpeg_color_space == JCS_YCCK) {
+ cconvert->pub.color_convert = ycck_cmyk_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_CMYK) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default:
+ /* Permit null conversion to same output space */
+ if (cinfo->out_color_space == cinfo->jpeg_color_space) {
+ cinfo->out_color_components = cinfo->num_components;
+ cconvert->pub.color_convert = null_convert;
+ } else /* unsupported non-null conversion */
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+ }
+
+ if (cinfo->quantize_colors)
+ cinfo->output_components = 1; /* single colormapped output component */
+ else
+ cinfo->output_components = cinfo->out_color_components;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdct.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdct.h
new file mode 100644
index 00000000..04192a26
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdct.h
@@ -0,0 +1,176 @@
+/*
+ * jdct.h
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the forward and
+ * inverse DCT modules. These declarations are private to the DCT managers
+ * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
+ * The individual DCT algorithms are kept in separate files to ease
+ * machine-dependent tuning (e.g., assembly coding).
+ */
+
+
+/*
+ * A forward DCT routine is given a pointer to a work area of type DCTELEM[];
+ * the DCT is to be performed in-place in that buffer. Type DCTELEM is int
+ * for 8-bit samples, INT32 for 12-bit samples. (NOTE: Floating-point DCT
+ * implementations use an array of type FAST_FLOAT, instead.)
+ * The DCT inputs are expected to be signed (range +-CENTERJSAMPLE).
+ * The DCT outputs are returned scaled up by a factor of 8; they therefore
+ * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
+ * convention improves accuracy in integer implementations and saves some
+ * work in floating-point ones.
+ * Quantization of the output coefficients is done by jcdctmgr.c.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef int DCTELEM; /* 16 or 32 bits is fine */
+#else
+typedef INT32 DCTELEM; /* must have 32 bits */
+#endif
+
+typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data));
+typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data));
+
+
+/*
+ * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
+ * to an output sample array. The routine must dequantize the input data as
+ * well as perform the IDCT; for dequantization, it uses the multiplier table
+ * pointed to by compptr->dct_table. The output data is to be placed into the
+ * sample array starting at a specified column. (Any row offset needed will
+ * be applied to the array pointer before it is passed to the IDCT code.)
+ * Note that the number of samples emitted by the IDCT routine is
+ * DCT_scaled_size * DCT_scaled_size.
+ */
+
+/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
+
+/*
+ * Each IDCT routine has its own ideas about the best dct_table element type.
+ */
+
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+#if BITS_IN_JSAMPLE == 8
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
+#else
+typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
+#endif
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+
+
+/*
+ * Each IDCT routine is responsible for range-limiting its results and
+ * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
+ * be quite far out of range if the input data is corrupt, so a bulletproof
+ * range-limiting step is required. We use a mask-and-table-lookup method
+ * to do the combined operations quickly. See the comments with
+ * prepare_range_limit_table (in jdmaster.c) for more info.
+ */
+
+#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
+
+#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_fdct_islow jFDislow
+#define jpeg_fdct_ifast jFDifast
+#define jpeg_fdct_float jFDfloat
+#define jpeg_idct_islow jRDislow
+#define jpeg_idct_ifast jRDifast
+#define jpeg_idct_float jRDfloat
+#define jpeg_idct_4x4 jRD4x4
+#define jpeg_idct_2x2 jRD2x2
+#define jpeg_idct_1x1 jRD1x1
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Extern declarations for the forward and inverse DCT routines. */
+
+EXTERN(void) jpeg_fdct_islow JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_ifast JPP((DCTELEM * data));
+EXTERN(void) jpeg_fdct_float JPP((FAST_FLOAT * data));
+
+EXTERN(void) jpeg_idct_islow
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_ifast
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_float
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x4
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x2
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_1x1
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+
+
+/*
+ * Macros for handling fixed-point arithmetic; these are used by many
+ * but not all of the DCT/IDCT modules.
+ *
+ * All values are expected to be of type INT32.
+ * Fractional constants are scaled left by CONST_BITS bits.
+ * CONST_BITS is defined within each module using these macros,
+ * and may differ from one module to the next.
+ */
+
+#define ONE ((INT32) 1)
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
+ * thus causing a lot of useless floating-point operations at run time.
+ */
+
+#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * This macro is used only when the two inputs will actually be no more than
+ * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
+ * full 32x32 multiply. This provides a useful speedup on many machines.
+ * Unfortunately there is no way to specify a 16x16->32 multiply portably
+ * in C, but some C compilers will do the right thing if you provide the
+ * correct combination of casts.
+ */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
+#endif
+
+#ifndef MULTIPLY16C16 /* default definition */
+#define MULTIPLY16C16(var,const) ((var) * (const))
+#endif
+
+/* Same except both inputs are variables. */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
+#endif
+
+#ifndef MULTIPLY16V16 /* default definition */
+#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jddctmgr.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddctmgr.cpp
new file mode 100644
index 00000000..a317eaf9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddctmgr.cpp
@@ -0,0 +1,271 @@
+/*
+ * jddctmgr.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the inverse-DCT management logic.
+ * This code selects a particular IDCT implementation to be used,
+ * and it performs related housekeeping chores. No code in this file
+ * is executed per IDCT step, only during output pass setup.
+ *
+ * Note that the IDCT routines are responsible for performing coefficient
+ * dequantization as well as the IDCT proper. This module sets up the
+ * dequantization multiplier table needed by the IDCT routine.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy subsystem */
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/*
+ * The decompressor input side (jdinput.c) saves away the appropriate
+ * quantization table for each component at the start of the first scan
+ * involving that component. (This is necessary in order to correctly
+ * decode files that reuse Q-table slots.)
+ * When we are ready to make an output pass, the saved Q-table is converted
+ * to a multiplier table that will actually be used by the IDCT routine.
+ * The multiplier table contents are IDCT-method-dependent. To support
+ * application changes in IDCT method between scans, we can remake the
+ * multiplier tables if necessary.
+ * In buffered-image mode, the first output pass may occur before any data
+ * has been seen for some components, and thus before their Q-tables have
+ * been saved away. To handle this case, multiplier tables are preset
+ * to zeroes; the result of the IDCT will be a neutral gray level.
+ */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ /* This array contains the IDCT method code that each multiplier table
+ * is currently set up for, or -1 if it's not yet set up.
+ * The actual multiplier tables are pointed to by dct_table in the
+ * per-component comp_info structures.
+ */
+ int cur_method[MAX_COMPONENTS];
+} idct_controller;
+
+typedef idct_controller * idct_ptr;
+
+
+/* Allocated multiplier tables: big enough for any supported variant */
+
+typedef union {
+ ISLOW_MULT_TYPE islow_array[DCTSIZE2];
+#ifdef DCT_IFAST_SUPPORTED
+ IFAST_MULT_TYPE ifast_array[DCTSIZE2];
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ FLOAT_MULT_TYPE float_array[DCTSIZE2];
+#endif
+} multiplier_table;
+
+
+/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
+ * so be sure to compile that code if either ISLOW or SCALING is requested.
+ */
+#ifdef DCT_ISLOW_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#else
+#ifdef IDCT_SCALING_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#endif
+#endif
+
+
+/*
+ * Prepare for an output pass.
+ * Here we select the proper IDCT routine for each component and build
+ * a matching multiplier table.
+ */
+
+METHODDEF(void)
+start_pass (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ idct_ptr idct = (idct_ptr) lossyd->idct_private;
+ int ci, i;
+ jpeg_component_info *compptr;
+ int method = 0;
+ inverse_DCT_method_ptr method_ptr = NULL;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Select the proper IDCT routine for this component's scaling */
+ switch (compptr->codec_data_unit) {
+#ifdef IDCT_SCALING_SUPPORTED
+ case 1:
+ method_ptr = jpeg_idct_1x1;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+ case 2:
+ method_ptr = jpeg_idct_2x2;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+ case 4:
+ method_ptr = jpeg_idct_4x4;
+ method = JDCT_ISLOW; /* jidctred uses islow-style table */
+ break;
+#endif
+ case DCTSIZE:
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ method_ptr = jpeg_idct_islow;
+ method = JDCT_ISLOW;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ method_ptr = jpeg_idct_ifast;
+ method = JDCT_IFAST;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ method_ptr = jpeg_idct_float;
+ method = JDCT_FLOAT;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ break;
+ default:
+ ERREXIT1(cinfo, JERR_BAD_DCTSIZE, compptr->codec_data_unit);
+ break;
+ }
+ lossyd->inverse_DCT[ci] = method_ptr;
+ /* Create multiplier table from quant table.
+ * However, we can skip this if the component is uninteresting
+ * or if we already built the table. Also, if no quant table
+ * has yet been saved for the component, we leave the
+ * multiplier table all-zero; we'll be reading zeroes from the
+ * coefficient controller's buffer anyway.
+ */
+ if (! compptr->component_needed || idct->cur_method[ci] == method)
+ continue;
+ qtbl = compptr->quant_table;
+ if (qtbl == NULL) /* happens if no data yet for component */
+ continue;
+ idct->cur_method[ci] = method;
+ switch (method) {
+#ifdef PROVIDE_ISLOW_TABLES
+ case JDCT_ISLOW:
+ {
+ /* For LL&M IDCT method, multipliers are equal to raw quantization
+ * coefficients, but are stored as ints to ensure access efficiency.
+ */
+ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ for (i = 0; i < DCTSIZE2; i++) {
+ ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+ }
+ }
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * For integer operation, the multiplier table is to be scaled by
+ * IFAST_SCALE_BITS.
+ */
+ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ ifmtbl[i] = (IFAST_MULT_TYPE)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-IFAST_SCALE_BITS);
+ }
+ }
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ */
+ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fmtbl[i] = (FLOAT_MULT_TYPE)
+ ((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col]);
+ i++;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Initialize IDCT manager.
+ */
+
+GLOBAL(void)
+jinit_inverse_dct (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ idct_ptr idct;
+ int ci;
+ jpeg_component_info *compptr;
+
+ idct = (idct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(idct_controller));
+ lossyd->idct_private = (void *) idct;
+ lossyd->idct_start_pass = start_pass;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate and pre-zero a multiplier table for each component */
+ compptr->dct_table =
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(multiplier_table));
+ MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
+ /* Mark multiplier table not yet set up for any method */
+ idct->cur_method[ci] = -1;
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.cpp
new file mode 100644
index 00000000..95eefa74
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.cpp
@@ -0,0 +1,399 @@
+/*
+ * jddiffct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the [un]difference buffer controller for decompression.
+ * This controller is the top level of the lossless JPEG decompressor proper.
+ * The difference buffer lies between the entropy decoding and
+ * prediction/undifferencing steps. The undifference buffer lies between the
+ * prediction/undifferencing and scaling steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h"
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/* Private buffer controller object */
+
+typedef struct {
+ /* These variables keep track of the current location of the input side. */
+ /* cinfo->input_iMCU_row is also used for this. */
+ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
+ unsigned int restart_rows_to_go; /* MCU-rows left in this restart interval */
+ unsigned int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ unsigned int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+ JDIFFARRAY diff_buf[MAX_COMPONENTS]; /* iMCU row of differences */
+ JDIFFARRAY undiff_buf[MAX_COMPONENTS]; /* iMCU row of undiff'd samples */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* In multi-pass modes, we need a virtual sample array for each component. */
+ jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} d_diff_controller;
+
+typedef d_diff_controller * d_diff_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) output_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ diff->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ diff->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ diff->MCU_ctr = 0;
+ diff->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+ /* Check that the restart interval is an integer multiple of the number
+ * of MCU in an MCU-row.
+ */
+ if (cinfo->restart_interval % cinfo->MCUs_per_row != 0)
+ ERREXIT2(cinfo, JERR_BAD_RESTART,
+ cinfo->restart_interval, cinfo->MCUs_per_row);
+
+ /* Initialize restart counter */
+ diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
+
+ cinfo->input_iMCU_row = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Check for a restart marker & resynchronize decoder, undifferencer.
+ * Returns FALSE if must suspend.
+ */
+
+METHODDEF(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+
+ if (! (*losslsd->entropy_process_restart) (cinfo))
+ return FALSE;
+
+ (*losslsd->predict_process_restart) (cinfo);
+
+ /* Reset restart counter */
+ diff->restart_rows_to_go = cinfo->restart_interval / cinfo->MCUs_per_row;
+
+ return TRUE;
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+ cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the supplied buffer.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION MCU_count; /* number of MCUs decoded */
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int comp, ci, yoffset, row, prev_row;
+ jpeg_component_info *compptr;
+
+ /* Loop to process as much as one whole iMCU row */
+ for (yoffset = diff->MCU_vert_offset; yoffset < (int)diff->MCU_rows_per_iMCU_row;
+ yoffset++) {
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (diff->restart_rows_to_go == 0)
+ if (! process_restart(cinfo))
+ return JPEG_SUSPENDED;
+ }
+
+ MCU_col_num = diff->MCU_ctr;
+ /* Try to fetch an MCU-row (or remaining portion of suspended MCU-row). */
+ MCU_count =
+ (*losslsd->entropy_decode_mcus) (cinfo,
+ diff->diff_buf, yoffset, MCU_col_num,
+ cinfo->MCUs_per_row - MCU_col_num);
+ if (MCU_count != cinfo->MCUs_per_row - MCU_col_num) {
+ /* Suspension forced; update state counters and exit */
+ diff->MCU_vert_offset = yoffset;
+ diff->MCU_ctr += MCU_count;
+ return JPEG_SUSPENDED;
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ diff->restart_rows_to_go--;
+
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ diff->MCU_ctr = 0;
+ }
+
+ /*
+ * Undifference and scale each scanline of the disassembled MCU-row
+ * separately. We do not process dummy samples at the end of a scanline
+ * or dummy rows at the end of the image.
+ */
+ for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+ compptr = cinfo->cur_comp_info[comp];
+ ci = compptr->component_index;
+ for (row = 0, prev_row = compptr->v_samp_factor - 1;
+ row < (cinfo->input_iMCU_row == last_iMCU_row ?
+ compptr->last_row_height : compptr->v_samp_factor);
+ prev_row = row, row++) {
+ (*losslsd->predict_undifference[ci]) (cinfo, ci,
+ diff->diff_buf[ci][row],
+ diff->undiff_buf[ci][prev_row],
+ diff->undiff_buf[ci][row],
+ compptr->width_in_data_units);
+ (*losslsd->scaler_scale) (cinfo, diff->undiff_buf[ci][row],
+ output_buf[ci][row],
+ compptr->width_in_data_units);
+ }
+ }
+
+ /* Completed the iMCU row, advance counters for next one.
+ *
+ * NB: output_data will increment output_iMCU_row.
+ * This counter is not needed for the single-pass case
+ * or the input side of the multi-pass case.
+ */
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+ return JPEG_SUSPENDED; /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image sample buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+ //JDIMENSION MCU_col_num; /* index of current MCU within row */
+ //JDIMENSION MCU_count; /* number of MCUs decoded */
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int comp, ci; // yoffset, row, prev_row;
+ JSAMPARRAY buffer[MAX_COMPS_IN_SCAN];
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (comp = 0; comp < cinfo->comps_in_scan; comp++) {
+ compptr = cinfo->cur_comp_info[comp];
+ ci = compptr->component_index;
+ buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, diff->whole_image[ci],
+ cinfo->input_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ }
+
+ return decompress_data(cinfo, buffer);
+}
+
+
+/*
+ * Output some data from the full-image buffer sample in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+output_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff = (d_diff_ptr) losslsd->diff_private;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int ci, samp_rows, row;
+ JSAMPARRAY buffer;
+ jpeg_component_info *compptr;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number < cinfo->output_scan_number ||
+ (cinfo->input_scan_number == cinfo->output_scan_number &&
+ cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, diff->whole_image[ci],
+ cinfo->output_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+
+ if (cinfo->output_iMCU_row < last_iMCU_row)
+ samp_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ samp_rows = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (samp_rows == 0) samp_rows = compptr->v_samp_factor;
+ }
+
+ for (row = 0; row < samp_rows; row++) {
+ MEMCOPY(output_buf[ci][row], buffer[row],
+ compptr->width_in_data_units * SIZEOF(JSAMPLE));
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize difference buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ d_diff_ptr diff;
+ int ci;
+ jpeg_component_info *compptr;
+
+ diff = (d_diff_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(d_diff_controller));
+ losslsd->diff_private = (void *) diff;
+ losslsd->diff_start_input_pass = start_input_pass;
+ losslsd->pub.start_output_pass = start_output_pass;
+
+ /* Create the [un]difference buffers. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ diff->diff_buf[ci] = (*cinfo->mem->alloc_darray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ diff->undiff_buf[ci] = (*cinfo->mem->alloc_darray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+
+ if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* Allocate a full-image virtual array for each component. */
+ int access_rows;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ access_rows = compptr->v_samp_factor;
+ diff->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) access_rows);
+ }
+ losslsd->pub.consume_data = consume_data;
+ losslsd->pub.decompress_data = output_data;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ losslsd->pub.consume_data = dummy_consume_data;
+ losslsd->pub.decompress_data = decompress_data;
+ diff->whole_image[0] = NULL; /* flag for no virtual arrays */
+ }
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.h
new file mode 100644
index 00000000..90b5bf0e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jddiffct.h
@@ -0,0 +1 @@
+GLOBAL(void) jinit_d_diff_controller (j_decompress_ptr cinfo, boolean need_full_buffer); \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.cpp
new file mode 100644
index 00000000..43c9fe74
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.cpp
@@ -0,0 +1,316 @@
+/*
+ * jdhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines which are shared
+ * by the sequential, progressive and lossless decoders.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+//#include "jlossls.h" /* Private declarations for lossless codec */
+//#include "jdhuff.h" /* Declarations shared with jd*huff.c */
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+GLOBAL(void)
+jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ d_derived_tbl *dtbl;
+ int p, i, l, si, numsymbols;
+ int lookbits, ctr;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (d_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(d_derived_tbl));
+ dtbl = *pdtbl;
+ dtbl->pub = htbl; /* fill in back link */
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ numsymbols = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure F.15: generate decoding tables for bit-sequential decoding */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ if (htbl->bits[l]) {
+ /* valoffset[l] = huffval[] index of 1st symbol of code length l,
+ * minus the minimum code of length l
+ */
+ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
+ p += htbl->bits[l];
+ dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+ } else {
+ dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
+ }
+ }
+ dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
+
+ /* Compute lookahead tables to speed up decoding.
+ * First we set all the table entries to 0, indicating "too long";
+ * then we iterate through the Huffman codes that are short enough and
+ * fill in all the entries that correspond to bit sequences starting
+ * with that code.
+ */
+
+ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
+
+ p = 0;
+ for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
+ for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+ /* l = current code's length, p = its index in huffcode[] & huffval[]. */
+ /* Generate left-justified code followed by all possible bit sequences */
+ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
+ for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+ dtbl->look_nbits[lookbits] = l;
+ dtbl->look_sym[lookbits] = htbl->huffval[p];
+ lookbits++;
+ }
+ }
+ }
+
+ /* Validate symbols as being reasonable.
+ * For AC tables, we make no check, but accept all byte values 0..255.
+ * For DC tables, we require the symbols to be in range 0..16.
+ * (Tighter bounds could be applied depending on the data depth and mode,
+ * but this is sufficient to ensure safe decoding.)
+ */
+ if (isDC) {
+ for (i = 0; i < numsymbols; i++) {
+ int sym = htbl->huffval[i];
+ if (sym < 0 || sym > 16)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ }
+ }
+}
+
+
+/*
+ * Out-of-line code for bit fetching.
+ * See jdhuff.h for info about usage.
+ * Note: current values of get_buffer and bits_left are passed as parameters,
+ * but are returned in the corresponding fields of the state struct.
+ *
+ * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
+ * of get_buffer to be used. (On machines with wider words, an even larger
+ * buffer could be used.) However, on some machines 32-bit shifts are
+ * quite slow and take time proportional to the number of places shifted.
+ * (This is true with most PC compilers, for instance.) In this case it may
+ * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
+ * average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
+ */
+
+#ifdef SLOW_SHIFT_32
+#define MIN_GET_BITS 15 /* minimum allowable value */
+#else
+#define MIN_GET_BITS (BIT_BUF_SIZE-7)
+#endif
+
+
+GLOBAL(boolean)
+jpeg_fill_bit_buffer (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ int nbits)
+/* Load up the bit buffer to a depth of at least nbits */
+{
+ /* Copy heavily used state fields into locals (hopefully registers) */
+ register const JOCTET * next_input_byte = state->next_input_byte;
+ register size_t bytes_in_buffer = state->bytes_in_buffer;
+ j_decompress_ptr cinfo = state->cinfo;
+
+ /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
+ /* (It is assumed that no request will be for more than that many bits.) */
+ /* We fail to do so only if we hit a marker or are forced to suspend. */
+
+ if (cinfo->unread_marker == 0) { /* cannot advance past a marker */
+ while (bits_left < MIN_GET_BITS) {
+ register int c;
+
+ /* Attempt to read a byte */
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+
+ /* If it's 0xFF, check and discard stuffed zero byte */
+ if (c == 0xFF) {
+ /* Loop here to discard any padding FF's on terminating marker,
+ * so that we can save a valid unread_marker value. NOTE: we will
+ * accept multiple FF's followed by a 0 as meaning a single FF data
+ * byte. This data pattern is not valid according to the standard.
+ */
+ do {
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+ } while (c == 0xFF);
+
+ if (c == 0) {
+ /* Found FF/00, which represents an FF data byte */
+ c = 0xFF;
+ } else {
+ /* Oops, it's actually a marker indicating end of compressed data.
+ * Save the marker code for later use.
+ * Fine point: it might appear that we should save the marker into
+ * bitread working state, not straight into permanent state. But
+ * once we have hit a marker, we cannot need to suspend within the
+ * current MCU, because we will read no more bytes from the data
+ * source. So it is OK to update permanent state right away.
+ */
+ cinfo->unread_marker = c;
+ /* See if we need to insert some fake zero bits. */
+ goto no_more_bytes;
+ }
+ }
+
+ /* OK, load c into get_buffer */
+ get_buffer = (get_buffer << 8) | c;
+ bits_left += 8;
+ } /* end while */
+ } else {
+ no_more_bytes:
+ /* We get here if we've read the marker that terminates the compressed
+ * data segment. There should be enough bits in the buffer register
+ * to satisfy the request; if so, no problem.
+ */
+ if (nbits > bits_left) {
+ /* Uh-oh. Report corrupted data to user and stuff zeroes into
+ * the data stream, so that we can produce some kind of image.
+ * We use a nonvolatile flag to ensure that only one warning message
+ * appears per data segment.
+ */
+ huffd_common_ptr huffd;
+ if (cinfo->process == JPROC_LOSSLESS)
+ huffd = (huffd_common_ptr) ((j_lossless_d_ptr) cinfo->codec)->entropy_private;
+ else
+ huffd = (huffd_common_ptr) ((j_lossy_d_ptr) cinfo->codec)->entropy_private;
+ if (! huffd->insufficient_data) {
+ WARNMS(cinfo, JWRN_HIT_MARKER);
+ huffd->insufficient_data = TRUE;
+ }
+ /* Fill the buffer with zero bits */
+ get_buffer <<= MIN_GET_BITS - bits_left;
+ bits_left = MIN_GET_BITS;
+ }
+ }
+
+ /* Unload the local registers */
+ state->next_input_byte = next_input_byte;
+ state->bytes_in_buffer = bytes_in_buffer;
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ return TRUE;
+}
+
+
+/*
+ * Out-of-line code for Huffman code decoding.
+ * See jdhuff.h for info about usage.
+ */
+
+GLOBAL(int)
+jpeg_huff_decode (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ d_derived_tbl * htbl, int min_bits)
+{
+ register int l = min_bits;
+ register INT32 code;
+
+ /* HUFF_DECODE has determined that the code is at least min_bits */
+ /* bits long, so fetch that many bits in one swoop. */
+
+ CHECK_BIT_BUFFER(*state, l, return -1);
+ code = GET_BITS(l);
+
+ /* Collect the rest of the Huffman code one bit at a time. */
+ /* This is per Figure F.16 in the JPEG spec. */
+
+ while (code > htbl->maxcode[l]) {
+ code <<= 1;
+ CHECK_BIT_BUFFER(*state, 1, return -1);
+ code |= GET_BITS(1);
+ l++;
+ }
+
+ /* Unload the local registers */
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ /* With garbage input we may reach the sentinel value l = 17. */
+
+ if (l > 16) {
+ WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
+ return 0; /* fake a zero as the safest result */
+ }
+
+ return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.h
new file mode 100644
index 00000000..f9bfc5cc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdhuff.h
@@ -0,0 +1,229 @@
+/*
+ * jdhuff.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for Huffman entropy decoding routines
+ * that are shared between the sequential decoder (jdhuff.c), the
+ * progressive decoder (jdphuff.c) and the lossless decoder (jdlhuff.c).
+ * No other modules need to see these.
+ */
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_make_d_derived_tbl jMkDDerived
+#define jpeg_fill_bit_buffer jFilBitBuf
+#define jpeg_huff_decode jHufDecode
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Derived data constructed for each Huffman table */
+
+#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
+
+typedef struct {
+ /* Basic tables: (element [0] of each array is unused) */
+ INT32 maxcode[18]; /* largest code of length k (-1 if none) */
+ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+ INT32 valoffset[17]; /* huffval[] offset for codes of length k */
+ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
+ * the smallest code of length k; so given a code of length k, the
+ * corresponding symbol is huffval[code + valoffset[k]]
+ */
+
+ /* Link to public Huffman table (needed only in jpeg_huff_decode) */
+ JHUFF_TBL *pub;
+
+ /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
+ * the input data stream. If the next Huffman code is no more
+ * than HUFF_LOOKAHEAD bits long, we can obtain its length and
+ * the corresponding symbol directly from these tables.
+ */
+ int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+ UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
+} d_derived_tbl;
+
+/* Expand a Huffman table definition into the derived format */
+EXTERN(void) jpeg_make_d_derived_tbl
+ JPP((j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl ** pdtbl));
+
+
+/*
+ * Fetching the next N bits from the input stream is a time-critical operation
+ * for the Huffman decoders. We implement it with a combination of inline
+ * macros and out-of-line subroutines. Note that N (the number of bits
+ * demanded at one time) never exceeds 15 for JPEG use.
+ *
+ * We read source bytes into get_buffer and dole out bits as needed.
+ * If get_buffer already contains enough bits, they are fetched in-line
+ * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
+ * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
+ * as full as possible (not just to the number of bits needed; this
+ * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
+ * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
+ * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
+ * at least the requested number of bits --- dummy zeroes are inserted if
+ * necessary.
+ */
+
+typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
+#define BIT_BUF_SIZE 32 /* size of buffer in bits */
+
+/* If long is > 32 bits on your machine, and shifting/masking longs is
+ * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
+ * appropriately should be a win. Unfortunately we can't define the size
+ * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
+ * because not all machines measure sizeof in 8-bit bytes.
+ */
+
+typedef struct { /* Bitreading state saved across MCUs */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+} bitread_perm_state;
+
+typedef struct { /* Bitreading working state within an MCU */
+ /* Current data source location */
+ /* We need a copy, rather than munging the original, in case of suspension */
+ const JOCTET * next_input_byte; /* => next byte to read from source */
+ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
+ /* Bit input buffer --- note these values are kept in register variables,
+ * not in this struct, inside the inner loops.
+ */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+ /* Pointer needed by jpeg_fill_bit_buffer. */
+ j_decompress_ptr cinfo; /* back link to decompress master record */
+} bitread_working_state;
+
+/* Macros to declare and load/save bitread local variables. */
+#define BITREAD_STATE_VARS \
+ register bit_buf_type get_buffer; \
+ register int bits_left; \
+ bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop,permstate) \
+ br_state.cinfo = cinfop; \
+ br_state.next_input_byte = cinfop->src->next_input_byte; \
+ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+ get_buffer = permstate.get_buffer; \
+ bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop,permstate) \
+ cinfop->src->next_input_byte = br_state.next_input_byte; \
+ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+ permstate.get_buffer = get_buffer; \
+ permstate.bits_left = bits_left
+
+/*
+ * These macros provide the in-line portion of bit fetching.
+ * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
+ * before using GET_BITS, PEEK_BITS, or DROP_BITS.
+ * The variables get_buffer and bits_left are assumed to be locals,
+ * but the state struct might not be (jpeg_huff_decode needs this).
+ * CHECK_BIT_BUFFER(state,n,action);
+ * Ensure there are N bits in get_buffer; if suspend, take action.
+ * val = GET_BITS(n);
+ * Fetch next N bits.
+ * val = PEEK_BITS(n);
+ * Fetch next N bits without removing them from the buffer.
+ * DROP_BITS(n);
+ * Discard next N bits.
+ * The value N should be a simple variable, not an expression, because it
+ * is evaluated multiple times.
+ */
+
+#define CHECK_BIT_BUFFER(state,nbits,action) \
+ { if (bits_left < (nbits)) { \
+ if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
+ { action; } \
+ get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+
+#define GET_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left -= (nbits)))) & ((1<<(nbits))-1))
+
+#define PEEK_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left - (nbits)))) & ((1<<(nbits))-1))
+
+#define DROP_BITS(nbits) \
+ (bits_left -= (nbits))
+
+/* Load up the bit buffer to a depth of at least nbits */
+EXTERN(boolean) jpeg_fill_bit_buffer
+ JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+ register int bits_left, int nbits));
+
+
+/*
+ * Code for extracting next Huffman-coded symbol from input bit stream.
+ * Again, this is time-critical and we make the main paths be macros.
+ *
+ * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
+ * without looping. Usually, more than 95% of the Huffman codes will be 8
+ * or fewer bits long. The few overlength codes are handled with a loop,
+ * which need not be inline code.
+ *
+ * Notes about the HUFF_DECODE macro:
+ * 1. Near the end of the data segment, we may fail to get enough bits
+ * for a lookahead. In that case, we do it the hard way.
+ * 2. If the lookahead table contains no entry, the next code must be
+ * more than HUFF_LOOKAHEAD bits long.
+ * 3. jpeg_huff_decode returns -1 if forced to suspend.
+ */
+
+#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
+{ register int nb, look; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ nb = 1; goto slowlabel; \
+ } \
+ } \
+ look = PEEK_BITS(HUFF_LOOKAHEAD); \
+ if ((nb = htbl->look_nbits[look]) != 0) { \
+ DROP_BITS(nb); \
+ result = htbl->look_sym[look]; \
+ } else { \
+ nb = HUFF_LOOKAHEAD+1; \
+slowlabel: \
+ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ } \
+}
+
+/* Out-of-line case for Huffman code fetching */
+EXTERN(int) jpeg_huff_decode
+ JPP((bitread_working_state * state, register bit_buf_type get_buffer,
+ register int bits_left, d_derived_tbl * htbl, int min_bits));
+
+
+/* Common fields between sequential, progressive and lossless Huffman entropy
+ * decoder master structs.
+ */
+
+#define huffd_common_fields \
+ boolean insufficient_data; /* set TRUE after emmitting warning */ \
+ /* These fields are loaded into local variables at start of each MCU. \
+ * In case of suspension, we exit WITHOUT updating them. \
+ */ \
+ bitread_perm_state bitstate /* Bit buffer at start of MCU */
+
+/* Routines that are to be used by any or all of the entropy decoders are
+ * declared to receive a pointer to this structure. There are no actual
+ * instances of huffd_common_struct, only of shuff_entropy_decoder,
+ * phuff_entropy_decoder and lhuff_entropy_decoder.
+ */
+struct huffd_common_struct {
+ huffd_common_fields; /* Fields common to all decoder struct types */
+ /* Additional fields follow in an actual shuff_entropy_decoder,
+ * phuff_entropy_decoder or lhuff_entropy_decoder struct. All four structs
+ * must agree on these initial fields! (This would be a lot cleaner in C++.)
+ */
+};
+
+typedef struct huffd_common_struct * huffd_common_ptr;
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdinput.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdinput.cpp
new file mode 100644
index 00000000..70bc2205
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdinput.cpp
@@ -0,0 +1,348 @@
+/*
+ * jdinput.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input control logic for the JPEG decompressor.
+ * These routines are concerned with controlling the decompressor's input
+ * processing (marker reading and coefficient/difference decoding).
+ * The actual input reading is done in jdmarker.c, jdhuff.c, jdphuff.c,
+ * and jdlhuff.c.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_input_controller pub; /* public fields */
+
+ boolean inheaders; /* TRUE until first SOS is reached */
+} my_input_controller;
+
+typedef my_input_controller * my_inputctl_ptr;
+
+
+/* Forward declarations */
+METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Routines to calculate various quantities related to the size of the image.
+ */
+
+LOCAL(void)
+initial_setup (j_decompress_ptr cinfo)
+/* Called once, when first SOS marker is reached */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ if (cinfo->process == JPROC_LOSSLESS) {
+ /* If precision > compiled-in value, we must downscale */
+ if (cinfo->data_precision > BITS_IN_JSAMPLE)
+ WARNMS2(cinfo, JWRN_MUST_DOWNSCALE,
+ cinfo->data_precision, BITS_IN_JSAMPLE);
+ }
+ else { /* Lossy processes */
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+ }
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* We initialize codec_data_unit and min_codec_data_unit to data_unit.
+ * In the full decompressor, this will be overridden by jdmaster.c;
+ * but in the transcoder, jdmaster.c is not used, so we must do it here.
+ */
+ cinfo->min_codec_data_unit = cinfo->data_unit;
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->codec_data_unit = cinfo->data_unit;
+ /* Size in data units */
+ compptr->width_in_data_units = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * cinfo->data_unit));
+ compptr->height_in_data_units = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * cinfo->data_unit));
+ /* downsampled_width and downsampled_height will also be overridden by
+ * jdmaster.c if we are doing full decompression. The transcoder library
+ * doesn't use these values, but the calling application might.
+ */
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) cinfo->max_h_samp_factor);
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) cinfo->max_v_samp_factor);
+ /* Mark component needed, until color conversion says otherwise */
+ compptr->component_needed = TRUE;
+ /* Mark no quantization table yet saved for component */
+ compptr->quant_table = NULL;
+ }
+
+ /* Compute number of fully interleaved MCU rows. */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*cinfo->data_unit));
+
+ /* Decide whether file contains multiple scans */
+ if (cinfo->comps_in_scan < cinfo->num_components ||
+ cinfo->process == JPROC_PROGRESSIVE)
+ cinfo->inputctl->has_multiple_scans = TRUE;
+ else
+ cinfo->inputctl->has_multiple_scans = FALSE;
+}
+
+
+LOCAL(void)
+per_scan_setup (j_decompress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_data_units;
+ cinfo->MCU_rows_in_scan = compptr->height_in_data_units;
+
+ /* For noninterleaved scan, always one data unit per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_data_units = 1;
+ compptr->MCU_sample_width = compptr->codec_data_unit;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of data unit rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_data_units % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->data_units_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width,
+ (long) (cinfo->max_h_samp_factor*cinfo->data_unit));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*cinfo->data_unit));
+
+ cinfo->data_units_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of data units of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_data_units = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * compptr->codec_data_unit;
+ /* Figure number of non-dummy data units in last MCU column & row */
+ tmp = (int) (compptr->width_in_data_units % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_data_units % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_data_units;
+ if (cinfo->data_units_in_MCU + mcublks > D_MAX_DATA_UNITS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->data_units_in_MCU++] = ci;
+ }
+ }
+
+ }
+}
+
+
+/*
+ * Initialize the input modules to read a scan of compressed data.
+ * The first call to this is done by jdmaster.c after initializing
+ * the entire decompressor (during jpeg_start_decompress).
+ * Subsequent calls come from consume_markers, below.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ per_scan_setup(cinfo);
+ (*cinfo->codec->start_input_pass) (cinfo);
+ cinfo->inputctl->consume_input = cinfo->codec->consume_data;
+}
+
+
+/*
+ * Finish up after inputting a compressed-data scan.
+ * This is called by the coefficient controller after it's read all
+ * the expected data of the scan.
+ */
+
+METHODDEF(void)
+finish_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->inputctl->consume_input = consume_markers;
+}
+
+
+/*
+ * Read JPEG markers before, between, or after compressed-data scans.
+ * Change state as necessary when a new scan is reached.
+ * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ *
+ * The consume_input method pointer points either here or to the
+ * coefficient controller's consume_data routine, depending on whether
+ * we are reading a compressed data segment or inter-segment markers.
+ */
+
+METHODDEF(int)
+consume_markers (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ int val;
+
+ if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
+ return JPEG_REACHED_EOI;
+
+ val = (*cinfo->marker->read_markers) (cinfo);
+
+ switch (val) {
+ case JPEG_REACHED_SOS: /* Found SOS */
+ if (inputctl->inheaders) { /* 1st SOS */
+ initial_setup(cinfo);
+ /*
+ * Initialize the decompression codec. We need to do this here so that
+ * any codec-specific fields and function pointers are available to
+ * the rest of the library.
+ */
+ jinit_d_codec(cinfo);
+ inputctl->inheaders = FALSE;
+ /* Note: start_input_pass must be called by jdmaster.c
+ * before any more input can be consumed. jdapimin.c is
+ * responsible for enforcing this sequencing.
+ */
+ } else { /* 2nd or later SOS marker */
+ if (! inputctl->pub.has_multiple_scans)
+ ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+ start_input_pass(cinfo);
+ }
+ break;
+ case JPEG_REACHED_EOI: /* Found EOI */
+ inputctl->pub.eoi_reached = TRUE;
+ if (inputctl->inheaders) { /* Tables-only datastream, apparently */
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_NO_SOS);
+ } else {
+ /* Prevent infinite loop in coef ctlr's decompress_data routine
+ * if user set output_scan_number larger than number of scans.
+ */
+ if (cinfo->output_scan_number > cinfo->input_scan_number)
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ }
+ break;
+ case JPEG_SUSPENDED:
+ break;
+ }
+
+ return val;
+}
+
+
+/*
+ * Reset state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+ /* Reset other modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->marker->reset_marker_reader) (cinfo);
+ /* Reset progression state -- would be cleaner if entropy decoder did this */
+ cinfo->coef_bits = NULL;
+}
+
+
+/*
+ * Initialize the input controller module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl;
+
+ /* Create subobject in permanent pool */
+ inputctl = (my_inputctl_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_input_controller));
+ cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+ /* Initialize method pointers */
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.reset_input_controller = reset_input_controller;
+ inputctl->pub.start_input_pass = start_input_pass;
+ inputctl->pub.finish_input_pass = finish_input_pass;
+ /* Initialize state: can't use reset_input_controller since we don't
+ * want to try to reset other modules yet.
+ */
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlhuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlhuff.cpp
new file mode 100644
index 00000000..574ccbdc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlhuff.cpp
@@ -0,0 +1,291 @@
+/*
+ * jdlhuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for lossless JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+//#include "jdhuff.h" /* Declarations shared with jd*huff.c */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+typedef struct {
+ int ci, yoffset, MCU_width;
+} lhd_output_ptr_info;
+
+/*
+ * Private entropy decoder object for lossless Huffman decoding.
+ */
+
+typedef struct {
+ huffd_common_fields; /* Fields shared with other entropy decoders */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ /* Precalculated info set up by start_pass for use in decode_mcus: */
+
+ /* Pointers to derived tables to be used for each data unit within an MCU */
+ d_derived_tbl * cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+
+ /* Pointers to the proper output difference row for each group of data units
+ * within an MCU. For each component, there are Vi groups of Hi data units.
+ */
+ JDIFFROW output_ptr[D_MAX_DATA_UNITS_IN_MCU];
+
+ /* Number of output pointers in use for the current MCU. This is the sum
+ * of all Vi in the MCU.
+ */
+ int num_output_ptrs;
+
+ /* Information used for positioning the output pointers within the output
+ * difference rows.
+ */
+ lhd_output_ptr_info output_ptr_info[D_MAX_DATA_UNITS_IN_MCU];
+
+ /* Index of the proper output pointer for each data unit within an MCU */
+ int output_ptr_index[D_MAX_DATA_UNITS_IN_MCU];
+
+} lhuff_entropy_decoder;
+
+typedef lhuff_entropy_decoder * lhuff_entropy_ptr;
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_lhuff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+ int ci, dctbl, sampn, ptrn, yoffset, xoffset;
+ jpeg_component_info * compptr;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ /* Make sure requested tables are present */
+ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS ||
+ cinfo->dc_huff_tbl_ptrs[dctbl] == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->derived_tbls[dctbl]);
+ }
+
+ /* Precalculate decoding info for each sample in an MCU of this scan */
+ for (sampn = 0, ptrn = 0; sampn < cinfo->data_units_in_MCU;) {
+ compptr = cinfo->cur_comp_info[cinfo->MCU_membership[sampn]];
+ ci = compptr->component_index;
+ for (yoffset = 0; yoffset < compptr->MCU_height; yoffset++, ptrn++) {
+ /* Precalculate the setup info for each output pointer */
+ entropy->output_ptr_info[ptrn].ci = ci;
+ entropy->output_ptr_info[ptrn].yoffset = yoffset;
+ entropy->output_ptr_info[ptrn].MCU_width = compptr->MCU_width;
+ for (xoffset = 0; xoffset < compptr->MCU_width; xoffset++, sampn++) {
+ /* Precalculate the output pointer index for each sample */
+ entropy->output_ptr_index[sampn] = ptrn;
+ /* Precalculate which table to use for each sample */
+ entropy->cur_tbls[sampn] = entropy->derived_tbls[compptr->dc_tbl_no];
+ }
+ }
+ }
+ entropy->num_output_ptrs = ptrn;
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->insufficient_data = FALSE;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] = /* entry n is 2**(n-1) */
+ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+ ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+ ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+METHODDEF(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+ // int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Decode and return nMCU's worth of Huffman-compressed differences.
+ * Each MCU is also disassembled and placed accordingly in diff_buf.
+ *
+ * MCU_col_num specifies the column of the first MCU being requested within
+ * the MCU-row. This tells us where to position the output row pointers in
+ * diff_buf.
+ *
+ * Returns the number of MCUs decoded. This may be less than nMCU if data
+ * source requested suspension. In that case no changes have been made to
+ * permanent state. (Exception: some output differences may already have
+ * been assigned. This is harmless for this module, since we'll just
+ * re-assign them on the next call.)
+ */
+
+METHODDEF(JDIMENSION)
+decode_mcus (j_decompress_ptr cinfo, JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num, JDIMENSION MCU_col_num, JDIMENSION nMCU)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy = (lhuff_entropy_ptr) losslsd->entropy_private;
+ int mcu_num, sampn, ci, yoffset, MCU_width, ptrn;
+ BITREAD_STATE_VARS;
+
+ /* Set output pointer locations based on MCU_col_num */
+ for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++) {
+ ci = entropy->output_ptr_info[ptrn].ci;
+ yoffset = entropy->output_ptr_info[ptrn].yoffset;
+ MCU_width = entropy->output_ptr_info[ptrn].MCU_width;
+ entropy->output_ptr[ptrn] =
+ diff_buf[ci][MCU_row_num + yoffset] + (MCU_col_num * MCU_width);
+ }
+
+ /*
+ * If we've run out of data, zero out the buffers and return.
+ * By resetting the undifferencer, the output samples will be CENTERJSAMPLE.
+ *
+ * NB: We should find a way to do this without interacting with the
+ * undifferencer module directly.
+ */
+ if (entropy->insufficient_data) {
+ for (ptrn = 0; ptrn < entropy->num_output_ptrs; ptrn++)
+ jzero_far((void FAR *) entropy->output_ptr[ptrn],
+ nMCU * entropy->output_ptr_info[ptrn].MCU_width * SIZEOF(JDIFF));
+
+ (*losslsd->predict_process_restart) (cinfo);
+ }
+
+ else {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+ /* Outer loop handles the number of MCU requested */
+
+ for (mcu_num = 0; mcu_num < (int)nMCU; mcu_num++) {
+
+ /* Inner loop handles the samples in the MCU */
+ for (sampn = 0; sampn < cinfo->data_units_in_MCU; sampn++) {
+ d_derived_tbl * dctbl = entropy->cur_tbls[sampn];
+ register int s, r;
+
+ /* Section H.2.2: decode the sample difference */
+ HUFF_DECODE(s, br_state, dctbl, return mcu_num, label1);
+ if (s) {
+ if (s == 16) /* special case: always output 32768 */
+ s = 32768;
+ else { /* normal case: fetch subsequent bits */
+ CHECK_BIT_BUFFER(br_state, s, return mcu_num);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+ }
+
+ /* Output the sample difference */
+ *entropy->output_ptr[entropy->output_ptr_index[sampn]]++ = (JDIFF) s;
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ }
+ }
+
+ return nMCU;
+}
+
+
+/*
+ * Module initialization routine for lossless Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_lhuff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ lhuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (lhuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(lhuff_entropy_decoder));
+ losslsd->entropy_private = (void *) entropy;
+ losslsd->entropy_start_pass = start_pass_lhuff_decoder;
+ losslsd->entropy_process_restart = process_restart;
+ losslsd->entropy_decode_mcus = decode_mcus;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ }
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossls.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossls.cpp
new file mode 100644
index 00000000..184c004c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossls.cpp
@@ -0,0 +1,95 @@
+/*
+ * jdlossls.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossless JPEG decompressor.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h"
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/*
+ * Compute output image dimensions and related values.
+ */
+
+METHODDEF(void)
+calc_output_dimensions (j_decompress_ptr cinfo)
+{
+ /* Hardwire it to "no scaling" */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ /* jdinput.c has already initialized codec_data_unit to 1,
+ * and has computed unscaled downsampled_width and downsampled_height.
+ */
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+ (*losslsd->entropy_start_pass) (cinfo);
+ (*losslsd->predict_start_pass) (cinfo);
+ (*losslsd->scaler_start_pass) (cinfo);
+ (*losslsd->diff_start_input_pass) (cinfo);
+}
+
+
+/*
+ * Initialize the lossless decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossless_d_codec(j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd;
+ boolean use_c_buffer;
+
+ /* Create subobject in permanent pool */
+ losslsd = (j_lossless_d_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(jpeg_lossless_d_codec));
+ cinfo->codec = (struct jpeg_d_codec *) losslsd;
+
+ /* Initialize sub-modules */
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ jinit_lhuff_decoder(cinfo);
+ }
+
+ /* Undifferencer */
+ jinit_undifferencer(cinfo);
+
+ /* Scaler */
+ jinit_d_scaler(cinfo);
+
+ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+ jinit_d_diff_controller(cinfo, use_c_buffer);
+
+ /* Initialize method pointers.
+ *
+ * Note: consume_data, start_output_pass and decompress_data are
+ * assigned in jddiffct.c.
+ */
+ losslsd->pub.calc_output_dimensions = calc_output_dimensions;
+ losslsd->pub.start_input_pass = start_input_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossy.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossy.cpp
new file mode 100644
index 00000000..2876eaf3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdlossy.cpp
@@ -0,0 +1,229 @@
+/*
+ * jdlossy.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the control logic for the lossy JPEG decompressor.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h"
+
+
+/*
+ * Compute output image dimensions and related values.
+ */
+
+METHODDEF(void)
+calc_output_dimensions (j_decompress_ptr cinfo)
+{
+#ifdef IDCT_SCALING_SUPPORTED
+ int ci;
+ jpeg_component_info *compptr;
+
+ /* Compute actual output image dimensions and DCT scaling choices. */
+ if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
+ /* Provide 1/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 8L);
+ cinfo->min_codec_data_unit = 1;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
+ /* Provide 1/4 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 4L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 4L);
+ cinfo->min_codec_data_unit = 2;
+ } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
+ /* Provide 1/2 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 2L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 2L);
+ cinfo->min_codec_data_unit = 4;
+ } else {
+ /* Provide 1/1 scaling */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ cinfo->min_codec_data_unit = DCTSIZE;
+ }
+ /* In selecting the actual DCT scaling for each component, we try to
+ * scale up the chroma components via IDCT scaling rather than upsampling.
+ * This saves time if the upsampler gets to use 1:1 scaling.
+ * Note this code assumes that the supported DCT scalings are powers of 2.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ int ssize = cinfo->min_codec_data_unit;
+ while (ssize < DCTSIZE &&
+ (compptr->h_samp_factor * ssize * 2 <=
+ cinfo->max_h_samp_factor * cinfo->min_codec_data_unit) &&
+ (compptr->v_samp_factor * ssize * 2 <=
+ cinfo->max_v_samp_factor * cinfo->min_codec_data_unit)) {
+ ssize = ssize * 2;
+ }
+ compptr->codec_data_unit = ssize;
+ }
+
+ /* Recompute downsampled dimensions of components;
+ * application needs to know these if using raw downsampled data.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Size in samples, after IDCT scaling */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width *
+ (long) (compptr->h_samp_factor * compptr->codec_data_unit),
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height *
+ (long) (compptr->v_samp_factor * compptr->codec_data_unit),
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ }
+
+#else /* !IDCT_SCALING_SUPPORTED */
+
+ /* Hardwire it to "no scaling" */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ /* jdinput.c has already initialized codec_data_unit to DCTSIZE,
+ * and has computed unscaled downsampled_width and downsampled_height.
+ */
+
+#endif /* IDCT_SCALING_SUPPORTED */
+}
+
+
+/*
+ * Save away a copy of the Q-table referenced by each component present
+ * in the current scan, unless already saved during a prior scan.
+ *
+ * In a multiple-scan JPEG file, the encoder could assign different components
+ * the same Q-table slot number, but change table definitions between scans
+ * so that each component uses a different Q-table. (The IJG encoder is not
+ * currently capable of doing this, but other encoders might.) Since we want
+ * to be able to dequantize all the components at the end of the file, this
+ * means that we have to save away the table actually used for each component.
+ * We do this by copying the table at the start of the first scan containing
+ * the component.
+ * The JPEG spec prohibits the encoder from changing the contents of a Q-table
+ * slot between scans of a component using that slot. If the encoder does so
+ * anyway, this decoder will simply use the Q-table values that were current
+ * at the start of the first scan for the component.
+ *
+ * The decompressor output side looks only at the saved quant tables,
+ * not at the current Q-table slots.
+ */
+
+LOCAL(void)
+latch_quant_tables (j_decompress_ptr cinfo)
+{
+ int ci, qtblno;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* No work if we already saved Q-table for this component */
+ if (compptr->quant_table != NULL)
+ continue;
+ /* Make sure specified quantization table is present */
+ qtblno = compptr->quant_tbl_no;
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ /* OK, save away the quantization table */
+ qtbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(JQUANT_TBL));
+ MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
+ compptr->quant_table = qtbl;
+ }
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+
+ latch_quant_tables(cinfo);
+ (*lossyd->entropy_start_pass) (cinfo);
+ (*lossyd->coef_start_input_pass) (cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+
+ (*lossyd->idct_start_pass) (cinfo);
+ (*lossyd->coef_start_output_pass) (cinfo);
+}
+
+/*
+ * Initialize the lossy decompression codec.
+ * This is called only once, during master selection.
+ */
+
+GLOBAL(void)
+jinit_lossy_d_codec (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd;
+ boolean use_c_buffer;
+
+ /* Create subobject in permanent pool */
+ lossyd = (j_lossy_d_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(jpeg_lossy_d_codec));
+ cinfo->codec = (struct jpeg_d_codec *) lossyd;
+
+ /* Initialize sub-modules */
+
+ /* Inverse DCT */
+ jinit_inverse_dct(cinfo);
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ ERREXIT(cinfo, JERR_ARITH_NOTIMPL);
+ } else {
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+#ifdef D_PROGRESSIVE_SUPPORTED
+ jinit_phuff_decoder(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else
+ jinit_shuff_decoder(cinfo);
+ }
+
+ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+ jinit_d_coef_controller(cinfo, use_c_buffer);
+
+ /* Initialize method pointers.
+ *
+ * Note: consume_data and decompress_data are assigned in jdcoefct.c.
+ */
+ lossyd->pub.calc_output_dimensions = calc_output_dimensions;
+ lossyd->pub.start_input_pass = start_input_pass;
+ lossyd->pub.start_output_pass = start_output_pass;
+}
+
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmainct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmainct.cpp
new file mode 100644
index 00000000..d37b96ce
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmainct.cpp
@@ -0,0 +1,513 @@
+/*
+ * jdmainct.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for decompression.
+ * The main buffer lies between the JPEG decompressor proper and the
+ * post-processor; it holds downsampled data in the JPEG colorspace.
+ *
+ * Note that this code is bypassed in raw-data mode, since the application
+ * supplies the equivalent of the main buffer in that case.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * In the current system design, the main buffer need never be a full-image
+ * buffer; any full-height buffers will be found inside the coefficient or
+ * postprocessing controllers. Nonetheless, the main controller is not
+ * trivial. Its responsibility is to provide context rows for upsampling/
+ * rescaling, and doing this in an efficient fashion is a bit tricky.
+ *
+ * Postprocessor input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
+ * sample rows of each component. (We require codec_data_unit values to be
+ * chosen such that these numbers are integers. In practice codec_data_unit
+ * values will likely be powers of two, so we actually have the stronger
+ * condition that codec_data_unit / min_codec_data_unit is an integer.)
+ * Upsampling will typically produce max_v_samp_factor pixel rows from each
+ * row group (times any additional scale factor that the upsampler is
+ * applying).
+ *
+ * The decompression codec will deliver data to us one iMCU row at a time;
+ * each iMCU row contains v_samp_factor * codec_data_unit sample rows, or
+ * exactly min_codec_data_unit row groups. (This amount of data corresponds
+ * to one row of MCUs when the image is fully interleaved.) Note that the
+ * number of sample rows varies across components, but the number of row
+ * groups does not. Some garbage sample rows may be included in the last iMCU
+ * row at the bottom of the image.
+ *
+ * Depending on the vertical scaling algorithm used, the upsampler may need
+ * access to the sample row(s) above and below its current input row group.
+ * The upsampler is required to set need_context_rows TRUE at global selection
+ * time if so. When need_context_rows is FALSE, this controller can simply
+ * obtain one iMCU row at a time from the coefficient controller and dole it
+ * out as row groups to the postprocessor.
+ *
+ * When need_context_rows is TRUE, this controller guarantees that the buffer
+ * passed to postprocessing contains at least one row group's worth of samples
+ * above and below the row group(s) being processed. Note that the context
+ * rows "above" the first passed row group appear at negative row offsets in
+ * the passed buffer. At the top and bottom of the image, the required
+ * context rows are manufactured by duplicating the first or last real sample
+ * row; this avoids having special cases in the upsampling inner loops.
+ *
+ * The amount of context is fixed at one row group just because that's a
+ * convenient number for this controller to work with. The existing
+ * upsamplers really only need one sample row of context. An upsampler
+ * supporting arbitrary output rescaling might wish for more than one row
+ * group of context when shrinking the image; tough, we don't handle that.
+ * (This is justified by the assumption that downsizing will be handled mostly
+ * by adjusting the codec_data_unit values, so that the actual scale factor at
+ * the upsample step needn't be much less than one.)
+ *
+ * To provide the desired context, we have to retain the last two row groups
+ * of one iMCU row while reading in the next iMCU row. (The last row group
+ * can't be processed until we have another row group for its below-context,
+ * and so we have to save the next-to-last group too for its above-context.)
+ * We could do this most simply by copying data around in our buffer, but
+ * that'd be very slow. We can avoid copying any data by creating a rather
+ * strange pointer structure. Here's how it works. We allocate a workspace
+ * consisting of M+2 row groups (where M = min_codec_data_unit is the number
+ * of row groups per iMCU row). We create two sets of redundant pointers to
+ * the workspace. Labeling the physical row groups 0 to M+1, the synthesized
+ * pointer lists look like this:
+ * M+1 M-1
+ * master pointer --> 0 master pointer --> 0
+ * 1 1
+ * ... ...
+ * M-3 M-3
+ * M-2 M
+ * M-1 M+1
+ * M M-2
+ * M+1 M-1
+ * 0 0
+ * We read alternate iMCU rows using each master pointer; thus the last two
+ * row groups of the previous iMCU row remain un-overwritten in the workspace.
+ * The pointer lists are set up so that the required context rows appear to
+ * be adjacent to the proper places when we pass the pointer lists to the
+ * upsampler.
+ *
+ * The above pictures describe the normal state of the pointer lists.
+ * At top and bottom of the image, we diddle the pointer lists to duplicate
+ * the first or last sample row as necessary (this is cheaper than copying
+ * sample rows around).
+ *
+ * This scheme breaks down if M < 2, ie, min_codec_data_unit is 1. In that
+ * situation each iMCU row provides only one row group so the buffering logic
+ * must be different (eg, we must read two iMCU rows before we can emit the
+ * first row group). For now, we simply do not support providing context
+ * rows when min_codec_data_unit is 1. That combination seems unlikely to
+ * be worth providing --- if someone wants a 1/8th-size preview, they probably
+ * want it quick and dirty, so a context-free upsampler is sufficient.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_main_controller pub; /* public fields */
+
+ /* Pointer to allocated workspace (M or M+2 row groups). */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+ boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
+ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
+
+ /* Remaining fields are only used in the context case. */
+
+ /* These are the master pointers to the funny-order pointer lists. */
+ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
+
+ int whichptr; /* indicates which pointer set is now in use */
+ int context_state; /* process_data state machine status */
+ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
+ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+/* context_state values: */
+#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
+#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
+#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+METHODDEF(void) process_data_context_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) process_data_crank_post
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#endif
+
+
+LOCAL(void)
+alloc_funny_pointers (j_decompress_ptr cinfo)
+/* Allocate space for the funny pointer lists.
+ * This is done only once, not once per pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, rgroup;
+ int M = cinfo->min_codec_data_unit;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ /* Get top-level space for component array pointers.
+ * We alloc both arrays with one call to save a few cycles.
+ */
+ main->xbuffer[0] = (JSAMPIMAGE)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
+ main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit; /* height of a row group of component */
+ /* Get space for pointer lists --- M+4 row groups in each list.
+ * We alloc both pointer lists with one call to save a few cycles.
+ */
+ xbuf = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
+ xbuf += rgroup; /* want one row group at negative offsets */
+ main->xbuffer[0][ci] = xbuf;
+ xbuf += rgroup * (M + 4);
+ main->xbuffer[1][ci] = xbuf;
+ }
+}
+
+
+LOCAL(void)
+make_funny_pointers (j_decompress_ptr cinfo)
+/* Create the funny pointer lists discussed in the comments above.
+ * The actual workspace is already allocated (in main->buffer),
+ * and the space for the pointer lists is allocated too.
+ * This routine just fills in the curiously ordered lists.
+ * This will be repeated at the beginning of each pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_codec_data_unit;
+ jpeg_component_info *compptr;
+ JSAMPARRAY buf, xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ /* First copy the workspace pointers as-is */
+ buf = main->buffer[ci];
+ for (i = 0; i < rgroup * (M + 2); i++) {
+ xbuf0[i] = xbuf1[i] = buf[i];
+ }
+ /* In the second list, put the last four row groups in swapped order */
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
+ xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+ }
+ /* The wraparound pointers at top and bottom will be filled later
+ * (see set_wraparound_pointers, below). Initially we want the "above"
+ * pointers to duplicate the first actual data line. This only needs
+ * to happen in xbuffer[0].
+ */
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[0];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_wraparound_pointers (j_decompress_ptr cinfo)
+/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
+ * This changes the pointer list state from top-of-image to the normal state.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_codec_data_unit;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
+ xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
+ xbuf0[rgroup*(M+2) + i] = xbuf0[i];
+ xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_bottom_pointers (j_decompress_ptr cinfo)
+/* Change the pointer lists to duplicate the last sample row at the bottom
+ * of the image. whichptr indicates which xbuffer holds the final iMCU row.
+ * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup, iMCUheight, rows_left;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Count sample rows in one iMCU row and in one row group */
+ iMCUheight = compptr->v_samp_factor * compptr->codec_data_unit;
+ rgroup = iMCUheight / cinfo->min_codec_data_unit;
+ /* Count nondummy sample rows remaining for this component */
+ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+ if (rows_left == 0) rows_left = iMCUheight;
+ /* Count nondummy row groups. Should get same answer for each component,
+ * so we need only do it once.
+ */
+ if (ci == 0) {
+ main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+ }
+ /* Duplicate the last real sample row rgroup*2 times; this pads out the
+ * last partial rowgroup and ensures at least one full rowgroup of context.
+ */
+ xbuf = main->xbuffer[main->whichptr][ci];
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf[rows_left + i] = xbuf[rows_left-1];
+ }
+ }
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->upsample->need_context_rows) {
+ main->pub.process_data = process_data_context_main;
+ make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
+ main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ main->iMCU_row_ctr = 0;
+ } else {
+ /* Simple case with no context needed */
+ main->pub.process_data = process_data_simple_main;
+ }
+ main->buffer_full = FALSE; /* Mark buffer empty */
+ main->rowgroup_ctr = 0;
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_CRANK_DEST:
+ /* For last pass of 2-pass quantization, just crank the postprocessor */
+ main->pub.process_data = process_data_crank_post;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the simple case where no context is required.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ JDIMENSION rowgroups_avail;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->codec->decompress_data) (cinfo, main->buffer))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ }
+
+ /* There are always min_codec_data_unit row groups in an iMCU row. */
+ rowgroups_avail = (JDIMENSION) cinfo->min_codec_data_unit;
+ /* Note: at the bottom of the image, we may pass extra garbage row groups
+ * to the postprocessor. The postprocessor has to check for bottom
+ * of image anyway (at row resolution), so no point in us doing it too.
+ */
+
+ /* Feed the postprocessor */
+ (*cinfo->post->post_process_data) (cinfo, main->buffer,
+ &main->rowgroup_ctr, rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+
+ /* Has postprocessor consumed all the data yet? If so, mark buffer empty */
+ if (main->rowgroup_ctr >= rowgroups_avail) {
+ main->buffer_full = FALSE;
+ main->rowgroup_ctr = 0;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the case where context rows must be provided.
+ */
+
+METHODDEF(void)
+process_data_context_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->codec->decompress_data) (cinfo,
+ main->xbuffer[main->whichptr]))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ main->iMCU_row_ctr++; /* count rows received */
+ }
+
+ /* Postprocessor typically will not swallow all the input data it is handed
+ * in one call (due to filling the output buffer first). Must be prepared
+ * to exit and restart. This switch lets us keep track of how far we got.
+ * Note that each case falls through to the next on successful completion.
+ */
+ switch (main->context_state) {
+ case CTX_POSTPONED_ROW:
+ /* Call postprocessor using previously set pointers for postponed row */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ if (*out_row_ctr >= out_rows_avail)
+ return; /* Postprocessor exactly filled output buf */
+ /*FALLTHROUGH*/
+ case CTX_PREPARE_FOR_IMCU:
+ /* Prepare to process first M-1 row groups of this iMCU row */
+ main->rowgroup_ctr = 0;
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit - 1);
+ /* Check for bottom of image: if so, tweak pointers to "duplicate"
+ * the last sample row, and adjust rowgroups_avail to ignore padding rows.
+ */
+ if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
+ set_bottom_pointers(cinfo);
+ main->context_state = CTX_PROCESS_IMCU;
+ /*FALLTHROUGH*/
+ case CTX_PROCESS_IMCU:
+ /* Call postprocessor using previously set pointers */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ /* After the first iMCU, change wraparound pointers to normal state */
+ if (main->iMCU_row_ctr == 1)
+ set_wraparound_pointers(cinfo);
+ /* Prepare to load new iMCU row using other xbuffer list */
+ main->whichptr ^= 1; /* 0=>1 or 1=>0 */
+ main->buffer_full = FALSE;
+ /* Still need to process last row group of this iMCU row, */
+ /* which is saved at index M+1 of the other xbuffer */
+ main->rowgroup_ctr = (JDIMENSION) (cinfo->min_codec_data_unit + 1);
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_codec_data_unit + 2);
+ main->context_state = CTX_POSTPONED_ROW;
+ }
+}
+
+
+/*
+ * Process some data.
+ * Final pass of two-pass quantization: just call the postprocessor.
+ * Source data will be the postprocessor controller's internal buffer.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF(void)
+process_data_crank_post (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
+ (JDIMENSION *) NULL, (JDIMENSION) 0,
+ output_buf, out_row_ctr, out_rows_avail);
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci, rgroup, ngroups;
+ jpeg_component_info *compptr;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_d_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ if (need_full_buffer) /* shouldn't happen */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Allocate the workspace.
+ * ngroups is the number of row groups we need.
+ */
+ if (cinfo->upsample->need_context_rows) {
+ if (cinfo->min_codec_data_unit < 2) /* unsupported, see comments above */
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
+ ngroups = cinfo->min_codec_data_unit + 2;
+ } else {
+ ngroups = cinfo->min_codec_data_unit;
+ }
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit; /* height of a row group of component */
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_data_units * compptr->codec_data_unit,
+ (JDIMENSION) (rgroup * ngroups));
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmarker.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmarker.cpp
new file mode 100644
index 00000000..64e5ae81
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmarker.cpp
@@ -0,0 +1,1371 @@
+/*
+ * jdmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to decode JPEG datastream markers.
+ * Most of the complexity arises from our desire to support input
+ * suspension: if not all of the data for a marker is available,
+ * we must exit back to the application. On resumption, we reprocess
+ * the marker.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_reader pub; /* public fields */
+
+ /* Application-overridable marker processing methods */
+ jpeg_marker_parser_method process_COM;
+ jpeg_marker_parser_method process_APPn[16];
+
+ /* Limit on marker data length to save for each marker type */
+ unsigned int length_limit_COM;
+ unsigned int length_limit_APPn[16];
+
+ /* Status of COM/APPn marker saving */
+ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */
+ unsigned int bytes_read; /* data bytes read so far in marker */
+ /* Note: cur_marker is not linked into marker_list until it's all read. */
+} my_marker_reader;
+
+typedef my_marker_reader * my_marker_ptr;
+
+
+/*
+ * Macros for fetching data from the data source module.
+ *
+ * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
+ * the current restart point; we update them only when we have reached a
+ * suitable place to restart if a suspension occurs.
+ */
+
+/* Declare and initialize local copies of input pointer/count */
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr * datasrc = (cinfo)->src; \
+ const JOCTET * next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
+
+/* Unload the local copies --- do this only at a restart boundary */
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
+
+/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
+
+/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
+ * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
+ * but we must reload the local copies after a successful fill.
+ */
+#define MAKE_BYTE_AVAIL(cinfo,action) \
+ if (bytes_in_buffer == 0) { \
+ if (! (*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ }
+
+/* Read a byte into variable V.
+ * If must suspend, take the specified action (typically "return FALSE").
+ */
+#define INPUT_BYTE(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = GETJOCTET(*next_input_byte++); )
+
+/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
+ * V should be declared unsigned int or perhaps INT32.
+ */
+#define INPUT_2BYTES(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
+
+
+/*
+ * Routines to process JPEG markers.
+ *
+ * Entry condition: JPEG marker itself has been read and its code saved
+ * in cinfo->unread_marker; input restart point is just after the marker.
+ *
+ * Exit: if return TRUE, have read and processed any parameters, and have
+ * updated the restart point to point after the parameters.
+ * If return FALSE, was forced to suspend before reaching end of
+ * marker parameters; restart point has not been moved. Same routine
+ * will be called again after application supplies more input data.
+ *
+ * This approach to suspension assumes that all of a marker's parameters
+ * can fit into a single input bufferload. This should hold for "normal"
+ * markers. Some COM/APPn markers might have large parameter segments
+ * that might not fit. If we are simply dropping such a marker, we use
+ * skip_input_data to get past it, and thereby put the problem on the
+ * source manager's shoulders. If we are saving the marker's contents
+ * into memory, we use a slightly different convention: when forced to
+ * suspend, the marker processor updates the restart point to the end of
+ * what it's consumed (ie, the end of the buffer) before returning FALSE.
+ * On resumption, cinfo->unread_marker still contains the marker code,
+ * but the data source will point to the next chunk of marker data.
+ * The marker processor must retain internal state to deal with this.
+ *
+ * Note that we don't bother to avoid duplicate trace messages if a
+ * suspension occurs within marker parameters. Other side effects
+ * require more care.
+ */
+
+
+LOCAL(boolean)
+get_soi (j_decompress_ptr cinfo)
+/* Process an SOI marker */
+{
+ int i;
+
+ TRACEMS(cinfo, 1, JTRC_SOI);
+
+ if (cinfo->marker->saw_SOI)
+ ERREXIT(cinfo, JERR_SOI_DUPLICATE);
+
+ /* Reset all parameters that are defined to be reset by SOI */
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+ cinfo->restart_interval = 0;
+
+ /* Set initial assumptions for colorspace etc */
+
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
+
+ cinfo->saw_JFIF_marker = FALSE;
+ cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0;
+ cinfo->X_density = 1;
+ cinfo->Y_density = 1;
+ cinfo->saw_Adobe_marker = FALSE;
+ cinfo->Adobe_transform = 0;
+
+ cinfo->marker->saw_SOI = TRUE;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sof (j_decompress_ptr cinfo, J_CODEC_PROCESS process, boolean is_arith,
+ int data_unit)
+/* Process a SOFn marker */
+{
+ INT32 length;
+ int c, ci;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ cinfo->data_unit = data_unit;
+ cinfo->process = process;
+ cinfo->arith_code = is_arith;
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
+ INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
+
+ length -= 8;
+
+ TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
+ (int) cinfo->image_width, (int) cinfo->image_height,
+ cinfo->num_components);
+
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_DUPLICATE);
+
+ /* We don't support files in which the image height is initially specified */
+ /* as 0 and is later redefined by DNL. As long as we have to check that, */
+ /* might as well have a general sanity check. */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+ || cinfo->num_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ if (length != (cinfo->num_components * 3))
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ if (cinfo->comp_info == NULL) /* do only once, even if suspend */
+ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * SIZEOF(jpeg_component_info));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->component_index = ci;
+ INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ compptr->h_samp_factor = (c >> 4) & 15;
+ compptr->v_samp_factor = (c ) & 15;
+ INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
+
+ TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
+ compptr->component_id, compptr->h_samp_factor,
+ compptr->v_samp_factor, compptr->quant_tbl_no);
+ }
+
+ cinfo->marker->saw_SOF = TRUE;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sos (j_decompress_ptr cinfo)
+/* Process a SOS marker */
+{
+ INT32 length;
+ int i, ci, n, c, cc;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ if (! cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOS_NO_SOF);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
+
+ TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+ if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ cinfo->comps_in_scan = n;
+
+ /* Collect the component-spec parameters */
+
+ for (i = 0; i < n; i++) {
+ INPUT_BYTE(cinfo, cc, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (cc == compptr->component_id)
+ goto id_found;
+ }
+
+ ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+
+ id_found:
+
+ cinfo->cur_comp_info[i] = compptr;
+ compptr->dc_tbl_no = (c >> 4) & 15;
+ compptr->ac_tbl_no = (c ) & 15;
+
+ TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
+ compptr->dc_tbl_no, compptr->ac_tbl_no);
+ }
+
+ /* Collect the additional scan parameters Ss, Se, Ah/Al. */
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ss = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Se = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ah = (c >> 4) & 15;
+ cinfo->Al = (c ) & 15;
+
+ TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
+ cinfo->Ah, cinfo->Al);
+
+ /* Prepare to scan data & restart markers */
+ cinfo->marker->next_restart_num = 0;
+
+ /* Count another SOS marker */
+ cinfo->input_scan_number++;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+#ifdef D_ARITH_CODING_SUPPORTED
+
+LOCAL(boolean)
+get_dac (j_decompress_ptr cinfo)
+/* Process a DAC marker */
+{
+ INT32 length;
+ int index, val;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+ INPUT_BYTE(cinfo, val, return FALSE);
+
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+
+ if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+ ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+
+ if (index >= NUM_ARITH_TBLS) { /* define AC table */
+ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+ } else { /* define DC table */
+ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
+ cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+ if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+ ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+ }
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+#else /* ! D_ARITH_CODING_SUPPORTED */
+
+#define get_dac(cinfo) skip_variable(cinfo)
+
+#endif /* D_ARITH_CODING_SUPPORTED */
+
+
+LOCAL(boolean)
+get_dht (j_decompress_ptr cinfo)
+/* Process a DHT marker */
+{
+ INT32 length;
+ UINT8 bits[17];
+ UINT8 huffval[256];
+ int i, index, count;
+ JHUFF_TBL **htblptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 16) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DHT, index);
+
+ bits[0] = 0;
+ count = 0;
+ for (i = 1; i <= 16; i++) {
+ INPUT_BYTE(cinfo, bits[i], return FALSE);
+ count += bits[i];
+ }
+
+ length -= 1 + 16;
+
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[1], bits[2], bits[3], bits[4],
+ bits[5], bits[6], bits[7], bits[8]);
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[9], bits[10], bits[11], bits[12],
+ bits[13], bits[14], bits[15], bits[16]);
+
+ /* Here we just do minimal validation of the counts to avoid walking
+ * off the end of our table space. jdhuff.c will check more carefully.
+ */
+ if (count > 256 || ((INT32) count) > length)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ for (i = 0; i < count; i++)
+ INPUT_BYTE(cinfo, huffval[i], return FALSE);
+
+ length -= count;
+
+ if (index & 0x10) { /* AC table definition */
+ index -= 0x10;
+ htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+ } else { /* DC table definition */
+ htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (index < 0 || index >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_DHT_INDEX, index);
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+ MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dqt (j_decompress_ptr cinfo)
+/* Process a DQT marker */
+{
+ INT32 length;
+ int n, i, prec;
+ unsigned int tmp;
+ JQUANT_TBL *quant_ptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, n, return FALSE);
+ prec = n >> 4;
+ n &= 0x0F;
+
+ TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
+
+ if (n >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, n);
+
+ if (cinfo->quant_tbl_ptrs[n] == NULL)
+ cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ quant_ptr = cinfo->quant_tbl_ptrs[n];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (prec)
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+ else
+ INPUT_BYTE(cinfo, tmp, return FALSE);
+ /* We convert the zigzag-order table to natural array order. */
+ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+ }
+
+ if (cinfo->err->trace_level >= 2) {
+ for (i = 0; i < DCTSIZE2; i += 8) {
+ TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
+ quant_ptr->quantval[i], quant_ptr->quantval[i+1],
+ quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
+ quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
+ quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+ }
+ }
+
+ length -= DCTSIZE2+1;
+ if (prec) length -= DCTSIZE2;
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dri (j_decompress_ptr cinfo)
+/* Process a DRI marker */
+{
+ INT32 length;
+ unsigned int tmp;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ if (length != 4)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
+
+ cinfo->restart_interval = tmp;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Routines for processing APPn and COM markers.
+ * These are either saved in memory or discarded, per application request.
+ * APP0 and APP14 are specially checked to see if they are
+ * JFIF and Adobe markers, respectively.
+ */
+
+#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */
+#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */
+#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */
+
+
+LOCAL(void)
+examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP0.
+ * Take appropriate action if it is a JFIF marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ INT32 totallen = (INT32) datalen + remaining;
+
+ if (datalen >= APP0_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x49 &&
+ GETJOCTET(data[3]) == 0x46 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF APP0 marker: save info */
+ cinfo->saw_JFIF_marker = TRUE;
+ cinfo->JFIF_major_version = GETJOCTET(data[5]);
+ cinfo->JFIF_minor_version = GETJOCTET(data[6]);
+ cinfo->density_unit = GETJOCTET(data[7]);
+ cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
+ cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
+ /* Check version.
+ * Major version must be 1, anything else signals an incompatible change.
+ * (We used to treat this as an error, but now it's a nonfatal warning,
+ * because some bozo at Hijaak couldn't read the spec.)
+ * Minor version should be 0..2, but process anyway if newer.
+ */
+ if (cinfo->JFIF_major_version != 1)
+ WARNMS2(cinfo, JWRN_JFIF_MAJOR,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
+ /* Generate trace messages */
+ TRACEMS5(cinfo, 1, JTRC_JFIF,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
+ cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
+ /* Validate thumbnail dimensions and issue appropriate messages */
+ if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
+ TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+ GETJOCTET(data[12]), GETJOCTET(data[13]));
+ totallen -= APP0_DATA_LEN;
+ if (totallen !=
+ ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3))
+ TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+ } else if (datalen >= 6 &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x58 &&
+ GETJOCTET(data[3]) == 0x58 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF "JFXX" extension APP0 marker */
+ /* The library doesn't actually do anything with these,
+ * but we try to produce a helpful trace message.
+ */
+ switch (GETJOCTET(data[5])) {
+ case 0x10:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+ break;
+ case 0x11:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+ break;
+ case 0x13:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
+ GETJOCTET(data[5]), (int) totallen);
+ break;
+ }
+ } else {
+ /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+ }
+}
+
+
+LOCAL(void)
+examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP14.
+ * Take appropriate action if it is an Adobe marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ unsigned int version, flags0, flags1, transform;
+
+ if (datalen >= APP14_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x41 &&
+ GETJOCTET(data[1]) == 0x64 &&
+ GETJOCTET(data[2]) == 0x6F &&
+ GETJOCTET(data[3]) == 0x62 &&
+ GETJOCTET(data[4]) == 0x65) {
+ /* Found Adobe APP14 marker */
+ version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
+ flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
+ flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
+ transform = GETJOCTET(data[11]);
+ TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
+ cinfo->saw_Adobe_marker = TRUE;
+ cinfo->Adobe_transform = (UINT8) transform;
+ } else {
+ /* Start of APP14 does not match "Adobe", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+ }
+}
+
+
+METHODDEF(boolean)
+get_interesting_appn (j_decompress_ptr cinfo)
+/* Process an APP0 or APP14 marker without saving it */
+{
+ INT32 length;
+ JOCTET b[APPN_DATA_LEN];
+ unsigned int i, numtoread;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ /* get the interesting part of the marker data */
+ if (length >= APPN_DATA_LEN)
+ numtoread = APPN_DATA_LEN;
+ else if (length > 0)
+ numtoread = (unsigned int) length;
+ else
+ numtoread = 0;
+ for (i = 0; i < numtoread; i++)
+ INPUT_BYTE(cinfo, b[i], return FALSE);
+ length -= numtoread;
+
+ /* process it */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ default:
+ /* can't get here unless jpeg_save_markers chooses wrong processor */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo);
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+METHODDEF(boolean)
+save_marker (j_decompress_ptr cinfo)
+/* Save an APPn or COM marker into the marker list */
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
+ unsigned int bytes_read, data_length;
+ JOCTET FAR * data;
+ INT32 length = 0;
+ INPUT_VARS(cinfo);
+
+ if (cur_marker == NULL) {
+ /* begin reading a marker */
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+ if (length >= 0) { /* watch out for bogus length word */
+ /* figure out how much we want to save */
+ unsigned int limit;
+ if (cinfo->unread_marker == (int) M_COM)
+ limit = marker->length_limit_COM;
+ else
+ limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
+ if ((unsigned int) length < limit)
+ limit = (unsigned int) length;
+ /* allocate and initialize the marker item */
+ cur_marker = (jpeg_saved_marker_ptr)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(struct jpeg_marker_struct) + limit);
+ cur_marker->next = NULL;
+ cur_marker->marker = (UINT8) cinfo->unread_marker;
+ cur_marker->original_length = (unsigned int) length;
+ cur_marker->data_length = limit;
+ /* data area is just beyond the jpeg_marker_struct */
+ data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
+ marker->cur_marker = cur_marker;
+ marker->bytes_read = 0;
+ bytes_read = 0;
+ data_length = limit;
+ } else {
+ /* deal with bogus length word */
+ bytes_read = data_length = 0;
+ data = NULL;
+ }
+ } else {
+ /* resume reading a marker */
+ bytes_read = marker->bytes_read;
+ data_length = cur_marker->data_length;
+ data = cur_marker->data + bytes_read;
+ }
+
+ while (bytes_read < data_length) {
+ INPUT_SYNC(cinfo); /* move the restart point to here */
+ marker->bytes_read = bytes_read;
+ /* If there's not at least one byte in buffer, suspend */
+ MAKE_BYTE_AVAIL(cinfo, return FALSE);
+ /* Copy bytes with reasonable rapidity */
+ while (bytes_read < data_length && bytes_in_buffer > 0) {
+ *data++ = *next_input_byte++;
+ bytes_in_buffer--;
+ bytes_read++;
+ }
+ }
+
+ /* Done reading what we want to read */
+ if (cur_marker != NULL) { /* will be NULL if bogus length word */
+ /* Add new marker to end of list */
+ if (cinfo->marker_list == NULL) {
+ cinfo->marker_list = cur_marker;
+ } else {
+ jpeg_saved_marker_ptr prev = cinfo->marker_list;
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = cur_marker;
+ }
+ /* Reset pointer & calc remaining data length */
+ data = cur_marker->data;
+ length = cur_marker->original_length - data_length;
+ }
+ /* Reset to initial state for next marker */
+ marker->cur_marker = NULL;
+
+ /* Process the marker if interesting; else just make a generic trace msg */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, data, data_length, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, data, data_length, length);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
+ (int) (data_length + length));
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+METHODDEF(boolean)
+skip_variable (j_decompress_ptr cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+ INT32 length;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+/*
+ * Find the next JPEG marker, save it in cinfo->unread_marker.
+ * Returns FALSE if had to suspend before reaching a marker;
+ * in that case cinfo->unread_marker is unchanged.
+ *
+ * Note that the result might not be a valid marker code,
+ * but it will never be 0 or FF.
+ */
+
+LOCAL(boolean)
+next_marker (j_decompress_ptr cinfo)
+{
+ int c;
+ INPUT_VARS(cinfo);
+
+ for (;;) {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ /* Skip any non-FF bytes.
+ * This may look a bit inefficient, but it will not occur in a valid file.
+ * We sync after each discarded byte so that a suspending data source
+ * can discard the byte from its buffer.
+ */
+ while (c != 0xFF) {
+ cinfo->marker->discarded_bytes++;
+ INPUT_SYNC(cinfo);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ }
+ /* This loop swallows any duplicate FF bytes. Extra FFs are legal as
+ * pad bytes, so don't count them in discarded_bytes. We assume there
+ * will not be so many consecutive FF bytes as to overflow a suspending
+ * data source's input buffer.
+ */
+ do {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ } while (c == 0xFF);
+ if (c != 0)
+ break; /* found a valid marker, exit loop */
+ /* Reach here if we found a stuffed-zero data sequence (FF/00).
+ * Discard it and loop back to try again.
+ */
+ cinfo->marker->discarded_bytes += 2;
+ INPUT_SYNC(cinfo);
+ }
+
+ if (cinfo->marker->discarded_bytes != 0) {
+ WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
+ cinfo->marker->discarded_bytes = 0;
+ }
+
+ cinfo->unread_marker = c;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+first_marker (j_decompress_ptr cinfo)
+/* Like next_marker, but used to obtain the initial SOI marker. */
+/* For this marker, we do not allow preceding garbage or fill; otherwise,
+ * we might well scan an entire input file before realizing it ain't JPEG.
+ * If an application wants to process non-JFIF files, it must seek to the
+ * SOI before calling the JPEG library.
+ */
+{
+ int c, c2;
+ INPUT_VARS(cinfo);
+
+ INPUT_BYTE(cinfo, c, return FALSE);
+ INPUT_BYTE(cinfo, c2, return FALSE);
+ if (c != 0xFF || c2 != (int) M_SOI)
+ ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+ cinfo->unread_marker = c2;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Read markers until SOS or EOI.
+ *
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+
+METHODDEF(int)
+read_markers (j_decompress_ptr cinfo)
+{
+ /* Outer loop repeats once for each marker. */
+ for (;;) {
+ /* Collect the marker proper, unless we already did. */
+ /* NB: first_marker() enforces the requirement that SOI appear first. */
+ if (cinfo->unread_marker == 0) {
+ if (! cinfo->marker->saw_SOI) {
+ if (! first_marker(cinfo))
+ return JPEG_SUSPENDED;
+ } else {
+ if (! next_marker(cinfo))
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* At this point cinfo->unread_marker contains the marker code and the
+ * input point is just past the marker proper, but before any parameters.
+ * A suspension will cause us to return with this state still true.
+ */
+ switch (cinfo->unread_marker) {
+ case M_SOI:
+ if (! get_soi(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF0: /* Baseline */
+ case M_SOF1: /* Extended sequential, Huffman */
+ if (! get_sof(cinfo, JPROC_SEQUENTIAL, FALSE, DCTSIZE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF2: /* Progressive, Huffman */
+ if (! get_sof(cinfo, JPROC_PROGRESSIVE, FALSE, DCTSIZE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF3: /* Lossless, Huffman */
+ if (! get_sof(cinfo, JPROC_LOSSLESS, FALSE, 1))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF9: /* Extended sequential, arithmetic */
+ if (! get_sof(cinfo, JPROC_SEQUENTIAL, TRUE, DCTSIZE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF10: /* Progressive, arithmetic */
+ if (! get_sof(cinfo, JPROC_PROGRESSIVE, TRUE, DCTSIZE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF11: /* Lossless, arithmetic */
+ if (! get_sof(cinfo, JPROC_LOSSLESS, TRUE, 1))
+ return JPEG_SUSPENDED;
+ break;
+
+ /* Currently unsupported SOFn types */
+ case M_SOF5: /* Differential sequential, Huffman */
+ case M_SOF6: /* Differential progressive, Huffman */
+ case M_SOF7: /* Differential lossless, Huffman */
+ case M_JPG: /* Reserved for JPEG extensions */
+ case M_SOF13: /* Differential sequential, arithmetic */
+ case M_SOF14: /* Differential progressive, arithmetic */
+ case M_SOF15: /* Differential lossless, arithmetic */
+ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
+ break;
+
+ case M_SOS:
+ if (! get_sos(cinfo))
+ return JPEG_SUSPENDED;
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_SOS;
+
+ case M_EOI:
+ TRACEMS(cinfo, 1, JTRC_EOI);
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_EOI;
+
+ case M_DAC:
+ if (! get_dac(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DHT:
+ if (! get_dht(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DQT:
+ if (! get_dqt(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DRI:
+ if (! get_dri(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_APP0:
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP14:
+ case M_APP15:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
+ cinfo->unread_marker - (int) M_APP0]) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_COM:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_RST0: /* these are all parameterless */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
+ break;
+
+ case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
+ if (! skip_variable(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ default: /* must be DHP, EXP, JPGn, or RESn */
+ /* For now, we treat the reserved markers as fatal errors since they are
+ * likely to be used to signal incompatible JPEG Part 3 extensions.
+ * Once the JPEG 3 version-number marker is well defined, this code
+ * ought to change!
+ */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+ /* Successfully processed marker, so reset state variable */
+ cinfo->unread_marker = 0;
+ } /* end loop */
+}
+
+
+/*
+ * Read a restart marker, which is expected to appear next in the datastream;
+ * if the marker is not there, take appropriate recovery action.
+ * Returns FALSE if suspension is required.
+ *
+ * This is called by the entropy decoder after it has read an appropriate
+ * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder
+ * has already read a marker from the data source. Under normal conditions
+ * cinfo->unread_marker will be reset to 0 before returning; if not reset,
+ * it holds a marker which the decoder will be unable to read past.
+ */
+
+METHODDEF(boolean)
+read_restart_marker (j_decompress_ptr cinfo)
+{
+ /* Obtain a marker unless we already did. */
+ /* Note that next_marker will complain if it skips any data. */
+ if (cinfo->unread_marker == 0) {
+ if (! next_marker(cinfo))
+ return FALSE;
+ }
+
+ if (cinfo->unread_marker ==
+ ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+ /* Normal case --- swallow the marker and let entropy decoder continue */
+ TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
+ cinfo->unread_marker = 0;
+ } else {
+ /* Uh-oh, the restart markers have been messed up. */
+ /* Let the data source manager determine how to resync. */
+ if (! (*cinfo->src->resync_to_restart) (cinfo,
+ cinfo->marker->next_restart_num))
+ return FALSE;
+ }
+
+ /* Update next-restart state */
+ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
+
+ return TRUE;
+}
+
+
+/*
+ * This is the default resync_to_restart method for data source managers
+ * to use if they don't have any better approach. Some data source managers
+ * may be able to back up, or may have additional knowledge about the data
+ * which permits a more intelligent recovery strategy; such managers would
+ * presumably supply their own resync method.
+ *
+ * read_restart_marker calls resync_to_restart if it finds a marker other than
+ * the restart marker it was expecting. (This code is *not* used unless
+ * a nonzero restart interval has been declared.) cinfo->unread_marker is
+ * the marker code actually found (might be anything, except 0 or FF).
+ * The desired restart marker number (0..7) is passed as a parameter.
+ * This routine is supposed to apply whatever error recovery strategy seems
+ * appropriate in order to position the input stream to the next data segment.
+ * Note that cinfo->unread_marker is treated as a marker appearing before
+ * the current data-source input point; usually it should be reset to zero
+ * before returning.
+ * Returns FALSE if suspension is required.
+ *
+ * This implementation is substantially constrained by wanting to treat the
+ * input as a data stream; this means we can't back up. Therefore, we have
+ * only the following actions to work with:
+ * 1. Simply discard the marker and let the entropy decoder resume at next
+ * byte of file.
+ * 2. Read forward until we find another marker, discarding intervening
+ * data. (In theory we could look ahead within the current bufferload,
+ * without having to discard data if we don't find the desired marker.
+ * This idea is not implemented here, in part because it makes behavior
+ * dependent on buffer size and chance buffer-boundary positions.)
+ * 3. Leave the marker unread (by failing to zero cinfo->unread_marker).
+ * This will cause the entropy decoder to process an empty data segment,
+ * inserting dummy zeroes, and then we will reprocess the marker.
+ *
+ * #2 is appropriate if we think the desired marker lies ahead, while #3 is
+ * appropriate if the found marker is a future restart marker (indicating
+ * that we have missed the desired restart marker, probably because it got
+ * corrupted).
+ * We apply #2 or #3 if the found marker is a restart marker no more than
+ * two counts behind or ahead of the expected one. We also apply #2 if the
+ * found marker is not a legal JPEG marker code (it's certainly bogus data).
+ * If the found marker is a restart marker more than 2 counts away, we do #1
+ * (too much risk that the marker is erroneous; with luck we will be able to
+ * resync at some future point).
+ * For any valid non-restart JPEG marker, we apply #3. This keeps us from
+ * overrunning the end of a scan. An implementation limited to single-scan
+ * files might find it better to apply #2 for markers other than EOI, since
+ * any other marker would have to be bogus data in that case.
+ */
+
+GLOBAL(boolean)
+jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+{
+ int marker = cinfo->unread_marker;
+ int action = 1;
+
+ /* Always put up a warning. */
+ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
+
+ /* Outer loop handles repeated decision after scanning forward. */
+ for (;;) {
+ if (marker < (int) M_SOF0)
+ action = 2; /* invalid marker */
+ else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+ action = 3; /* valid non-restart marker */
+ else {
+ if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired+2) & 7)))
+ action = 3; /* one of the next two expected restarts */
+ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired-2) & 7)))
+ action = 2; /* a prior restart, so advance */
+ else
+ action = 1; /* desired restart or too far away */
+ }
+ TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
+ switch (action) {
+ case 1:
+ /* Discard marker and let entropy decoder resume processing. */
+ cinfo->unread_marker = 0;
+ return TRUE;
+ case 2:
+ /* Scan to the next marker, and repeat the decision loop. */
+ if (! next_marker(cinfo))
+ return FALSE;
+ marker = cinfo->unread_marker;
+ break;
+ case 3:
+ /* Return without advancing past this marker. */
+ /* Entropy decoder will be forced to process an empty segment. */
+ return TRUE;
+ }
+ } /* end loop */
+}
+
+
+/*
+ * Reset marker processing state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ cinfo->comp_info = NULL; /* until allocated by get_sof */
+ cinfo->input_scan_number = 0; /* no SOS seen yet */
+ cinfo->unread_marker = 0; /* no pending marker */
+ marker->pub.saw_SOI = FALSE; /* set internal state too */
+ marker->pub.saw_SOF = FALSE;
+ marker->pub.discarded_bytes = 0;
+ marker->cur_marker = NULL;
+}
+
+
+/*
+ * Initialize the marker reader module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker;
+ int i;
+
+ /* Create subobject in permanent pool */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_marker_reader));
+ cinfo->marker = (struct jpeg_marker_reader *) marker;
+ /* Initialize public method pointers */
+ marker->pub.reset_marker_reader = reset_marker_reader;
+ marker->pub.read_markers = read_markers;
+ marker->pub.read_restart_marker = read_restart_marker;
+ /* Initialize COM/APPn processing.
+ * By default, we examine and then discard APP0 and APP14,
+ * but simply discard COM and all other APPn.
+ */
+ marker->process_COM = skip_variable;
+ marker->length_limit_COM = 0;
+ for (i = 0; i < 16; i++) {
+ marker->process_APPn[i] = skip_variable;
+ marker->length_limit_APPn[i] = 0;
+ }
+ marker->process_APPn[0] = get_interesting_appn;
+ marker->process_APPn[14] = get_interesting_appn;
+ /* Reset marker processing state */
+ reset_marker_reader(cinfo);
+}
+
+
+/*
+ * Control saving of COM and APPn markers into marker_list.
+ */
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+GLOBAL(void)
+jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ long maxlength;
+ jpeg_marker_parser_method processor;
+
+ /* Length limit mustn't be larger than what we can allocate
+ * (should only be a concern in a 16-bit environment).
+ */
+ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
+ if (((long) length_limit) > maxlength)
+ length_limit = (unsigned int) maxlength;
+
+ /* Choose processor routine to use.
+ * APP0/APP14 have special requirements.
+ */
+ if (length_limit) {
+ processor = save_marker;
+ /* If saving APP0/APP14, save at least enough for our internal use. */
+ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+ length_limit = APP0_DATA_LEN;
+ else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+ length_limit = APP14_DATA_LEN;
+ } else {
+ processor = skip_variable;
+ /* If discarding APP0/APP14, use our regular on-the-fly processor. */
+ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+ processor = get_interesting_appn;
+ }
+
+ if (marker_code == (int) M_COM) {
+ marker->process_COM = processor;
+ marker->length_limit_COM = length_limit;
+ } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
+ marker->process_APPn[marker_code - (int) M_APP0] = processor;
+ marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+ } else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+/*
+ * Install a special processing method for COM or APPn markers.
+ */
+
+GLOBAL(void)
+jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ if (marker_code == (int) M_COM)
+ marker->process_COM = routine;
+ else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
+ marker->process_APPn[marker_code - (int) M_APP0] = routine;
+ else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmaster.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmaster.cpp
new file mode 100644
index 00000000..9fffa066
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmaster.cpp
@@ -0,0 +1,461 @@
+/*
+ * jdmaster.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG decompressor.
+ * These routines are concerned with selecting the modules to be executed
+ * and with determining the number of passes and the work to be done in each
+ * pass.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_decomp_master pub; /* public fields */
+
+ int pass_number; /* # of passes completed */
+
+ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
+
+ /* Saved references to initialized quantizer modules,
+ * in case we need to switch modes.
+ */
+ struct jpeg_color_quantizer * quantizer_1pass;
+ struct jpeg_color_quantizer * quantizer_2pass;
+} my_decomp_master;
+
+typedef my_decomp_master * my_master_ptr;
+
+
+/*
+ * Determine whether merged upsample/color conversion should be used.
+ * CRUCIAL: this must match the actual capabilities of jdmerge.c!
+ */
+
+LOCAL(boolean)
+use_merged_upsample (j_decompress_ptr cinfo)
+{
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ /* Merging is the equivalent of plain box-filter upsampling */
+ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
+ return FALSE;
+ /* jdmerge.c only supports YCC=>RGB color conversion */
+ if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
+ cinfo->out_color_space != JCS_RGB ||
+ cinfo->out_color_components != RGB_PIXELSIZE)
+ return FALSE;
+ /* and it only handles 2h1v or 2h2v sampling ratios */
+ if (cinfo->comp_info[0].h_samp_factor != 2 ||
+ cinfo->comp_info[1].h_samp_factor != 1 ||
+ cinfo->comp_info[2].h_samp_factor != 1 ||
+ cinfo->comp_info[0].v_samp_factor > 2 ||
+ cinfo->comp_info[1].v_samp_factor != 1 ||
+ cinfo->comp_info[2].v_samp_factor != 1)
+ return FALSE;
+ /* furthermore, it doesn't work if each component has been
+ processed differently */
+ if (cinfo->comp_info[0].codec_data_unit != cinfo->min_codec_data_unit ||
+ cinfo->comp_info[1].codec_data_unit != cinfo->min_codec_data_unit ||
+ cinfo->comp_info[2].codec_data_unit != cinfo->min_codec_data_unit)
+ return FALSE;
+ /* ??? also need to test for upsample-time rescaling, when & if supported */
+ return TRUE; /* by golly, it'll work... */
+#else
+ return FALSE;
+#endif
+}
+
+
+/*
+ * Compute output image dimensions and related values.
+ * NOTE: this is exported for possible use by application.
+ * Hence it mustn't do anything that can't be done twice.
+ * Also note that it may be called before the master module is initialized!
+ */
+
+GLOBAL(void)
+jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_READY)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->codec->calc_output_dimensions) (cinfo);
+
+ /* Report number of components in selected colorspace. */
+ /* Probably this should be in the color conversion module... */
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ break;
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ break;
+#endif /* else share code with YCbCr */
+ case JCS_YCbCr:
+ cinfo->out_color_components = 3;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+ cinfo->out_color_components = 4;
+ break;
+ default: /* else must be same colorspace as in file */
+ cinfo->out_color_components = cinfo->num_components;
+ break;
+ }
+ cinfo->output_components = (cinfo->quantize_colors ? 1 :
+ cinfo->out_color_components);
+
+ /* See if upsampler will want to emit more than one row at a time */
+ if (use_merged_upsample(cinfo))
+ cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
+ else
+ cinfo->rec_outbuf_height = 1;
+}
+
+
+/*
+ * Several decompression processes need to range-limit values to the range
+ * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
+ * due to noise introduced by quantization, roundoff error, etc. These
+ * processes are inner loops and need to be as fast as possible. On most
+ * machines, particularly CPUs with pipelines or instruction prefetch,
+ * a (subscript-check-less) C table lookup
+ * x = sample_range_limit[x];
+ * is faster than explicit tests
+ * if (x < 0) x = 0;
+ * else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
+ * These processes all use a common table prepared by the routine below.
+ *
+ * For most steps we can mathematically guarantee that the initial value
+ * of x is within MAXJSAMPLE+1 of the legal range, so a table running from
+ * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
+ * limiting step (just after the IDCT), a wildly out-of-range value is
+ * possible if the input data is corrupt. To avoid any chance of indexing
+ * off the end of memory and getting a bad-pointer trap, we perform the
+ * post-IDCT limiting thus:
+ * x = range_limit[x & MASK];
+ * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
+ * samples. Under normal circumstances this is more than enough range and
+ * a correct output will be generated; with bogus input data the mask will
+ * cause wraparound, and we will safely generate a bogus-but-in-range output.
+ * For the post-IDCT step, we want to convert the data from signed to unsigned
+ * representation by adding CENTERJSAMPLE at the same time that we limit it.
+ * So the post-IDCT limiting table ends up looking like this:
+ * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
+ * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0,1,...,CENTERJSAMPLE-1
+ * Negative inputs select values from the upper half of the table after
+ * masking.
+ *
+ * We can save some space by overlapping the start of the post-IDCT table
+ * with the simpler range limiting table. The post-IDCT table begins at
+ * sample_range_limit + CENTERJSAMPLE.
+ *
+ * Note that the table is allocated in near data space on PCs; it's small
+ * enough and used often enough to justify this.
+ */
+
+LOCAL(void)
+prepare_range_limit_table (j_decompress_ptr cinfo)
+/* Allocate and fill in the sample_range_limit table */
+{
+ JSAMPLE * table;
+ int i;
+
+ table = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
+ cinfo->sample_range_limit = table;
+ /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+ /* Main part of "simple" table: limit[x] = x */
+ for (i = 0; i <= MAXJSAMPLE; i++)
+ table[i] = (JSAMPLE) i;
+ table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
+ /* End of simple table, rest of first half of post-IDCT table */
+ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+ table[i] = MAXJSAMPLE;
+ /* Second half of post-IDCT table */
+ MEMZERO(table + (2 * (MAXJSAMPLE+1)),
+ (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+ cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
+}
+
+
+/*
+ * Master selection of decompression modules.
+ * This is done once at jpeg_start_decompress time. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ * We also initialize the decompressor input side to begin consuming data.
+ *
+ * Since jpeg_read_header has finished, we know what is in the SOF
+ * and (first) SOS markers. We also have all the application parameter
+ * settings.
+ */
+
+LOCAL(void)
+master_selection (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ /* Initialize dimensions and other stuff */
+ jpeg_calc_output_dimensions(cinfo);
+ prepare_range_limit_table(cinfo);
+
+ /* Width of an output scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* Initialize my private state */
+ master->pass_number = 0;
+ master->using_merged_upsample = use_merged_upsample(cinfo);
+
+ /* Color quantizer selection */
+ master->quantizer_1pass = NULL;
+ master->quantizer_2pass = NULL;
+ /* No mode changes if not using buffered-image mode. */
+ if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ }
+ if (cinfo->quantize_colors) {
+ if (cinfo->raw_data_out)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ /* 2-pass quantizer only works in 3-component color space. */
+ if (cinfo->out_color_components != 3) {
+ cinfo->enable_1pass_quant = TRUE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ cinfo->colormap = NULL;
+ } else if (cinfo->colormap != NULL) {
+ cinfo->enable_external_quant = TRUE;
+ } else if (cinfo->two_pass_quantize) {
+ cinfo->enable_2pass_quant = TRUE;
+ } else {
+ cinfo->enable_1pass_quant = TRUE;
+ }
+
+ if (cinfo->enable_1pass_quant) {
+#ifdef QUANT_1PASS_SUPPORTED
+ jinit_1pass_quantizer(cinfo);
+ master->quantizer_1pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+
+ /* We use the 2-pass code to map to external colormaps. */
+ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
+#ifdef QUANT_2PASS_SUPPORTED
+ jinit_2pass_quantizer(cinfo);
+ master->quantizer_2pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+ /* If both quantizers are initialized, the 2-pass one is left active;
+ * this is necessary for starting with quantization to an external map.
+ */
+ }
+
+ /* Post-processing: in particular, color conversion first */
+ if (! cinfo->raw_data_out) {
+ if (master->using_merged_upsample) {
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ jinit_merged_upsampler(cinfo); /* does color conversion too */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ jinit_color_deconverter(cinfo);
+ jinit_upsampler(cinfo);
+ }
+ jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
+ }
+
+ /* Initialize principal buffer controllers. */
+ if (! cinfo->raw_data_out)
+ jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* If jpeg_start_decompress will read the whole file, initialize
+ * progress monitoring appropriately. The input step is counted
+ * as one pass.
+ */
+ if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+ cinfo->inputctl->has_multiple_scans) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
+ /* Count the input pass as done */
+ master->pass_number++;
+ }
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each output pass. We determine which
+ * modules will be active during this pass and give them appropriate
+ * start_pass calls. We also set is_dummy_pass to indicate whether this
+ * is a "real" output pass or a dummy pass for color quantization.
+ * (In the latter case, jdapistd.c will crank the pass to completion.)
+ */
+
+METHODDEF(void)
+prepare_for_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (master->pub.is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Final pass of 2-pass quantization */
+ master->pub.is_dummy_pass = FALSE;
+ (*cinfo->cquantize->start_pass) (cinfo, FALSE);
+ (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
+ (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ if (cinfo->quantize_colors && cinfo->colormap == NULL) {
+ /* Select new quantization method */
+ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
+ cinfo->cquantize = master->quantizer_2pass;
+ master->pub.is_dummy_pass = TRUE;
+ } else if (cinfo->enable_1pass_quant) {
+ cinfo->cquantize = master->quantizer_1pass;
+ } else {
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+ }
+ }
+ (*cinfo->codec->start_output_pass) (cinfo);
+ if (! cinfo->raw_data_out) {
+ if (! master->using_merged_upsample)
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->upsample->start_pass) (cinfo);
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
+ (*cinfo->post->start_pass) (cinfo,
+ (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ }
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->pass_number +
+ (master->pub.is_dummy_pass ? 2 : 1);
+ /* In buffered-image mode, we assume one more output pass if EOI not
+ * yet reached, but no more passes if EOI has been reached.
+ */
+ if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+ cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
+ }
+ }
+}
+
+
+/*
+ * Finish up at end of an output pass.
+ */
+
+METHODDEF(void)
+finish_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->finish_pass) (cinfo);
+ master->pass_number++;
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+GLOBAL(void)
+jpeg_new_colormap (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_BUFIMAGE)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (cinfo->quantize_colors && cinfo->enable_external_quant &&
+ cinfo->colormap != NULL) {
+ /* Select 2-pass quantizer for external colormap use */
+ cinfo->cquantize = master->quantizer_2pass;
+ /* Notify quantizer of colormap change */
+ (*cinfo->cquantize->new_color_map) (cinfo);
+ master->pub.is_dummy_pass = FALSE; /* just in case */
+ } else
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize master decompression control and select active modules.
+ * This is performed at the start of jpeg_start_decompress.
+ */
+
+GLOBAL(void)
+jinit_master_decompress (j_decompress_ptr cinfo)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_decomp_master));
+ cinfo->master = (struct jpeg_decomp_master *) master;
+ master->pub.prepare_for_output_pass = prepare_for_output_pass;
+ master->pub.finish_output_pass = finish_output_pass;
+
+ master->pub.is_dummy_pass = FALSE;
+
+ master_selection(cinfo);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmerge.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmerge.cpp
new file mode 100644
index 00000000..3907dc36
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdmerge.cpp
@@ -0,0 +1,401 @@
+/*
+ * jdmerge.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains code for merged upsampling/color conversion.
+ *
+ * This file combines functions from jdsample.c and jdcolor.c;
+ * read those files first to understand what's going on.
+ *
+ * When the chroma components are to be upsampled by simple replication
+ * (ie, box filtering), we can save some work in color conversion by
+ * calculating all the output pixels corresponding to a pair of chroma
+ * samples at one time. In the conversion equations
+ * R = Y + K1 * Cr
+ * G = Y + K2 * Cb + K3 * Cr
+ * B = Y + K4 * Cb
+ * only the Y term varies among the group of pixels corresponding to a pair
+ * of chroma samples, so the rest of the terms can be calculated just once.
+ * At typical sampling ratios, this eliminates half or three-quarters of the
+ * multiplications needed for color conversion.
+ *
+ * This file currently provides implementations for the following cases:
+ * YCbCr => RGB color conversion only.
+ * Sampling ratios of 2h1v or 2h2v.
+ * No scaling needed at upsample time.
+ * Corner-aligned (non-CCIR601) sampling alignment.
+ * Other special cases could be added, but in most applications these are
+ * the only common cases. (For uncommon cases we fall back on the more
+ * general code in jdsample.c and jdcolor.c.)
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Pointer to routine to do actual upsampling/conversion of one row group */
+ JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf));
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+
+ /* For 2:1 vertical sampling, we produce two output rows at a time.
+ * We need a "spare" row buffer to hold the second output row if the
+ * application provides just a one-row buffer; we also use the spare
+ * to discard the dummy last row if the image height is odd.
+ */
+ JSAMPROW spare_row;
+ boolean spare_full; /* T if spare buffer is occupied */
+
+ JDIMENSION out_row_width; /* samples per output row */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX_JDMERGE(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ * This is taken directly from jdcolor.c; see that file for more info.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ upsample->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ upsample->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ upsample->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX_JDMERGE(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ upsample->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX_JDMERGE(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ upsample->Cr_g_tab[i] = (- FIX_JDMERGE(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ upsample->Cb_g_tab[i] = (- FIX_JDMERGE(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_merged_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the spare buffer empty */
+ upsample->spare_full = FALSE;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * The control routine just handles the row buffering considerations.
+ */
+
+METHODDEF(void)
+merged_2v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 2:1 vertical sampling case: may need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPROW work_ptrs[2];
+ JDIMENSION num_rows; /* number of rows returned to caller */
+
+ if (upsample->spare_full) {
+ /* If we have a spare row saved from a previous cycle, just return it. */
+ jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
+ 1, upsample->out_row_width);
+ num_rows = 1;
+ upsample->spare_full = FALSE;
+ } else {
+ /* Figure number of rows to return to caller. */
+ num_rows = 2;
+ /* Not more than the distance to the end of the image. */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+ /* Create output pointer array for upsampler. */
+ work_ptrs[0] = output_buf[*out_row_ctr];
+ if (num_rows > 1) {
+ work_ptrs[1] = output_buf[*out_row_ctr + 1];
+ } else {
+ work_ptrs[1] = upsample->spare_row;
+ upsample->spare_full = TRUE;
+ }
+ /* Now do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
+ }
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (! upsample->spare_full)
+ (*in_row_group_ctr)++;
+}
+
+
+METHODDEF(void)
+merged_1v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 1:1 vertical sampling case: much easier, never need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Just do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
+ output_buf + *out_row_ctr);
+ /* Adjust counts */
+ (*out_row_ctr)++;
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by the control routines to do
+ * the actual upsampling/conversion. One row group is processed per call.
+ *
+ * Note: since we may be writing directly into application-supplied buffers,
+ * we have to be honest about the output width; we can't assume the buffer
+ * has been rounded up to an even width.
+ */
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
+ */
+
+METHODDEF(void)
+h2v1_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr;
+ JSAMPROW inptr0, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr0 = input_buf[0][in_row_group_ctr];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr = output_buf[0];
+ /* Loop for each pair of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 2 Y values and emit 2 pixels */
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr0);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
+ */
+
+METHODDEF(void)
+h2v2_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr0, outptr1;
+ JSAMPROW inptr00, inptr01, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr00 = input_buf[0][in_row_group_ctr*2];
+ inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr0 = output_buf[0];
+ outptr1 = output_buf[1];
+ /* Loop for each group of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 4 Y values and emit 4 pixels */
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr00);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ y = GETJSAMPLE(*inptr01);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Module initialization routine for merged upsampling/color conversion.
+ *
+ * NB: this is called under the conditions determined by use_merged_upsample()
+ * in jdmaster.c. That routine MUST correspond to the actual capabilities
+ * of this module; no safety checks are made here.
+ */
+
+GLOBAL(void)
+jinit_merged_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_merged_upsample;
+ upsample->pub.need_context_rows = FALSE;
+
+ upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
+
+ if (cinfo->max_v_samp_factor == 2) {
+ upsample->pub.upsample = merged_2v_upsample;
+ upsample->upmethod = h2v2_merged_upsample;
+ /* Allocate a spare row buffer */
+ upsample->spare_row = (JSAMPROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
+ } else {
+ upsample->pub.upsample = merged_1v_upsample;
+ upsample->upmethod = h2v1_merged_upsample;
+ /* No spare row needed */
+ upsample->spare_row = NULL;
+ }
+
+ build_ycc_rgb_table(cinfo);
+}
+
+#endif /* UPSAMPLE_MERGING_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdphuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdphuff.cpp
new file mode 100644
index 00000000..d669202e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdphuff.cpp
@@ -0,0 +1,676 @@
+/*
+ * jdphuff.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for progressive JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy subsystem */
+//#include "jdhuff.h" /* Declarations shared with jd*huff.c */
+
+
+#ifdef D_PROGRESSIVE_SUPPORTED
+
+/*
+ * Private entropy decoder object for progressive Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ unsigned int EOBRUN; /* remaining EOBs in EOBRUN */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).EOBRUN = (src).EOBRUN, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ huffd_common_fields; /* Fields shared with other entropy decoders */
+
+ /* These fields are loaded into local variables at start of each MCU.
+ * In case of suspension, we exit WITHOUT updating them.
+ */
+ savable_state saved; /* Other state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
+} phuff_entropy_decoder;
+
+typedef phuff_entropy_decoder * phuff_entropy_ptr;
+
+/* Forward declarations */
+METHODDEF(boolean) decode_mcu_DC_first JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_first JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_DC_refine JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+METHODDEF(boolean) decode_mcu_AC_refine JPP((j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_phuff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ boolean is_DC_band, bad;
+ int ci, coefi, tbl;
+ int *coef_bit_ptr;
+ jpeg_component_info * compptr;
+
+ is_DC_band = (cinfo->Ss == 0);
+
+ /* Validate scan parameters */
+ bad = FALSE;
+ if (is_DC_band) {
+ if (cinfo->Se != 0)
+ bad = TRUE;
+ } else {
+ /* need not check Ss/Se < 0 since they came from unsigned bytes */
+ if (cinfo->Ss > cinfo->Se || cinfo->Se >= DCTSIZE2)
+ bad = TRUE;
+ /* AC scans may have only one component */
+ if (cinfo->comps_in_scan != 1)
+ bad = TRUE;
+ }
+ if (cinfo->Ah != 0) {
+ /* Successive approximation refinement scan: must have Al = Ah-1. */
+ if (cinfo->Al != cinfo->Ah-1)
+ bad = TRUE;
+ }
+ if (cinfo->Al > 13) /* need not check for < 0 */
+ bad = TRUE;
+ /* Arguably the maximum Al value should be less than 13 for 8-bit precision,
+ * but the spec doesn't say so, and we try to be liberal about what we
+ * accept. Note: large Al values could result in out-of-range DC
+ * coefficients during early scans, leading to bizarre displays due to
+ * overflows in the IDCT math. But we won't crash.
+ */
+ if (bad)
+ ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
+ cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+ /* Update progression status, and verify that scan order is legal.
+ * Note that inter-scan inconsistencies are treated as warnings
+ * not fatal errors ... not clear if this is right way to behave.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ int cindex = cinfo->cur_comp_info[ci]->component_index;
+ coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ if (!is_DC_band && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+ for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
+ int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+ if (cinfo->Ah != expected)
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+ coef_bit_ptr[coefi] = cinfo->Al;
+ }
+ }
+
+ /* Select MCU decoding routine */
+ if (cinfo->Ah == 0) {
+ if (is_DC_band)
+ lossyd->entropy_decode_mcu = decode_mcu_DC_first;
+ else
+ lossyd->entropy_decode_mcu = decode_mcu_AC_first;
+ } else {
+ if (is_DC_band)
+ lossyd->entropy_decode_mcu = decode_mcu_DC_refine;
+ else
+ lossyd->entropy_decode_mcu = decode_mcu_AC_refine;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Make sure requested tables are present, and compute derived tables.
+ * We may build same derived table more than once, but it's not expensive.
+ */
+ if (is_DC_band) {
+ if (cinfo->Ah == 0) { /* DC refinement needs no table */
+ tbl = compptr->dc_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, TRUE, tbl,
+ & entropy->derived_tbls[tbl]);
+ }
+ } else {
+ tbl = compptr->ac_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, FALSE, tbl,
+ & entropy->derived_tbls[tbl]);
+ /* remember the single active table */
+ entropy->ac_derived_tbl = entropy->derived_tbls[tbl];
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->insufficient_data = FALSE;
+
+ /* Initialize private state variables */
+ entropy->saved.EOBRUN = 0;
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] = /* entry n is 2**(n-1) */
+ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+ ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+ ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Re-init EOB run count, too */
+ entropy->saved.EOBRUN = 0;
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Huffman MCU decoding.
+ * Each of these routines decodes and returns one MCU's worth of
+ * Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
+ *
+ * We return FALSE if data source requested suspension. In that case no
+ * changes have been made to permanent state. (Exception: some output
+ * coefficients may already have been assigned. This is harmless for
+ * spectral selection, since we'll just re-assign them on the next call.
+ * Successive approximation AC refinement has to be more careful, however.)
+ */
+
+/*
+ * MCU decoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ int Al = cinfo->Al;
+ register int s, r;
+ int blkn, ci;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ savable_state state;
+ d_derived_tbl * tbl;
+ jpeg_component_info * compptr;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ tbl = entropy->derived_tbls[compptr->dc_tbl_no];
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+
+ /* Convert DC difference to actual value, update last_dc_val */
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
+ (*block)[0] = (JCOEF) (s << Al);
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->insufficient_data) {
+
+ /* Load up working state.
+ * We can avoid loading/saving bitread state if in an EOB run.
+ */
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+
+ if (EOBRUN > 0) /* if it's a band of zeroes... */
+ EOBRUN--; /* ...process it now (we do nothing) */
+ else {
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Scale and output coefficient in natural (dezigzagged) order */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
+ } else {
+ if (r == 15) { /* ZRL */
+ k += 15; /* skip 15 zeroes in band */
+ } else { /* EOBr, run length is 2^r + appended bits */
+ EOBRUN = 1 << r;
+ if (r) { /* EOBr, r > 0 */
+ CHECK_BIT_BUFFER(br_state, r, return FALSE);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ EOBRUN--; /* this band is processed at this moment */
+ break; /* force end-of-band */
+ }
+ }
+ }
+
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ }
+
+ /* Completed MCU, so update state */
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int blkn;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* Not worth the cycles to check insufficient_data here,
+ * since we will not change the data anyway if we read zeroes.
+ */
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* Encoded data is simply the next bit of the two's-complement DC value */
+ CHECK_BIT_BUFFER(br_state, 1, return FALSE);
+ if (GET_BITS(1))
+ (*block)[0] |= p1;
+ /* Note: since we use |=, repeating the assignment later is safe */
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy = (phuff_entropy_ptr) lossyd->entropy_private;
+ int Se = cinfo->Se;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ JCOEFPTR thiscoef;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+ int num_newnz;
+ int newnz_pos[DCTSIZE2];
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, don't modify the MCU.
+ */
+ if (! entropy->insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ /* If we are forced to suspend, we must undo the assignments to any newly
+ * nonzero coefficients in the block, because otherwise we'd get confused
+ * next time about which coefficients were already nonzero.
+ * But we need not undo addition of bits to already-nonzero coefficients;
+ * instead, we can test the current bit to see if we already did it.
+ */
+ num_newnz = 0;
+
+ /* initialize coefficient loop counter to start of band */
+ k = cinfo->Ss;
+
+ if (EOBRUN == 0) {
+ for (; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ if (s != 1) /* size of new coef should always be 1 */
+ WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1))
+ s = p1; /* newly nonzero coef is positive */
+ else
+ s = m1; /* newly nonzero coef is negative */
+ } else {
+ if (r != 15) {
+ EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */
+ if (r) {
+ CHECK_BIT_BUFFER(br_state, r, goto undoit);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ break; /* rest of block is handled by EOB logic */
+ }
+ /* note s = 0 for processing ZRL */
+ }
+ /* Advance over already-nonzero coefs and r still-zero coefs,
+ * appending correction bits to the nonzeroes. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ do {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ } else {
+ if (--r < 0)
+ break; /* reached target zero coefficient */
+ }
+ k++;
+ } while (k <= Se);
+ if (s) {
+ int pos = jpeg_natural_order[k];
+ /* Output newly nonzero coefficient */
+ (*block)[pos] = (JCOEF) s;
+ /* Remember its position in case we have to suspend */
+ newnz_pos[num_newnz++] = pos;
+ }
+ }
+ }
+
+ if (EOBRUN > 0) {
+ /* Scan any remaining coefficient positions after the end-of-band
+ * (the last newly nonzero coefficient, if any). Append a correction
+ * bit to each already-nonzero coefficient. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ for (; k <= Se; k++) {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ }
+ }
+ /* Count one block completed in EOB run */
+ EOBRUN--;
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+
+undoit:
+ /* Re-zero any output coefficients that we made newly nonzero */
+ while (num_newnz > 0)
+ (*block)[newnz_pos[--num_newnz]] = 0;
+
+ return FALSE;
+}
+
+
+/*
+ * Module initialization routine for progressive Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_phuff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ phuff_entropy_ptr entropy;
+ int *coef_bit_ptr;
+ int ci, i;
+
+ entropy = (phuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(phuff_entropy_decoder));
+ lossyd->entropy_private = (void *) entropy;
+ lossyd->entropy_start_pass = start_pass_phuff_decoder;
+
+ /* Mark derived tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ }
+
+ /* Create progression status table */
+ cinfo->coef_bits = (int (*)[DCTSIZE2])
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components*DCTSIZE2*SIZEOF(int));
+ coef_bit_ptr = & cinfo->coef_bits[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (i = 0; i < DCTSIZE2; i++)
+ *coef_bit_ptr++ = -1;
+}
+
+#endif /* D_PROGRESSIVE_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpostct.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpostct.cpp
new file mode 100644
index 00000000..e4e6066c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpostct.cpp
@@ -0,0 +1,291 @@
+/*
+ * jdpostct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the decompression postprocessing controller.
+ * This controller manages the upsampling, color conversion, and color
+ * quantization/reduction steps; specifically, it controls the buffering
+ * between upsample/color conversion and color quantization/reduction.
+ *
+ * If no color quantization/reduction is required, then this module has no
+ * work to do, and it just hands off to the upsample/color conversion code.
+ * An integrated upsample/convert/quantize process would replace this module
+ * entirely.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_post_controller pub; /* public fields */
+
+ /* Color quantization source buffer: this holds output data from
+ * the upsample/color conversion step to be passed to the quantizer.
+ * For two-pass color quantization, we need a full-image buffer;
+ * for one-pass operation, a strip buffer is sufficient.
+ */
+ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
+ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
+ JDIMENSION strip_height; /* buffer size in rows */
+ /* for two-pass mode only: */
+ JDIMENSION starting_row; /* row # of first row in current strip */
+ JDIMENSION next_row; /* index of next row to fill/empty in strip */
+} my_post_controller;
+
+typedef my_post_controller * my_post_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) post_process_1pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) post_process_prepass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+METHODDEF(void) post_process_2pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->quantize_colors) {
+ /* Single-pass processing with color quantization. */
+ post->pub.post_process_data = post_process_1pass;
+ /* We could be doing buffered-image output before starting a 2-pass
+ * color quantization; in that case, jinit_d_post_controller did not
+ * allocate a strip buffer. Use the virtual-array buffer as workspace.
+ */
+ if (post->buffer == NULL) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ (JDIMENSION) 0, post->strip_height, TRUE);
+ }
+ } else {
+ /* For single-pass processing without color quantization,
+ * I have no work to do; just call the upsampler directly.
+ */
+ post->pub.post_process_data = cinfo->upsample->upsample;
+ }
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ /* First pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_prepass;
+ break;
+ case JBUF_CRANK_DEST:
+ /* Second pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_2pass;
+ break;
+#endif /* QUANT_2PASS_SUPPORTED */
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+ post->starting_row = post->next_row = 0;
+}
+
+
+/*
+ * Process some data in the one-pass (strip buffer) case.
+ * This is used for color precision reduction as well as one-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_1pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Fill the buffer, but not more than what we can dump out in one go. */
+ /* Note we rely on the upsampler to detect bottom of image. */
+ max_rows = out_rows_avail - *out_row_ctr;
+ if (max_rows > post->strip_height)
+ max_rows = post->strip_height;
+ num_rows = 0;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &num_rows, max_rows);
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+ *out_row_ctr += num_rows;
+}
+
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+/*
+ * Process some data in the first pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_prepass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION old_next_row, num_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, TRUE);
+ }
+
+ /* Upsample some data (up to a strip height's worth). */
+ old_next_row = post->next_row;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &post->next_row, post->strip_height);
+
+ /* Allow quantizer to scan new data. No data is emitted, */
+ /* but we advance out_row_ctr so outer loop can tell when we're done. */
+ if (post->next_row > old_next_row) {
+ num_rows = post->next_row - old_next_row;
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
+ (JSAMPARRAY) NULL, (int) num_rows);
+ *out_row_ctr += num_rows;
+ }
+
+ /* Advance if we filled the strip. */
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+
+/*
+ * Process some data in the second pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_2pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, FALSE);
+ }
+
+ /* Determine number of rows to emit. */
+ num_rows = post->strip_height - post->next_row; /* available in strip */
+ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+ /* We have to check bottom of image here, can't depend on upsampler. */
+ max_rows = cinfo->output_height - post->starting_row;
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer + post->next_row, output_buf + *out_row_ctr,
+ (int) num_rows);
+ *out_row_ctr += num_rows;
+
+ /* Advance if we filled the strip. */
+ post->next_row += num_rows;
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize postprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_post_ptr post;
+
+ post = (my_post_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_post_controller));
+ cinfo->post = (struct jpeg_d_post_controller *) post;
+ post->pub.start_pass = start_pass_dpost;
+ post->whole_image = NULL; /* flag for no virtual arrays */
+ post->buffer = NULL; /* flag for no strip buffer */
+
+ /* Create the quantization buffer, if needed */
+ if (cinfo->quantize_colors) {
+ /* The buffer strip height is max_v_samp_factor, which is typically
+ * an efficient number of rows for upsampling to return.
+ * (In the presence of output rescaling, we might want to be smarter?)
+ */
+ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+ if (need_full_buffer) {
+ /* Two-pass color quantization: need full-image storage. */
+ /* We round up the number of rows to a multiple of the strip height. */
+#ifdef QUANT_2PASS_SUPPORTED
+ post->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ cinfo->output_width * cinfo->out_color_components,
+ (JDIMENSION) jround_up((long) cinfo->output_height,
+ (long) post->strip_height),
+ post->strip_height);
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ /* One-pass color quantization: just make a strip buffer. */
+ post->buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width * cinfo->out_color_components,
+ post->strip_height);
+ }
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpred.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpred.cpp
new file mode 100644
index 00000000..d5af559e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdpred.cpp
@@ -0,0 +1,248 @@
+/*
+ * jdpred.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample undifferencing (reconstruction) for lossless JPEG.
+ *
+ * In order to avoid paying the performance penalty of having to check the
+ * predictor being used and the row being processed for each call of the
+ * undifferencer, and to promote optimization, we have separate undifferencing
+ * functions for each case.
+ *
+ * We are able to avoid duplicating source code by implementing the predictors
+ * and undifferencers as macros. Each of the undifferencing functions are
+ * simply wrappers around an UNDIFFERENCE macro with the appropriate PREDICTOR
+ * macro passed as an argument.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/* Predictor for the first column of the first row: 2^(P-Pt-1) */
+#define INITIAL_PREDICTORx (1 << (cinfo->data_precision - cinfo->Al - 1))
+
+/* Predictor for the first column of the remaining rows: Rb */
+#define INITIAL_PREDICTOR2 GETJSAMPLE(prev_row[0])
+
+
+/*
+ * 1-Dimensional undifferencer routine.
+ *
+ * This macro implements the 1-D horizontal predictor (1). INITIAL_PREDICTOR
+ * is used as the special case predictor for the first column, which must be
+ * either INITIAL_PREDICTOR2 or INITIAL_PREDICTORx. The remaining samples
+ * use PREDICTOR1.
+ *
+ * The reconstructed sample is supposed to be calculated modulo 2^16, so we
+ * logically AND the result with 0xFFFF.
+*/
+
+#define UNDIFFERENCE_1D(INITIAL_PREDICTOR) \
+ int xindex; \
+ int Ra; \
+ \
+ Ra = (diff_buf[0] + INITIAL_PREDICTOR) & 0xFFFF; \
+ undiff_buf[0] = Ra; \
+ \
+ for (xindex = 1; xindex < (int)width; xindex++) { \
+ Ra = (diff_buf[xindex] + PREDICTOR1) & 0xFFFF; \
+ undiff_buf[xindex] = Ra; \
+ }
+
+/*
+ * 2-Dimensional undifferencer routine.
+ *
+ * This macro implements the 2-D horizontal predictors (#2-7). PREDICTOR2 is
+ * used as the special case predictor for the first column. The remaining
+ * samples use PREDICTOR, which is a function of Ra, Rb, Rc.
+ *
+ * Because prev_row and output_buf may point to the same storage area (in an
+ * interleaved image with Vi=1, for example), we must take care to buffer Rb/Rc
+ * before writing the current reconstructed sample value into output_buf.
+ *
+ * The reconstructed sample is supposed to be calculated modulo 2^16, so we
+ * logically AND the result with 0xFFFF.
+ */
+
+#define UNDIFFERENCE_2D(PREDICTOR) \
+ int xindex; \
+ int Ra, Rb, Rc; \
+ \
+ Rb = GETJSAMPLE(prev_row[0]); \
+ Ra = (diff_buf[0] + PREDICTOR2) & 0xFFFF; \
+ undiff_buf[0] = Ra; \
+ \
+ for (xindex = 1; xindex < (int)width; xindex++) { \
+ Rc = Rb; \
+ Rb = GETJSAMPLE(prev_row[xindex]); \
+ Ra = (diff_buf[xindex] + PREDICTOR) & 0xFFFF; \
+ undiff_buf[xindex] = Ra; \
+ }
+
+
+/*
+ * Undifferencers for the all rows but the first in a scan or restart interval.
+ * The first sample in the row is undifferenced using the vertical
+ * predictor (2). The rest of the samples are undifferenced using the
+ * predictor specified in the scan header.
+ */
+
+METHODDEF(void)
+jpeg_undifference1(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_1D(INITIAL_PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_undifference2(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR2);
+}
+
+METHODDEF(void)
+jpeg_undifference3(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR3);
+}
+
+METHODDEF(void)
+jpeg_undifference4(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR4);
+}
+
+METHODDEF(void)
+jpeg_undifference5(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR5);
+}
+
+METHODDEF(void)
+jpeg_undifference6(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR6);
+}
+
+METHODDEF(void)
+jpeg_undifference7(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ UNDIFFERENCE_2D(PREDICTOR7);
+}
+
+
+/*
+ * Undifferencer for the first row in a scan or restart interval. The first
+ * sample in the row is undifferenced using the special predictor constant
+ * x=2^(P-Pt-1). The rest of the samples are undifferenced using the
+ * 1-D horizontal predictor (1).
+ */
+
+METHODDEF(void)
+jpeg_undifference_first_row(j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+ UNDIFFERENCE_1D(INITIAL_PREDICTORx);
+
+ /*
+ * Now that we have undifferenced the first row, we want to use the
+ * undifferencer which corresponds to the predictor specified in the
+ * scan header.
+ */
+ switch (cinfo->Ss) {
+ case 1:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference1;
+ break;
+ case 2:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference2;
+ break;
+ case 3:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference3;
+ break;
+ case 4:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference4;
+ break;
+ case 5:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference5;
+ break;
+ case 6:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference6;
+ break;
+ case 7:
+ losslsd->predict_undifference[comp_index] = jpeg_undifference7;
+ break;
+ }
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+predict_start_pass (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ int ci;
+
+ /* Check that the scan parameters Ss, Se, Ah, Al are OK for lossless JPEG.
+ *
+ * Ss is the predictor selection value (psv). Legal values for sequential
+ * lossless JPEG are: 1 <= psv <= 7.
+ *
+ * Se and Ah are not used and should be zero.
+ *
+ * Al specifies the point transform (Pt). Legal values are: 0 <= Pt <= 15.
+ */
+ if (cinfo->Ss < 1 || cinfo->Ss > 7 ||
+ cinfo->Se != 0 || cinfo->Ah != 0 ||
+ cinfo->Al > 15) /* need not check for < 0 */
+ ERREXIT4(cinfo, JERR_BAD_LOSSLESS,
+ cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+
+ /* Set undifference functions to first row function */
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ losslsd->predict_undifference[ci] = jpeg_undifference_first_row;
+}
+
+
+/*
+ * Module initialization routine for the undifferencer.
+ */
+
+GLOBAL(void)
+jinit_undifferencer (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+
+ losslsd->predict_start_pass = predict_start_pass;
+ losslsd->predict_process_restart = predict_start_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
+
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdsample.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdsample.cpp
new file mode 100644
index 00000000..3d45d4da
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdsample.cpp
@@ -0,0 +1,479 @@
+/*
+ * jdsample.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains upsampling routines.
+ *
+ * Upsampling input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * codec_data_unit / min_codec_data_unit)
+ * sample rows of each component. Upsampling will normally produce
+ * max_v_samp_factor pixel rows from each row group (but this could vary
+ * if the upsampler is applying a scale factor of its own).
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/* Pointer to routine to upsample a single component */
+typedef JMETHOD(void, upsample1_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Color conversion buffer. When using separate upsampling and color
+ * conversion steps, this buffer holds one upsampled row group until it
+ * has been color converted and output.
+ * Note: we do not allocate any storage for component(s) which are full-size,
+ * ie do not need rescaling. The corresponding entry of color_buf[] is
+ * simply set to point to the input data array, thereby avoiding copying.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ /* Per-component upsampling method pointers */
+ upsample1_ptr methods[MAX_COMPONENTS];
+
+ int next_row_out; /* counts rows emitted from color_buf */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+
+ /* Height of an input row group for each component. */
+ int rowgroup_height[MAX_COMPONENTS];
+
+ /* These arrays save pixel expansion factors so that int_expand need not
+ * recompute them each time. They are unused for other upsampling methods.
+ */
+ UINT8 h_expand[MAX_COMPONENTS];
+ UINT8 v_expand[MAX_COMPONENTS];
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the conversion buffer empty */
+ upsample->next_row_out = cinfo->max_v_samp_factor;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * In this version we upsample each component independently.
+ * We upsample one row group into the conversion buffer, then apply
+ * color conversion a row at a time.
+ */
+
+METHODDEF(void)
+sep_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JDIMENSION num_rows;
+
+ /* Fill the conversion buffer, if it's empty */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Invoke per-component upsample method. Notice we pass a POINTER
+ * to color_buf[ci], so that fullsize_upsample can change it.
+ */
+ (*upsample->methods[ci]) (cinfo, compptr,
+ input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
+ upsample->color_buf + ci);
+ }
+ upsample->next_row_out = 0;
+ }
+
+ /* Color-convert and emit rows */
+
+ /* How many we have in the buffer: */
+ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+ /* Not more than the distance to the end of the image. Need this test
+ * in case the image height is not a multiple of max_v_samp_factor:
+ */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+
+ (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
+ (JDIMENSION) upsample->next_row_out,
+ output_buf + *out_row_ctr,
+ (int) num_rows);
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ upsample->next_row_out += num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor)
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by sep_upsample to upsample pixel values
+ * of a single component. One row group is processed per call.
+ */
+
+
+/*
+ * For full-size components, we just make color_buf[ci] point at the
+ * input buffer, and thus avoid copying any data. Note that this is
+ * safe only because sep_upsample doesn't declare the input row group
+ * "consumed" until we are done color converting and emitting it.
+ */
+
+METHODDEF(void)
+fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = input_data;
+}
+
+
+/*
+ * This is a no-op version used for "uninteresting" components.
+ * These components will not be referenced by color conversion.
+ */
+
+METHODDEF(void)
+noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = NULL; /* safety check */
+}
+
+
+/*
+ * This version handles any integral sampling ratios.
+ * This is not used for typical JPEG files, so it need not be fast.
+ * Nor, for that matter, is it particularly accurate: the algorithm is
+ * simple replication of the input pixel onto the corresponding output
+ * pixels. The hi-falutin sampling literature refers to this as a
+ * "box filter". A box filter tends to introduce visible artifacts,
+ * so if you are actually going to use 3:1 or 4:1 sampling ratios
+ * you would be well advised to improve this code.
+ */
+
+METHODDEF(void)
+int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ register int h;
+ JSAMPROW outend;
+ int h_expand, v_expand;
+ int inrow, outrow;
+
+ h_expand = upsample->h_expand[compptr->component_index];
+ v_expand = upsample->v_expand[compptr->component_index];
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ /* Generate one output row with proper horizontal expansion */
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ for (h = h_expand; h > 0; h--) {
+ *outptr++ = invalue;
+ }
+ }
+ /* Generate any additional output rows by duplicating the first one */
+ if (v_expand > 1) {
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ v_expand-1, cinfo->output_width);
+ }
+ inrow++;
+ outrow += v_expand;
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int inrow;
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ inptr = input_data[inrow];
+ outptr = output_data[inrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int inrow, outrow;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ 1, cinfo->output_width);
+ inrow++;
+ outrow += 2;
+ }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 1:1 vertical.
+ *
+ * The upsampling algorithm is linear interpolation between pixel centers,
+ * also known as a "triangle filter". This is a good compromise between
+ * speed and visual quality. The centers of the output pixels are 1/4 and 3/4
+ * of the way between input pixel centers.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register int invalue;
+ register JDIMENSION colctr;
+ int inrow;
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ inptr = input_data[inrow];
+ outptr = output_data[inrow];
+ /* Special case for first column */
+ invalue = GETJSAMPLE(*inptr++);
+ *outptr++ = (JSAMPLE) invalue;
+ *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(*inptr) + 2) >> 2);
+
+ for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+ /* General case: 3/4 * nearer pixel + 1/4 * further pixel */
+ invalue = GETJSAMPLE(*inptr++) * 3;
+ *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(inptr[-2]) + 1) >> 2);
+ *outptr++ = (JSAMPLE) ((invalue + GETJSAMPLE(*inptr) + 2) >> 2);
+ }
+
+ /* Special case for last column */
+ invalue = GETJSAMPLE(*inptr);
+ *outptr++ = (JSAMPLE) ((invalue * 3 + GETJSAMPLE(inptr[-1]) + 1) >> 2);
+ *outptr++ = (JSAMPLE) invalue;
+ }
+}
+
+
+/*
+ * Fancy processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * Again a triangle filter; see comments for h2v1 case, above.
+ *
+ * It is OK for us to reference the adjacent input rows because we demanded
+ * context from the main buffer controller (see initialization code).
+ */
+
+METHODDEF(void)
+h2v2_fancy_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr0, inptr1, outptr;
+#if BITS_IN_JSAMPLE == 8
+ register int thiscolsum, lastcolsum, nextcolsum;
+#else
+ register INT32 thiscolsum, lastcolsum, nextcolsum;
+#endif
+ register JDIMENSION colctr;
+ int inrow, outrow, v;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ for (v = 0; v < 2; v++) {
+ /* inptr0 points to nearest input row, inptr1 points to next nearest */
+ inptr0 = input_data[inrow];
+ if (v == 0) /* next nearest is row above */
+ inptr1 = input_data[inrow-1];
+ else /* next nearest is row below */
+ inptr1 = input_data[inrow+1];
+ outptr = output_data[outrow++];
+
+ /* Special case for first column */
+ thiscolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+
+ for (colctr = compptr->downsampled_width - 2; colctr > 0; colctr--) {
+ /* General case: 3/4 * nearer pixel + 1/4 * further pixel in each */
+ /* dimension, thus 9/16, 3/16, 3/16, 1/16 overall */
+ nextcolsum = GETJSAMPLE(*inptr0++) * 3 + GETJSAMPLE(*inptr1++);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + nextcolsum + 7) >> 4);
+ lastcolsum = thiscolsum; thiscolsum = nextcolsum;
+ }
+
+ /* Special case for last column */
+ *outptr++ = (JSAMPLE) ((thiscolsum * 3 + lastcolsum + 8) >> 4);
+ *outptr++ = (JSAMPLE) ((thiscolsum * 4 + 7) >> 4);
+ }
+ inrow++;
+ }
+}
+
+
+/*
+ * Module initialization routine for upsampling.
+ */
+
+GLOBAL(void)
+jinit_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean need_buffer, do_fancy;
+ int h_in_group, v_in_group, h_out_group, v_out_group;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_upsample;
+ upsample->pub.upsample = sep_upsample;
+ upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+
+ if (cinfo->CCIR601_sampling) /* this isn't supported */
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* jdmainct.c doesn't support context rows when min_codec_data_unit = 1,
+ * so don't ask for it.
+ */
+ do_fancy = cinfo->do_fancy_upsampling && cinfo->min_codec_data_unit > 1;
+
+ /* Verify we can handle the sampling factors, select per-component methods,
+ * and create storage as needed.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Compute size of an "input group" after IDCT scaling. This many samples
+ * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
+ */
+ h_in_group = (compptr->h_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit;
+ v_in_group = (compptr->v_samp_factor * compptr->codec_data_unit) /
+ cinfo->min_codec_data_unit;
+ h_out_group = cinfo->max_h_samp_factor;
+ v_out_group = cinfo->max_v_samp_factor;
+ upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
+ need_buffer = TRUE;
+ if (! compptr->component_needed) {
+ /* Don't bother to upsample an uninteresting component. */
+ upsample->methods[ci] = noop_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
+ /* Fullsize components can be processed without any work. */
+ upsample->methods[ci] = fullsize_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group == v_out_group) {
+ /* Special cases for 2h1v upsampling */
+ if (do_fancy && compptr->downsampled_width > 2)
+ upsample->methods[ci] = h2v1_fancy_upsample;
+ else
+ upsample->methods[ci] = h2v1_upsample;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group * 2 == v_out_group) {
+ /* Special cases for 2h2v upsampling */
+ if (do_fancy && compptr->downsampled_width > 2) {
+ upsample->methods[ci] = h2v2_fancy_upsample;
+ upsample->pub.need_context_rows = TRUE;
+ } else
+ upsample->methods[ci] = h2v2_upsample;
+ } else if ((h_out_group % h_in_group) == 0 &&
+ (v_out_group % v_in_group) == 0) {
+ /* Generic integral-factors upsampling method */
+ upsample->methods[ci] = int_upsample;
+ upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
+ upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ if (need_buffer) {
+ upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) cinfo->output_width,
+ (long) cinfo->max_h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdscale.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdscale.cpp
new file mode 100644
index 00000000..d08b5bd8
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdscale.cpp
@@ -0,0 +1,119 @@
+/*
+ * jdscale.c
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains sample scaling for lossless JPEG. This is a
+ * combination of upscaling the undifferenced sample by 2^Pt and downscaling
+ * the sample to fit into JSAMPLE.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossls.h" /* Private declarations for lossless codec */
+
+
+#ifdef D_LOSSLESS_SUPPORTED
+
+/*
+ * Private scaler object for lossless decoding.
+ */
+
+typedef struct {
+ int scale_factor;
+} scaler;
+
+typedef scaler * scaler_ptr;
+
+
+/*
+ * Scalers for packing sample differences into JSAMPLEs.
+ */
+
+METHODDEF(void)
+simple_upscale(j_decompress_ptr cinfo,
+ JDIFFROW diff_buf, JSAMPROW output_buf,
+ JDIMENSION width)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+ int scale_factor = scaler->scale_factor;
+ int xindex;
+
+ for (xindex = 0; xindex < (int)width; xindex++)
+ output_buf[xindex] = (JSAMPLE) (diff_buf[xindex] << scale_factor);
+}
+
+METHODDEF(void)
+simple_downscale(j_decompress_ptr cinfo,
+ JDIFFROW diff_buf, JSAMPROW output_buf,
+ JDIMENSION width)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+ int scale_factor = scaler->scale_factor;
+ int xindex;
+
+ for (xindex = 0; xindex < (int)width; xindex++)
+ output_buf[xindex] = (JSAMPLE) RIGHT_SHIFT(diff_buf[xindex], scale_factor);
+}
+
+METHODDEF(void)
+noscale(j_decompress_ptr cinfo,
+ JDIFFROW diff_buf, JSAMPROW output_buf,
+ JDIMENSION width)
+{
+ int xindex;
+
+ for (xindex = 0; xindex < (int)width; xindex++)
+ output_buf[xindex] = (JSAMPLE) diff_buf[xindex];
+}
+
+
+METHODDEF(void)
+scaler_start_pass (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ scaler_ptr scaler = (scaler_ptr) losslsd->scaler_private;
+ int downscale;
+
+ /*
+ * Downscale by the difference in the input vs. output precision. If the
+ * output precision >= input precision, then do not downscale.
+ */
+ downscale = BITS_IN_JSAMPLE < cinfo->data_precision ?
+ cinfo->data_precision - BITS_IN_JSAMPLE : 0;
+
+ scaler->scale_factor = cinfo->Al - downscale;
+
+ /* Set scaler functions based on scale_factor (positive = left shift) */
+ if (scaler->scale_factor > 0)
+ losslsd->scaler_scale = simple_upscale;
+ else if (scaler->scale_factor < 0) {
+ scaler->scale_factor = -scaler->scale_factor;
+ losslsd->scaler_scale = simple_downscale;
+ }
+ else
+ losslsd->scaler_scale = noscale;
+}
+
+
+GLOBAL(void)
+jinit_d_scaler (j_decompress_ptr cinfo)
+{
+ j_lossless_d_ptr losslsd = (j_lossless_d_ptr) cinfo->codec;
+ scaler_ptr scaler;
+
+ scaler = (scaler_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(scaler));
+ losslsd->scaler_private = (void *) scaler;
+ losslsd->scaler_start_pass = scaler_start_pass;
+}
+
+#endif /* D_LOSSLESS_SUPPORTED */
+
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdshuff.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdshuff.cpp
new file mode 100644
index 00000000..a5e0696f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdshuff.cpp
@@ -0,0 +1,361 @@
+/*
+ * jdshuff.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines for sequential JPEG.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h" /* Private declarations for lossy codec */
+//#include "jdhuff.h" /* Declarations shared with jd*huff.c */
+
+
+/*
+ * Private entropy decoder object for Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ huffd_common_fields; /* Fields shared with other entropy decoders */
+
+ /* These fields are loaded into local variables at start of each MCU.
+ * In case of suspension, we exit WITHOUT updating them.
+ */
+ savable_state saved; /* Other state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+ /* Precalculated info set up by start_pass for use in decode_mcu: */
+
+ /* Pointers to derived tables to be used for each block within an MCU */
+ d_derived_tbl * dc_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+ d_derived_tbl * ac_cur_tbls[D_MAX_DATA_UNITS_IN_MCU];
+ /* Whether we care about the DC and AC coefficient values for each block */
+ boolean dc_needed[D_MAX_DATA_UNITS_IN_MCU];
+ boolean ac_needed[D_MAX_DATA_UNITS_IN_MCU];
+} shuff_entropy_decoder;
+
+typedef shuff_entropy_decoder * shuff_entropy_ptr;
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_huff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+ int ci, blkn, dctbl, actbl;
+ jpeg_component_info * compptr;
+
+ /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+ * This ought to be an error condition, but we make it a warning because
+ * there are some baseline files out there with all zeroes in these bytes.
+ */
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ cinfo->Ah != 0 || cinfo->Al != 0)
+ WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Precalculate decoding info for each block in an MCU of this scan */
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ /* Precalculate which table to use for each block */
+ entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
+ entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
+ /* Decide whether we really care about the coefficient values */
+ if (compptr->component_needed) {
+ entropy->dc_needed[blkn] = TRUE;
+ /* we don't need the ACs if producing a 1/8th-size image */
+ entropy->ac_needed[blkn] = (compptr->codec_data_unit > 1);
+ } else {
+ entropy->dc_needed[blkn] = entropy->ac_needed[blkn] = FALSE;
+ }
+ }
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->insufficient_data = FALSE;
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and add will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) + (((-1)<<(s)) + 1) : (x))
+
+#else
+
+#define HUFF_EXTEND(x,s) ((x) < extend_test[s] ? (x) + extend_offset[s] : (x))
+
+static const int extend_test[16] = /* entry n is 2**(n-1) */
+ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
+ 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 };
+
+static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */
+ { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1,
+ ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1,
+ ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1,
+ ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+ int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Decode and return one MCU's worth of Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA HAS BEEN ZEROED BY THE CALLER.
+ * (Wholesale zeroing is usually a little faster than retail...)
+ *
+ * Returns FALSE if data source requested suspension. In that case no
+ * changes have been made to permanent state. (Exception: some output
+ * coefficients may already have been assigned. This is harmless for
+ * this module, since we'll just re-assign them on the next call.)
+ */
+
+METHODDEF(boolean)
+decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy = (shuff_entropy_ptr) lossyd->entropy_private;
+ int blkn;
+ BITREAD_STATE_VARS;
+ savable_state state;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->data_units_in_MCU; blkn++) {
+ JBLOCKROW block = MCU_data[blkn];
+ d_derived_tbl * dctbl = entropy->dc_cur_tbls[blkn];
+ d_derived_tbl * actbl = entropy->ac_cur_tbls[blkn];
+ register int s, k, r;
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ HUFF_DECODE(s, br_state, dctbl, return FALSE, label1);
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+
+ if (entropy->dc_needed[blkn]) {
+ /* Convert DC difference to actual value, update last_dc_val */
+ int ci = cinfo->MCU_membership[blkn];
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Output the DC coefficient (assumes jpeg_natural_order[0] = 0) */
+ (*block)[0] = (JCOEF) s;
+ }
+
+ if (entropy->ac_needed[blkn]) {
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* Since zeroes are skipped, output area must be cleared beforehand */
+ for (k = 1; k < DCTSIZE2; k++) {
+ HUFF_DECODE(s, br_state, actbl, return FALSE, label2);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Output coefficient in natural (dezigzagged) order.
+ * Note: the extra entries in jpeg_natural_order[] will save us
+ * if k >= DCTSIZE2, which could happen if the data is corrupted.
+ */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ } else {
+ if (r != 15)
+ break;
+ k += 15;
+ }
+ }
+
+ } else {
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* In this path we just discard the values */
+ for (k = 1; k < DCTSIZE2; k++) {
+ HUFF_DECODE(s, br_state, actbl, return FALSE, label3);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ DROP_BITS(s);
+ } else {
+ if (r != 15)
+ break;
+ k += 15;
+ }
+ }
+
+ }
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_shuff_decoder (j_decompress_ptr cinfo)
+{
+ j_lossy_d_ptr lossyd = (j_lossy_d_ptr) cinfo->codec;
+ shuff_entropy_ptr entropy;
+ int i;
+
+ entropy = (shuff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(shuff_entropy_decoder));
+ lossyd->entropy_private = (void *) entropy;
+ lossyd->entropy_start_pass = start_pass_huff_decoder;
+ lossyd->entropy_decode_mcu = decode_mcu;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jdtrans.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdtrans.cpp
new file mode 100644
index 00000000..fc98e0cb
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jdtrans.cpp
@@ -0,0 +1,139 @@
+/*
+ * jdtrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding decompression,
+ * that is, reading raw DCT coefficient arrays from an input JPEG file.
+ * The routines in jdapimin.c will also be needed by a transcoder.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jlossy.h"
+
+
+/* Forward declarations */
+LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Read the coefficient arrays from a JPEG file.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * The entire image is read into a set of virtual coefficient-block arrays,
+ * one per component. The return value is a pointer to the array of
+ * virtual-array descriptors. These can be manipulated directly via the
+ * JPEG memory manager, or handed off to jpeg_write_coefficients().
+ * To release the memory occupied by the virtual arrays, call
+ * jpeg_finish_decompress() when done with the data.
+ *
+ * An alternative usage is to simply obtain access to the coefficient arrays
+ * during a buffered-image-mode decompression operation. This is allowed
+ * after any jpeg_finish_output() call. The arrays can be accessed until
+ * jpeg_finish_decompress() is called. (Note that any call to the library
+ * may reposition the arrays, so don't rely on access_virt_barray() results
+ * to stay valid across library calls.)
+ *
+ * Returns NULL if suspended. This case need be checked only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jpeg_read_coefficients (j_decompress_ptr cinfo)
+{
+ // j_lossy_d_ptr decomp;
+
+ /* Can't read coefficients from lossless streams */
+ if (cinfo->process == JPROC_LOSSLESS) {
+ ERREXIT(cinfo, JERR_CANT_TRANSCODE);
+ return NULL;
+ }
+
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize active modules */
+ transdecode_master_selection(cinfo);
+ cinfo->global_state = DSTATE_RDCOEFS;
+ }
+ if (cinfo->global_state == DSTATE_RDCOEFS) {
+ /* Absorb whole file into the coef buffer */
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return NULL;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* startup underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+ /* Set state so that jpeg_finish_decompress does the right thing */
+ cinfo->global_state = DSTATE_STOPPING;
+ }
+ /* At this point we should be in state DSTATE_STOPPING if being used
+ * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access
+ * to the coefficients during a full buffered-image-mode decompression.
+ */
+ if ((cinfo->global_state == DSTATE_STOPPING ||
+ cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
+ return ((j_lossy_d_ptr) cinfo->codec)->coef_arrays;
+ }
+ /* Oops, improper usage */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return NULL; /* keep compiler happy */
+}
+
+
+/*
+ * Master selection of decompression modules for transcoding.
+ * This substitutes for jdmaster.c's initialization of the full decompressor.
+ */
+
+LOCAL(void)
+transdecode_master_selection (j_decompress_ptr cinfo)
+{
+ /* This is effectively a buffered-image operation. */
+ cinfo->buffered_image = TRUE;
+
+ /* Initialize decompression codec */
+ jinit_d_codec(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+ /* Initialize progress monitoring. */
+ if (cinfo->progress != NULL) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->process == JPROC_PROGRESSIVE) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else if (cinfo->inputctl->has_multiple_scans) {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ } else {
+ nscans = 1;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = 1;
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.cpp
new file mode 100644
index 00000000..4efdce27
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.cpp
@@ -0,0 +1,249 @@
+/*
+ * jerror.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains simple error-reporting and trace-message routines.
+ * These are suitable for Unix-like systems and others where writing to
+ * stderr is the right thing to do. Many applications will want to replace
+ * some or all of these routines.
+ *
+ * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
+ * you get a Windows-specific hack to display error messages in a dialog box.
+ * It ain't much, but it beats dropping error messages into the bit bucket,
+ * which is what happens to output to stderr under most Windows C compilers.
+ *
+ * These routines are used by both the compression and decompression code.
+ */
+#include "stdafx.h"
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jversion.h"
+//#include "jerror.h"
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+
+
+/*
+ * Create the message string table.
+ * We do this from the master message list in jerror.h by re-reading
+ * jerror.h with a suitable definition for macro JMESSAGE.
+ * The message table is made an external symbol just in case any applications
+ * want to refer to it directly.
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_message_table jMsgTable
+#endif
+
+#define JMESSAGE(code,string) string ,
+
+const char * const jpeg_std_message_table[] = {
+#include "jerror.h"
+ NULL
+};
+
+
+/*
+ * Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error. Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object. Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ */
+
+METHODDEF(void)
+error_exit (j_common_ptr cinfo)
+{
+ /* Always display the message */
+ (*cinfo->err->output_message) (cinfo);
+
+ /* Let the memory manager delete any temp files before we die */
+ jpeg_destroy(cinfo);
+
+ exit(EXIT_FAILURE);
+}
+
+
+/*
+ * Actual output of an error or trace message.
+ * Applications may override this method to send JPEG messages somewhere
+ * other than stderr.
+ *
+ * On Windows, printing to stderr is generally completely useless,
+ * so we provide optional code to produce an error-dialog popup.
+ * Most Windows applications will still prefer to override this routine,
+ * but if they don't, it'll do something at least marginally useful.
+ *
+ * NOTE: to use the library in an environment that doesn't support the
+ * C stdio library, you may have to delete the call to fprintf() entirely,
+ * not just not use this routine.
+ */
+
+METHODDEF(void)
+output_message (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+ /* Display it in a message dialog box */
+ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
+ MB_OK | MB_ICONERROR);
+#else
+ /* Send it to stderr, adding a newline */
+ fprintf(stderr, "%s\n", buffer);
+#endif
+}
+
+
+/*
+ * Decide whether to emit a trace or warning message.
+ * msg_level is one of:
+ * -1: recoverable corrupt-data warning, may want to abort.
+ * 0: important advisory messages (always display to user).
+ * 1: first level of tracing detail.
+ * 2,3,...: successively more detailed tracing messages.
+ * An application might override this method if it wanted to abort on warnings
+ * or change the policy about which messages to display.
+ */
+
+METHODDEF(void)
+emit_message (j_common_ptr cinfo, int msg_level)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+
+ if (msg_level < 0) {
+ /* It's a warning message. Since corrupt files may generate many warnings,
+ * the policy implemented here is to show only the first warning,
+ * unless trace_level >= 3.
+ */
+ if (err->num_warnings == 0 || err->trace_level >= 3)
+ (*err->output_message) (cinfo);
+ /* Always count warnings in num_warnings. */
+ err->num_warnings++;
+ } else {
+ /* It's a trace message. Show it if trace_level >= msg_level. */
+ if (err->trace_level >= msg_level)
+ (*err->output_message) (cinfo);
+ }
+}
+
+
+/*
+ * Format a message string for the most recent JPEG error or message.
+ * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
+ * characters. Note that no '\n' character is added to the string.
+ * Few applications should need to override this method.
+ */
+
+METHODDEF(void)
+format_message (j_common_ptr cinfo, char * buffer)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+ int msg_code = err->msg_code;
+ const char * msgtext = NULL;
+ const char * msgptr;
+ char ch;
+ boolean isstring;
+
+ /* Look up message string in proper table */
+ if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
+ msgtext = err->jpeg_message_table[msg_code];
+ } else if (err->addon_message_table != NULL &&
+ msg_code >= err->first_addon_message &&
+ msg_code <= err->last_addon_message) {
+ msgtext = err->addon_message_table[msg_code - err->first_addon_message];
+ }
+
+ /* Defend against bogus message number */
+ if (msgtext == NULL) {
+ err->msg_parm.i[0] = msg_code;
+ msgtext = err->jpeg_message_table[0];
+ }
+
+ /* Check for string parameter, as indicated by %s in the message text */
+ isstring = FALSE;
+ msgptr = msgtext;
+ while ((ch = *msgptr++) != '\0') {
+ if (ch == '%') {
+ if (*msgptr == 's') isstring = TRUE;
+ break;
+ }
+ }
+
+ /* Format the message into the passed buffer */
+ if (isstring)
+ sprintf(buffer, msgtext, err->msg_parm.s);
+ else
+ sprintf(buffer, msgtext,
+ err->msg_parm.i[0], err->msg_parm.i[1],
+ err->msg_parm.i[2], err->msg_parm.i[3],
+ err->msg_parm.i[4], err->msg_parm.i[5],
+ err->msg_parm.i[6], err->msg_parm.i[7]);
+}
+
+
+/*
+ * Reset error state variables at start of a new image.
+ * This is called during compression startup to reset trace/error
+ * processing to default state, without losing any application-specific
+ * method pointers. An application might possibly want to override
+ * this method if it has additional error processing state.
+ */
+
+METHODDEF(void)
+reset_error_mgr (j_common_ptr cinfo)
+{
+ cinfo->err->num_warnings = 0;
+ /* trace_level is not reset since it is an application-supplied parameter */
+ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
+}
+
+
+/*
+ * Fill in the standard error-handling methods in a jpeg_error_mgr object.
+ * Typical call is:
+ * struct jpeg_compress_struct cinfo;
+ * struct jpeg_error_mgr err;
+ *
+ * cinfo.err = jpeg_std_error(&err);
+ * after which the application may override some of the methods.
+ */
+
+GLOBAL(struct jpeg_error_mgr *)
+jpeg_std_error (struct jpeg_error_mgr * err)
+{
+ err->error_exit = error_exit;
+ err->emit_message = emit_message;
+ err->output_message = output_message;
+ err->format_message = format_message;
+ err->reset_error_mgr = reset_error_mgr;
+
+ err->trace_level = 0; /* default = no tracing */
+ err->num_warnings = 0; /* no warnings emitted yet */
+ err->msg_code = 0; /* may be useful as a flag for "no error" */
+
+ /* Initialize message table pointers */
+ err->jpeg_message_table = jpeg_std_message_table;
+ err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+
+ err->addon_message_table = NULL;
+ err->first_addon_message = 0; /* for safety */
+ err->last_addon_message = 0;
+
+ return err;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.h
new file mode 100644
index 00000000..b38a0591
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jerror.h
@@ -0,0 +1,304 @@
+/*
+ * jerror.h
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the JPEG library.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ * A set of error-reporting macros are defined too. Some applications using
+ * the JPEG library may wish to include this file to get the error codes
+ * and/or the macros.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef JERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* JERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
+
+/* For maintenance convenience, list is alphabetical by message code name */
+JMESSAGE(JERR_ARITH_NOTIMPL,
+ "Sorry, there are legal restrictions on arithmetic coding")
+JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
+JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
+JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
+JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
+JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
+JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
+JMESSAGE(JERR_BAD_DIFF, "spatial difference out of range")
+JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
+JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
+JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
+JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
+JMESSAGE(JERR_BAD_LIB_VERSION,
+ "Wrong JPEG library version: library is %d, caller expects %d")
+JMESSAGE(JERR_BAD_LOSSLESS,
+ "Invalid lossless parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_LOSSLESS_SCRIPT,
+ "Invalid lossless parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
+JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
+JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
+JMESSAGE(JERR_BAD_PROGRESSION,
+ "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_PROG_SCRIPT,
+ "Invalid progressive parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_RESTART, "Invalid restart interval: %d, must be an integer multiple of the number of MCUs in an MCU_row (%d)")
+JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
+JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
+JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
+JMESSAGE(JERR_BAD_STRUCT_SIZE,
+ "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
+JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
+JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
+JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
+JMESSAGE(JERR_CANT_TRANSCODE,
+ "Cannot transcode to/from lossless JPEG datastreams")
+JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
+JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
+JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
+JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
+JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
+JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
+JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
+JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
+JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
+JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
+JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
+JMESSAGE(JERR_FILE_READ, "Input file read error")
+JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
+JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
+JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
+JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
+JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
+JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
+JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
+JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
+ "Cannot transcode due to multiple use of quantization table %d")
+JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
+JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
+JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
+JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
+JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
+JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
+JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
+JMESSAGE(JERR_NO_LOSSLESS_SCRIPT, "Lossless encoding was requested but no scan script was supplied")
+JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
+JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
+JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
+JMESSAGE(JERR_QUANT_COMPONENTS,
+ "Cannot quantize more than %d color components")
+JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
+JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
+JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
+JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
+JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
+JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
+JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
+JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
+JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
+JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
+JMESSAGE(JERR_TFILE_WRITE,
+ "Write failed on temporary file --- out of disk space?")
+JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
+JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
+JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
+JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
+JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
+JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
+JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
+JMESSAGE(JMSG_VERSION, JVERSION)
+JMESSAGE(JTRC_16BIT_TABLES,
+ "Caution: quantization tables are too coarse for baseline JPEG")
+JMESSAGE(JTRC_ADOBE,
+ "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
+JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
+JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
+JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
+JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
+JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
+JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
+JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
+JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
+JMESSAGE(JTRC_EOI, "End Of Image")
+JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
+JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
+JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
+ "Warning: thumbnail image size does not match data length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION,
+ "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
+JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
+JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
+JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
+JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
+JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
+JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
+JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
+JMESSAGE(JTRC_RST, "RST%d")
+JMESSAGE(JTRC_SMOOTH_NOTIMPL,
+ "Smoothing not supported with nonstandard sampling ratios")
+JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
+JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
+JMESSAGE(JTRC_SOI, "Start of Image")
+JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
+JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
+JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
+JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
+JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
+JMESSAGE(JTRC_THUMB_JPEG,
+ "JFIF extension marker: JPEG-compressed thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_PALETTE,
+ "JFIF extension marker: palette thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_RGB,
+ "JFIF extension marker: RGB thumbnail image, length %u")
+JMESSAGE(JTRC_UNKNOWN_LOSSLESS_IDS,
+ "Unrecognized component IDs %d %d %d, assuming RGB")
+JMESSAGE(JTRC_UNKNOWN_LOSSY_IDS,
+ "Unrecognized component IDs %d %d %d, assuming YCbCr")
+JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
+JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
+JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
+JMESSAGE(JWRN_BOGUS_PROGRESSION,
+ "Inconsistent progression sequence for component %d coefficient %d")
+JMESSAGE(JWRN_EXTRANEOUS_DATA,
+ "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
+JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
+JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
+JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
+JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
+JMESSAGE(JWRN_MUST_DOWNSCALE,
+ "Must downscale data from %d bits to %d")
+JMESSAGE(JWRN_MUST_RESYNC,
+ "Corrupt JPEG data: found marker 0x%02x instead of RST%d")
+JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
+JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTMSGCODE
+} J_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
+
+
+#ifndef JERROR_H
+#define JERROR_H
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is either type of cinfo pointer */
+
+/* Fatal errors (print message and exit) */
+#define ERREXIT(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT3(cinfo,code,p1,p2,p3) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (cinfo)->err->msg_parm.i[3] = (p4), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXITS(cinfo,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+#define MAKESTMT(stuff) do { stuff } while (0)
+
+/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
+#define WARNMS(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+
+/* Informational/debugging messages */
+#define TRACEMS(cinfo,lvl,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS1(cinfo,lvl,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS2(cinfo,lvl,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMSS(cinfo,lvl,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+
+#endif /* JERROR_H */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctflt.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctflt.cpp
new file mode 100644
index 00000000..ca3c4cae
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctflt.cpp
@@ -0,0 +1,169 @@
+/*
+ * jfdctflt.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * This implementation should be more accurate than either of the integer
+ * DCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_float (FAST_FLOAT * data)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
+ FAST_FLOAT *dataptr;
+ int ctr;
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctfst.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctfst.cpp
new file mode 100644
index 00000000..f301004d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctfst.cpp
@@ -0,0 +1,225 @@
+/*
+ * jfdctfst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jfdctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * Again to save a few shifts, the intermediate results between pass 1 and
+ * pass 2 are not upscaled, but are represented only to integral precision.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#define CONST_BITS 8
+
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
+#else
+#define FIX_0_382683433 FIX(0.382683433)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_707106781 FIX(0.707106781)
+#define FIX_1_306562965 FIX(1.306562965)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_ifast (DCTELEM * data)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctint.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctint.cpp
new file mode 100644
index 00000000..5e102038
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jfdctint.cpp
@@ -0,0 +1,284 @@
+/*
+ * jfdctint.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D DCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true DCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D DCT,
+ * because the y0 and y4 outputs need not be divided by sqrt(N).
+ * In the IJG code, this factor of 8 is removed by the quantization step
+ * (in jcdctmgr.c), NOT in this module.
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (For 12-bit sample data, the intermediate
+ * array is INT32 anyway.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_islow (DCTELEM * data)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ DCTELEM *dataptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[0] + dataptr[7];
+ tmp7 = dataptr[0] - dataptr[7];
+ tmp1 = dataptr[1] + dataptr[6];
+ tmp6 = dataptr[1] - dataptr[6];
+ tmp2 = dataptr[2] + dataptr[5];
+ tmp5 = dataptr[2] - dataptr[5];
+ tmp3 = dataptr[3] + dataptr[4];
+ tmp4 = dataptr[3] - dataptr[4];
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[0] = (DCTELEM) ((tmp10 + tmp11) << PASS1_BITS);
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+
+ z1 = tmp4 + tmp7;
+ z2 = tmp5 + tmp6;
+ z3 = tmp4 + tmp6;
+ z4 = tmp5 + tmp7;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ dataptr[7] = (DCTELEM) DESCALE(tmp4 + z1 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp5 + z2 + z4, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp6 + z2 + z3, CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM) DESCALE(tmp7 + z1 + z4, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp13, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, - FIX_1_847759065),
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents cos(K*pi/16).
+ * i0..i3 in the paper are tmp4..tmp7 here.
+ */
+
+ z1 = tmp4 + tmp7;
+ z2 = tmp5 + tmp6;
+ z3 = tmp4 + tmp6;
+ z4 = tmp5 + tmp7;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp4 = MULTIPLY(tmp4, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp5 = MULTIPLY(tmp5, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp6 = MULTIPLY(tmp6, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp7 = MULTIPLY(tmp7, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp4 + z1 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp5 + z2 + z4,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp6 + z2 + z3,
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp7 + z1 + z4,
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctflt.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctflt.cpp
new file mode 100644
index 00000000..e47714dd
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctflt.cpp
@@ -0,0 +1,243 @@
+/*
+ * jidctflt.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * This implementation should be more accurate than either of the integer
+ * IDCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a float result.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ FLOAT_MULT_TYPE * quantptr;
+ FAST_FLOAT * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = tmp0 + tmp7;
+ wsptr[DCTSIZE*7] = tmp0 - tmp7;
+ wsptr[DCTSIZE*1] = tmp1 + tmp6;
+ wsptr[DCTSIZE*6] = tmp1 - tmp6;
+ wsptr[DCTSIZE*2] = tmp2 + tmp5;
+ wsptr[DCTSIZE*5] = tmp2 - tmp5;
+ wsptr[DCTSIZE*4] = tmp3 + tmp4;
+ wsptr[DCTSIZE*3] = tmp3 - tmp4;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * And testing floats for zero is relatively expensive, so we don't bother.
+ */
+
+ /* Even part */
+
+ tmp10 = wsptr[0] + wsptr[4];
+ tmp11 = wsptr[0] - wsptr[4];
+
+ tmp13 = wsptr[2] + wsptr[6];
+ tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = wsptr[5] + wsptr[3];
+ z10 = wsptr[5] - wsptr[3];
+ z11 = wsptr[1] + wsptr[7];
+ z12 = wsptr[1] - wsptr[7];
+
+ tmp7 = z11 + z13;
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7;
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctfst.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctfst.cpp
new file mode 100644
index 00000000..10f7036f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctfst.cpp
@@ -0,0 +1,369 @@
+/*
+ * jidctfst.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jidctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * The dequantized coefficients are not integers because the AA&N scaling
+ * factors have been incorporated. We represent them scaled up by PASS1_BITS,
+ * so that the first and second IDCT rounds have the same input scaling.
+ * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
+ * avoid a descaling shift; this compromises accuracy rather drastically
+ * for small quantization table entries, but it saves a lot of shifts.
+ * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
+ * so we use a much larger scaling factor to preserve accuracy.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 8
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 8
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */
+#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */
+#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */
+#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */
+#else
+#define FIX_1_082392200 FIX(1.082392200)
+#define FIX_1_414213562 FIX(1.414213562)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_2_613125930 FIX(2.613125930)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a DCTELEM result. For 8-bit data a 16x16->16
+ * multiplication will do. For 12-bit data, the multiplier table is
+ * declared INT32, so a 32-bit multiply will be used.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#else
+#define DEQUANTIZE(coef,quantval) \
+ DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#endif
+
+
+/* Like DESCALE, but applies to a DCTELEM and produces an int.
+ * We assume that int right shift is unsigned if INT32 right shift is.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS DCTELEM ishift_temp;
+#if BITS_IN_JSAMPLE == 8
+#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */
+#else
+#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
+#endif
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+#ifdef USE_ACCURATE_ROUNDING
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#else
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
+#endif
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ IFAST_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS /* for DESCALE */
+ ISHIFT_TEMPS /* for IDESCALE */
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
+ wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
+ wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
+ wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
+ wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
+ wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
+ wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
+ wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
+ tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+
+ tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
+ tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
+ - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
+ z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
+ z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
+ z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctint.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctint.cpp
new file mode 100644
index 00000000..7bc29071
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctint.cpp
@@ -0,0 +1,390 @@
+/*
+ * jidctint.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate INT32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result. In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3, z4, z5;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+
+ tmp0 = (z2 + z3) << CONST_BITS;
+ tmp1 = (z2 - z3) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*7] = (int) DESCALE(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*6] = (int) DESCALE(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*5] = (int) DESCALE(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*3] = (int) DESCALE(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*4] = (int) DESCALE(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
+ tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
+
+ tmp0 = ((INT32) wsptr[0] + (INT32) wsptr[4]) << CONST_BITS;
+ tmp1 = ((INT32) wsptr[0] - (INT32) wsptr[4]) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp3;
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) wsptr[7];
+ tmp1 = (INT32) wsptr[5];
+ tmp2 = (INT32) wsptr[3];
+ tmp3 = (INT32) wsptr[1];
+
+ z1 = tmp0 + tmp3;
+ z2 = tmp1 + tmp2;
+ z3 = tmp0 + tmp2;
+ z4 = tmp1 + tmp3;
+ z5 = MULTIPLY(z3 + z4, FIX_1_175875602); /* sqrt(2) * c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ z1 = MULTIPLY(z1, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ z2 = MULTIPLY(z2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ z3 = MULTIPLY(z3, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z4 = MULTIPLY(z4, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+
+ z3 += z5;
+ z4 += z5;
+
+ tmp0 += z1 + z3;
+ tmp1 += z2 + z4;
+ tmp2 += z2 + z3;
+ tmp3 += z1 + z4;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) DESCALE(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) DESCALE(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) DESCALE(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) DESCALE(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctred.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctred.cpp
new file mode 100644
index 00000000..4deccdca
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jidctred.cpp
@@ -0,0 +1,399 @@
+/*
+ * jidctred.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains inverse-DCT routines that produce reduced-size output:
+ * either 4x4, 2x2, or 1x1 pixels from an 8x8 DCT block.
+ *
+ * The implementation is based on the Loeffler, Ligtenberg and Moschytz (LL&M)
+ * algorithm used in jidctint.c. We simply replace each 8-to-8 1-D IDCT step
+ * with an 8-to-4 step that produces the four averages of two adjacent outputs
+ * (or an 8-to-2 step producing two averages of four outputs, for 2x2 output).
+ * These steps were derived by computing the corresponding values at the end
+ * of the normal LL&M code, then simplifying as much as possible.
+ *
+ * 1x1 is trivial: just take the DC coefficient divided by 8.
+ *
+ * See jidctint.c for additional comments.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling is the same as in jidctint.c. */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_211164243 ((INT32) 1730) /* FIX(0.211164243) */
+#define FIX_0_509795579 ((INT32) 4176) /* FIX(0.509795579) */
+#define FIX_0_601344887 ((INT32) 4926) /* FIX(0.601344887) */
+#define FIX_0_720959822 ((INT32) 5906) /* FIX(0.720959822) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_850430095 ((INT32) 6967) /* FIX(0.850430095) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_061594337 ((INT32) 8697) /* FIX(1.061594337) */
+#define FIX_1_272758580 ((INT32) 10426) /* FIX(1.272758580) */
+#define FIX_1_451774981 ((INT32) 11893) /* FIX(1.451774981) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_2_172734803 ((INT32) 17799) /* FIX(2.172734803) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_624509785 ((INT32) 29692) /* FIX(3.624509785) */
+#else
+#define FIX_0_211164243 FIX(0.211164243)
+#define FIX_0_509795579 FIX(0.509795579)
+#define FIX_0_601344887 FIX(0.601344887)
+#define FIX_0_720959822 FIX(0.720959822)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_850430095 FIX(0.850430095)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_061594337 FIX(1.061594337)
+#define FIX_1_272758580 FIX(1.272758580)
+#define FIX_1_451774981 FIX(1.451774981)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_2_172734803 FIX(2.172734803)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_624509785 FIX(3.624509785)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result. In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 4x4 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE*4]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+ /* Don't bother to process column 4, because second pass won't use it */
+ if (ctr == DCTSIZE-4)
+ continue;
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*5] == 0 &&
+ inptr[DCTSIZE*6] == 0 && inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero; we need not examine term 4 for 4x4 output */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= (CONST_BITS+1);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp2 = MULTIPLY(z2, FIX_1_847759065) + MULTIPLY(z3, - FIX_0_765366865);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+
+ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+ /* Final output stage */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp2, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*3] = (int) DESCALE(tmp10 - tmp2, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp12 + tmp0, CONST_BITS-PASS1_BITS+1);
+ wsptr[DCTSIZE*2] = (int) DESCALE(tmp12 - tmp0, CONST_BITS-PASS1_BITS+1);
+ }
+
+ /* Pass 2: process 4 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp0 = ((INT32) wsptr[0]) << (CONST_BITS+1);
+
+ tmp2 = MULTIPLY((INT32) wsptr[2], FIX_1_847759065)
+ + MULTIPLY((INT32) wsptr[6], - FIX_0_765366865);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[7];
+ z2 = (INT32) wsptr[5];
+ z3 = (INT32) wsptr[3];
+ z4 = (INT32) wsptr[1];
+
+ tmp0 = MULTIPLY(z1, - FIX_0_211164243) /* sqrt(2) * (c3-c1) */
+ + MULTIPLY(z2, FIX_1_451774981) /* sqrt(2) * (c3+c7) */
+ + MULTIPLY(z3, - FIX_2_172734803) /* sqrt(2) * (-c1-c5) */
+ + MULTIPLY(z4, FIX_1_061594337); /* sqrt(2) * (c5+c7) */
+
+ tmp2 = MULTIPLY(z1, - FIX_0_509795579) /* sqrt(2) * (c7-c5) */
+ + MULTIPLY(z2, - FIX_0_601344887) /* sqrt(2) * (c5-c1) */
+ + MULTIPLY(z3, FIX_0_899976223) /* sqrt(2) * (c3-c7) */
+ + MULTIPLY(z4, FIX_2_562915447); /* sqrt(2) * (c1+c3) */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp2,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE(tmp10 - tmp2,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp12 + tmp0,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE(tmp12 - tmp0,
+ CONST_BITS+PASS1_BITS+3+1)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 2x2 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp10, z1;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE*2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; inptr++, quantptr++, wsptr++, ctr--) {
+ /* Don't bother to process columns 2,4,6 */
+ if (ctr == DCTSIZE-2 || ctr == DCTSIZE-4 || ctr == DCTSIZE-6)
+ continue;
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*3] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero; we need not examine terms 2,4,6 for 2x2 output */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+
+ continue;
+ }
+
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 = z1 << (CONST_BITS+2);
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp0 = MULTIPLY(z1, - FIX_0_720959822); /* sqrt(2) * (c7-c5+c3-c1) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp0 += MULTIPLY(z1, FIX_0_850430095); /* sqrt(2) * (-c1+c3+c5+c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp0 += MULTIPLY(z1, - FIX_1_272758580); /* sqrt(2) * (-c1+c3-c5-c7) */
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 += MULTIPLY(z1, FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+ /* Final output stage */
+
+ wsptr[DCTSIZE*0] = (int) DESCALE(tmp10 + tmp0, CONST_BITS-PASS1_BITS+2);
+ wsptr[DCTSIZE*1] = (int) DESCALE(tmp10 - tmp0, CONST_BITS-PASS1_BITS+2);
+ }
+
+ /* Pass 2: process 2 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 2; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* It's not clear whether a zero row test is worthwhile here ... */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[3] == 0 && wsptr[5] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp10 = ((INT32) wsptr[0]) << (CONST_BITS+2);
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY((INT32) wsptr[7], - FIX_0_720959822) /* sqrt(2) * (c7-c5+c3-c1) */
+ + MULTIPLY((INT32) wsptr[5], FIX_0_850430095) /* sqrt(2) * (-c1+c3+c5+c7) */
+ + MULTIPLY((INT32) wsptr[3], - FIX_1_272758580) /* sqrt(2) * (-c1+c3-c5-c7) */
+ + MULTIPLY((INT32) wsptr[1], FIX_3_624509785); /* sqrt(2) * (c1+c3+c5+c7) */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) DESCALE(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3+2)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3+2)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 1x1 output block.
+ */
+
+GLOBAL(void)
+jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ int dcval;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* We hardly need an inverse DCT routine for this: just take the
+ * average pixel value, which is one-eighth of the DC coefficient.
+ */
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
+ dcval = (int) DESCALE((INT32) dcval, 3);
+
+ output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
+}
+
+#endif /* IDCT_SCALING_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jinclude.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jinclude.h
new file mode 100644
index 00000000..0a4f1514
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jinclude.h
@@ -0,0 +1,91 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file exists to provide a single place to fix any problems with
+ * including the wrong system include files. (Common problems are taken
+ * care of by the standard jconfig symbols, but on really weird systems
+ * you may have to edit this file.)
+ *
+ * NOTE: this file is NOT intended to be included by applications using the
+ * JPEG library. Most applications need only include jpeglib.h.
+ */
+
+
+/* Include auto-config file to find out which system include files we need. */
+
+#include "jconfig.h" /* auto configuration options */
+#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
+
+/*
+ * We need the NULL macro and size_t typedef.
+ * On an ANSI-conforming system it is sufficient to include <stddef.h>.
+ * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
+ * pull in <sys/types.h> as well.
+ * Note that the core JPEG library does not require <stdio.h>;
+ * only the default error handler and data source/destination modules do.
+ * But we must pull it in because of the references to FILE in jpeglib.h.
+ * You can remove those references if you want to compile without <stdio.h>.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+
+/*
+ * We need memory copying and zeroing functions, plus strncpy().
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * Some systems may declare memset and memcpy in <memory.h>.
+ *
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Change the casts in these macros if not!
+ */
+
+#ifdef NEED_BSD_STRINGS
+
+#include <strings.h>
+#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+
+#else /* not BSD, assume ANSI/SysV string lib */
+
+#include <string.h>
+#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof(). However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long. To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object) ((size_t) sizeof(object))
+
+/*
+ * The modules that use fread() and fwrite() always invoke them through
+ * these macros. On some systems you may need to twiddle the argument casts.
+ * CAUTION: argument order is different from underlying functions!
+ */
+
+#define JFREAD(file,buf,sizeofbuf) \
+ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf) \
+ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossls.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossls.h
new file mode 100644
index 00000000..ec13bd03
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossls.h
@@ -0,0 +1,152 @@
+/*
+ * jlossls.h
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the lossless JPEG
+ * codec modules.
+ */
+
+#ifndef JLOSSLS_H
+#define JLOSSLS_H
+
+
+/*
+ * Table H.1: Predictors for lossless coding.
+ */
+
+#define PREDICTOR1 Ra
+#define PREDICTOR2 Rb
+#define PREDICTOR3 Rc
+#define PREDICTOR4 (int) ((INT32) Ra + (INT32) Rb - (INT32) Rc)
+#define PREDICTOR5 (int) ((INT32) Ra + RIGHT_SHIFT((INT32) Rb - (INT32) Rc, 1))
+#define PREDICTOR6 (int) ((INT32) Rb + RIGHT_SHIFT((INT32) Ra - (INT32) Rc, 1))
+#define PREDICTOR7 (int) RIGHT_SHIFT((INT32) Ra + (INT32) Rb, 1)
+
+
+typedef JMETHOD(void, predict_difference_method_ptr,
+ (j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW prev_row,
+ JDIFFROW diff_buf, JDIMENSION width));
+
+typedef JMETHOD(void, scaler_method_ptr,
+ (j_compress_ptr cinfo, int ci,
+ JSAMPROW input_buf, JSAMPROW output_buf,
+ JDIMENSION width));
+
+/* Lossless-specific compression codec (compressor proper) */
+typedef struct {
+ struct jpeg_c_codec pub; /* public fields */
+
+
+ /* Difference buffer control */
+ JMETHOD(void, diff_start_pass, (j_compress_ptr cinfo,
+ J_BUF_MODE pass_mode));
+
+ /* Pointer to data which is private to diff controller */
+ void *diff_private;
+
+
+ /* Entropy encoding */
+ JMETHOD(JDIMENSION, entropy_encode_mcus, (j_compress_ptr cinfo,
+ JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num,
+ JDIMENSION MCU_col_num,
+ JDIMENSION nMCU));
+
+ /* Pointer to data which is private to entropy module */
+ void *entropy_private;
+
+
+ /* Prediction, differencing */
+ JMETHOD(void, predict_start_pass, (j_compress_ptr cinfo));
+
+ /* It is useful to allow each component to have a separate diff method. */
+ predict_difference_method_ptr predict_difference[MAX_COMPONENTS];
+
+ /* Pointer to data which is private to predictor module */
+ void *pred_private;
+
+ /* Sample scaling */
+ JMETHOD(void, scaler_start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, scaler_scale, (j_compress_ptr cinfo,
+ JSAMPROW input_buf, JSAMPROW output_buf,
+ JDIMENSION width));
+
+ /* Pointer to data which is private to scaler module */
+ void *scaler_private;
+
+} jpeg_lossless_c_codec;
+
+typedef jpeg_lossless_c_codec * j_lossless_c_ptr;
+
+
+typedef JMETHOD(void, predict_undifference_method_ptr,
+ (j_decompress_ptr cinfo, int comp_index,
+ JDIFFROW diff_buf, JDIFFROW prev_row,
+ JDIFFROW undiff_buf, JDIMENSION width));
+
+/* Lossless-specific decompression codec (decompressor proper) */
+typedef struct {
+ struct jpeg_d_codec pub; /* public fields */
+
+
+ /* Difference buffer control */
+ JMETHOD(void, diff_start_input_pass, (j_decompress_ptr cinfo));
+
+ /* Pointer to data which is private to diff controller */
+ void *diff_private;
+
+
+ /* Entropy decoding */
+ JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, entropy_process_restart, (j_decompress_ptr cinfo));
+ JMETHOD(JDIMENSION, entropy_decode_mcus, (j_decompress_ptr cinfo,
+ JDIFFIMAGE diff_buf,
+ JDIMENSION MCU_row_num,
+ JDIMENSION MCU_col_num,
+ JDIMENSION nMCU));
+
+ /* Pointer to data which is private to entropy module */
+ void *entropy_private;
+
+
+ /* Prediction, undifferencing */
+ JMETHOD(void, predict_start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, predict_process_restart, (j_decompress_ptr cinfo));
+
+ /* It is useful to allow each component to have a separate undiff method. */
+ predict_undifference_method_ptr predict_undifference[MAX_COMPONENTS];
+
+ /* Pointer to data which is private to predictor module */
+ void *pred_private;
+
+ /* Sample scaling */
+ JMETHOD(void, scaler_start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, scaler_scale, (j_decompress_ptr cinfo,
+ JDIFFROW diff_buf, JSAMPROW output_buf,
+ JDIMENSION width));
+
+ /* Pointer to data which is private to scaler module */
+ void *scaler_private;
+
+} jpeg_lossless_d_codec;
+
+typedef jpeg_lossless_d_codec * j_lossless_d_ptr;
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_lhuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_differencer JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_scaler JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_lhuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_undifferencer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_scaler JPP((j_decompress_ptr cinfo));
+
+GLOBAL(void) jinit_lossless_c_codec(j_compress_ptr cinfo);
+GLOBAL(void) jinit_lossless_d_codec(j_decompress_ptr cinfo);
+
+#endif /* JLOSSLS_H */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossy.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossy.h
new file mode 100644
index 00000000..ad4d62b3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jlossy.h
@@ -0,0 +1,120 @@
+/*
+ * jlossy.h
+ *
+ * Copyright (C) 1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the lossy (DCT-based)
+ * JPEG codec modules.
+ */
+
+#ifndef JLOSSY_H
+#define JLOSSY_H
+
+
+/* Lossy-specific compression codec (compressor proper) */
+typedef struct {
+ struct jpeg_c_codec pub; /* public fields */
+
+
+ /* Coefficient buffer control */
+ JMETHOD(void, coef_start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ /* JMETHOD(boolean, coef_compress_data, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf));*/
+
+ /* Pointer to data which is private to coef module */
+ void *coef_private;
+
+
+ /* Forward DCT (also controls coefficient quantization) */
+ JMETHOD(void, fdct_start_pass, (j_compress_ptr cinfo));
+ /* perhaps this should be an array??? */
+ JMETHOD(void, fdct_forward_DCT, (j_compress_ptr cinfo,
+ jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks));
+
+ /* Pointer to data which is private to fdct module */
+ void *fdct_private;
+
+
+ /* Entropy encoding */
+ JMETHOD(boolean, entropy_encode_mcu, (j_compress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+ /* Pointer to data which is private to entropy module */
+ void *entropy_private;
+
+} jpeg_lossy_c_codec;
+
+typedef jpeg_lossy_c_codec * j_lossy_c_ptr;
+
+
+
+typedef JMETHOD(void, inverse_DCT_method_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col));
+
+/* Lossy-specific decompression codec (decompressor proper) */
+typedef struct {
+ struct jpeg_d_codec pub; /* public fields */
+
+
+ /* Coefficient buffer control */
+ JMETHOD(void, coef_start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, coef_start_output_pass, (j_decompress_ptr cinfo));
+
+ /* Pointer to array of coefficient virtual arrays, or NULL if none */
+ jvirt_barray_ptr *coef_arrays;
+
+ /* Pointer to data which is private to coef module */
+ void *coef_private;
+
+
+ /* Entropy decoding */
+ JMETHOD(void, entropy_start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, entropy_decode_mcu, (j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+ /* This is here to share code between baseline and progressive decoders; */
+ /* other modules probably should not use it */
+ boolean entropy_insufficient_data; /* set TRUE after emitting warning */
+
+ /* Pointer to data which is private to entropy module */
+ void *entropy_private;
+
+
+ /* Inverse DCT (also performs dequantization) */
+ JMETHOD(void, idct_start_pass, (j_decompress_ptr cinfo));
+
+ /* It is useful to allow each component to have a separate IDCT method. */
+ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+
+ /* Pointer to data which is private to idct module */
+ void *idct_private;
+
+} jpeg_lossy_d_codec;
+
+typedef jpeg_lossy_d_codec * j_lossy_d_ptr;
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_lossy_c_codec JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_shuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
+
+/* Decompression module initialization routines */
+EXTERN(void) jinit_lossy_d_codec JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_shuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
+
+#endif /* JLOSSY_H */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemdosa.asm b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemdosa.asm
new file mode 100644
index 00000000..ecd43729
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemdosa.asm
@@ -0,0 +1,379 @@
+;
+; jmemdosa.asm
+;
+; Copyright (C) 1992, Thomas G. Lane.
+; This file is part of the Independent JPEG Group's software.
+; For conditions of distribution and use, see the accompanying README file.
+;
+; This file contains low-level interface routines to support the MS-DOS
+; backing store manager (jmemdos.c). Routines are provided to access disk
+; files through direct DOS calls, and to access XMS and EMS drivers.
+;
+; This file should assemble with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler). If you haven't got
+; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
+;
+; To minimize dependence on the C compiler's register usage conventions,
+; we save and restore all 8086 registers, even though most compilers only
+; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return
+; values, which everybody returns in AX.
+;
+; Based on code contributed by Ge' Weijers.
+;
+
+JMEMDOSA_TXT segment byte public 'CODE'
+
+ assume cs:JMEMDOSA_TXT
+
+ public _jdos_open
+ public _jdos_close
+ public _jdos_seek
+ public _jdos_read
+ public _jdos_write
+ public _jxms_getdriver
+ public _jxms_calldriver
+ public _jems_available
+ public _jems_calldriver
+
+;
+; short far jdos_open (short far * handle, char far * filename)
+;
+; Create and open a temporary file
+;
+_jdos_open proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov cx,0 ; normal file attributes
+ lds dx,dword ptr [bp+10] ; get filename pointer
+ mov ah,3ch ; create file
+ int 21h
+ jc open_err ; if failed, return error code
+ lds bx,dword ptr [bp+6] ; get handle pointer
+ mov word ptr [bx],ax ; save the handle
+ xor ax,ax ; return zero for OK
+open_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_open endp
+
+
+;
+; short far jdos_close (short handle)
+;
+; Close the file handle
+;
+_jdos_close proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ mov ah,3eh ; close file
+ int 21h
+ jc close_err ; if failed, return error code
+ xor ax,ax ; return zero for OK
+close_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_close endp
+
+
+;
+; short far jdos_seek (short handle, long offset)
+;
+; Set file position
+;
+_jdos_seek proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ mov dx,word ptr [bp+8] ; LS offset
+ mov cx,word ptr [bp+10] ; MS offset
+ mov ax,4200h ; absolute seek
+ int 21h
+ jc seek_err ; if failed, return error code
+ xor ax,ax ; return zero for OK
+seek_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_seek endp
+
+
+;
+; short far jdos_read (short handle, void far * buffer, unsigned short count)
+;
+; Read from file
+;
+_jdos_read proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ lds dx,dword ptr [bp+8] ; buffer address
+ mov cx,word ptr [bp+12] ; number of bytes
+ mov ah,3fh ; read file
+ int 21h
+ jc read_err ; if failed, return error code
+ cmp ax,word ptr [bp+12] ; make sure all bytes were read
+ je read_ok
+ mov ax,1 ; else return 1 for not OK
+ jmp short read_err
+read_ok: xor ax,ax ; return zero for OK
+read_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_read endp
+
+
+;
+; short far jdos_write (short handle, void far * buffer, unsigned short count)
+;
+; Write to file
+;
+_jdos_write proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ lds dx,dword ptr [bp+8] ; buffer address
+ mov cx,word ptr [bp+12] ; number of bytes
+ mov ah,40h ; write file
+ int 21h
+ jc write_err ; if failed, return error code
+ cmp ax,word ptr [bp+12] ; make sure all bytes written
+ je write_ok
+ mov ax,1 ; else return 1 for not OK
+ jmp short write_err
+write_ok: xor ax,ax ; return zero for OK
+write_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_write endp
+
+
+;
+; void far jxms_getdriver (XMSDRIVER far *)
+;
+; Get the address of the XMS driver, or NULL if not available
+;
+_jxms_getdriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov ax,4300h ; call multiplex interrupt with
+ int 2fh ; a magic cookie, hex 4300
+ cmp al,80h ; AL should contain hex 80
+ je xmsavail
+ xor dx,dx ; no XMS driver available
+ xor ax,ax ; return a nil pointer
+ jmp short xmsavail_done
+xmsavail: mov ax,4310h ; fetch driver address with
+ int 2fh ; another magic cookie
+ mov dx,es ; copy address to dx:ax
+ mov ax,bx
+xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value
+ mov word ptr es:[bx],ax
+ mov word ptr es:[bx+2],dx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jxms_getdriver endp
+
+
+;
+; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
+;
+; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
+; These are loaded, the XMS call is performed, and the new values of the
+; AX,DX,BX registers are written back to the context structure.
+;
+_jxms_calldriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ les bx,dword ptr [bp+10] ; get XMScontext pointer
+ mov ax,word ptr es:[bx] ; load registers
+ mov dx,word ptr es:[bx+2]
+ mov si,word ptr es:[bx+6]
+ mov ds,word ptr es:[bx+8]
+ mov bx,word ptr es:[bx+4]
+ call dword ptr [bp+6] ; call the driver
+ mov cx,bx ; save returned BX for a sec
+ les bx,dword ptr [bp+10] ; get XMScontext pointer
+ mov word ptr es:[bx],ax ; put back ax,dx,bx
+ mov word ptr es:[bx+2],dx
+ mov word ptr es:[bx+4],cx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jxms_calldriver endp
+
+
+;
+; short far jems_available (void)
+;
+; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
+;
+_jems_available proc far
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov ax,3567h ; get interrupt vector 67h
+ int 21h
+ push cs
+ pop ds
+ mov di,000ah ; check offs 10 in returned seg
+ lea si,ASCII_device_name ; against literal string
+ mov cx,8
+ cld
+ repe cmpsb
+ jne no_ems
+ mov ax,1 ; match, it's there
+ jmp short avail_done
+no_ems: xor ax,ax ; it's not there
+avail_done: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ ret
+
+ASCII_device_name db "EMMXXXX0"
+
+_jems_available endp
+
+
+;
+; void far jems_calldriver (EMScontext far *)
+;
+; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
+; These are loaded, the EMS trap is performed, and the new values of the
+; AX,DX,BX registers are written back to the context structure.
+;
+_jems_calldriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ les bx,dword ptr [bp+6] ; get EMScontext pointer
+ mov ax,word ptr es:[bx] ; load registers
+ mov dx,word ptr es:[bx+2]
+ mov si,word ptr es:[bx+6]
+ mov ds,word ptr es:[bx+8]
+ mov bx,word ptr es:[bx+4]
+ int 67h ; call the EMS driver
+ mov cx,bx ; save returned BX for a sec
+ les bx,dword ptr [bp+6] ; get EMScontext pointer
+ mov word ptr es:[bx],ax ; put back ax,dx,bx
+ mov word ptr es:[bx+2],dx
+ mov word ptr es:[bx+4],cx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jems_calldriver endp
+
+JMEMDOSA_TXT ends
+
+ end
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemmgr.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemmgr.cpp
new file mode 100644
index 00000000..d17517c0
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemmgr.cpp
@@ -0,0 +1,1175 @@
+/*
+ * jmemmgr.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the JPEG system-independent memory management
+ * routines. This code is usable across a wide variety of machines; most
+ * of the system dependencies have been isolated in a separate file.
+ * The major functions provided here are:
+ * * pool-based allocation and freeing of memory;
+ * * policy decisions about how to divide available memory among the
+ * virtual arrays;
+ * * control logic for swapping virtual arrays between main memory and
+ * backing storage.
+ * The separate system-dependent file provides the actual backing-storage
+ * access code, and it contains the policy decision about how much total
+ * main memory to use.
+ * This file is system-dependent in the sense that some of its functions
+ * are unnecessary in some systems. For example, if there is enough virtual
+ * memory so that backing storage will never be used, much of the virtual
+ * array control logic could be removed. (Of course, if you have that much
+ * memory then you shouldn't care about a little bit of unused code...)
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef NO_GETENV
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */
+extern char * getenv JPP((const char * name));
+#endif
+#endif
+
+
+/*
+ * Some important notes:
+ * The allocation routines provided here must never return NULL.
+ * They should exit to error_exit if unsuccessful.
+ *
+ * It's not a good idea to try to merge the sarray, barray and darray
+ * routines, even though they are textually almost the same, because
+ * samples are usually stored as bytes while coefficients and differenced
+ * are shorts or ints. Thus, in machines where byte pointers have a
+ * different representation from word pointers, the resulting machine
+ * code could not be the same.
+ */
+
+
+/*
+ * Many machines require storage alignment: longs must start on 4-byte
+ * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc()
+ * always returns pointers that are multiples of the worst-case alignment
+ * requirement, and we had better do so too.
+ * There isn't any really portable way to determine the worst-case alignment
+ * requirement. This module assumes that the alignment requirement is
+ * multiples of sizeof(ALIGN_TYPE).
+ * By default, we define ALIGN_TYPE as double. This is necessary on some
+ * workstations (where doubles really do need 8-byte alignment) and will work
+ * fine on nearly everything. If your machine has lesser alignment needs,
+ * you can save a few bytes by making ALIGN_TYPE smaller.
+ * The only place I know of where this will NOT work is certain Macintosh
+ * 680x0 compilers that define double as a 10-byte IEEE extended float.
+ * Doing 10-byte alignment is counterproductive because longwords won't be
+ * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have
+ * such a compiler.
+ */
+
+#ifndef ALIGN_TYPE /* so can override from jconfig.h */
+#define ALIGN_TYPE double
+#endif
+
+
+/*
+ * We allocate objects from "pools", where each pool is gotten with a single
+ * request to jpeg_get_small() or jpeg_get_large(). There is no per-object
+ * overhead within a pool, except for alignment padding. Each pool has a
+ * header with a link to the next pool of the same class.
+ * Small and large pool headers are identical except that the latter's
+ * link pointer must be FAR on 80x86 machines.
+ * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
+ * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
+ * of the alignment requirement of ALIGN_TYPE.
+ */
+
+typedef union small_pool_struct * small_pool_ptr;
+
+typedef union small_pool_struct {
+ struct {
+ small_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} small_pool_hdr;
+
+typedef union large_pool_struct FAR * large_pool_ptr;
+
+typedef union large_pool_struct {
+ struct {
+ large_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} large_pool_hdr;
+
+
+/*
+ * Here is the full definition of a memory manager object.
+ */
+
+typedef struct {
+ struct jpeg_memory_mgr pub; /* public fields */
+
+ /* Each pool identifier (lifetime class) names a linked list of pools. */
+ small_pool_ptr small_list[JPOOL_NUMPOOLS];
+ large_pool_ptr large_list[JPOOL_NUMPOOLS];
+
+ /* Since we only have one lifetime class of virtual arrays, only one
+ * linked list is necessary (for each datatype). Note that the virtual
+ * array control blocks being linked together are actually stored somewhere
+ * in the small-pool list.
+ */
+ jvirt_sarray_ptr virt_sarray_list;
+ jvirt_barray_ptr virt_barray_list;
+
+ /* This counts total space obtained from jpeg_get_small/large */
+ long total_space_allocated;
+
+ /* alloc_sarray and alloc_barray set this value for use by virtual
+ * array routines.
+ */
+ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
+} my_memory_mgr;
+
+typedef my_memory_mgr * my_mem_ptr;
+
+
+/*
+ * The control blocks for virtual arrays.
+ * Note that these blocks are allocated in the "small" pool area.
+ * System-dependent info for the associated backing store (if any) is hidden
+ * inside the backing_store_info struct.
+ */
+
+struct jvirt_sarray_control {
+ JSAMPARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_sarray_ptr next; /* link to next virtual sarray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+struct jvirt_barray_control {
+ JBLOCKARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_barray_ptr next; /* link to next virtual barray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+
+#ifdef MEM_STATS /* optional extra stuff for statistics */
+
+LOCAL(void)
+print_mem_stats (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+
+ /* Since this is only a debugging stub, we can cheat a little by using
+ * fprintf directly rather than going through the trace message code.
+ * This is helpful because message parm array can't handle longs.
+ */
+ fprintf(stderr, "Freeing pool %d, total space = %ld\n",
+ pool_id, mem->total_space_allocated);
+
+ for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
+ lhdr_ptr = lhdr_ptr->hdr.next) {
+ fprintf(stderr, " Large chunk used %ld\n",
+ (long) lhdr_ptr->hdr.bytes_used);
+ }
+
+ for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
+ shdr_ptr = shdr_ptr->hdr.next) {
+ fprintf(stderr, " Small chunk used %ld free %ld\n",
+ (long) shdr_ptr->hdr.bytes_used,
+ (long) shdr_ptr->hdr.bytes_left);
+ }
+}
+
+#endif /* MEM_STATS */
+
+
+LOCAL(void)
+out_of_memory (j_common_ptr cinfo, int which)
+/* Report an out-of-memory error and stop execution */
+/* If we compiled MEM_STATS support, report alloc requests before dying */
+{
+#ifdef MEM_STATS
+ cinfo->err->trace_level = 2; /* force self_destruct to report stats */
+#endif
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
+}
+
+
+/*
+ * Allocation of "small" objects.
+ *
+ * For these, we use pooled storage. When a new pool must be created,
+ * we try to get enough space for the current request plus a "slop" factor,
+ * where the slop will be the amount of leftover space in the new pool.
+ * The speed vs. space tradeoff is largely determined by the slop values.
+ * A different slop value is provided for each pool class (lifetime),
+ * and we also distinguish the first pool of a class from later ones.
+ * NOTE: the values given work fairly well on both 16- and 32-bit-int
+ * machines, but may be too small if longs are 64 bits or more.
+ */
+
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 1600, /* first PERMANENT pool */
+ 16000 /* first IMAGE pool */
+};
+
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 0, /* additional PERMANENT pools */
+ 5000 /* additional IMAGE pools */
+};
+
+#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
+
+
+METHODDEF(void *)
+alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "small" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr hdr_ptr, prev_hdr_ptr;
+ char * data_ptr;
+ size_t odd_bytes, min_request, slop;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
+ out_of_memory(cinfo, 1); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* See if space is available in any existing pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+ prev_hdr_ptr = NULL;
+ hdr_ptr = mem->small_list[pool_id];
+ while (hdr_ptr != NULL) {
+ if (hdr_ptr->hdr.bytes_left >= sizeofobject)
+ break; /* found pool with enough space */
+ prev_hdr_ptr = hdr_ptr;
+ hdr_ptr = hdr_ptr->hdr.next;
+ }
+
+ /* Time to make a new pool? */
+ if (hdr_ptr == NULL) {
+ /* min_request is what we need now, slop is what will be leftover */
+ min_request = sizeofobject + SIZEOF(small_pool_hdr);
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ slop = first_pool_slop[pool_id];
+ else
+ slop = extra_pool_slop[pool_id];
+ /* Don't ask for more than MAX_ALLOC_CHUNK */
+ if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
+ slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+ /* Try to get space, if fail reduce slop and try again */
+ for (;;) {
+ hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+ if (hdr_ptr != NULL)
+ break;
+ slop /= 2;
+ if (slop < MIN_SLOP) /* give up when it gets real small */
+ out_of_memory(cinfo, 2); /* jpeg_get_small failed */
+ }
+ mem->total_space_allocated += (long)(min_request + slop);
+ /* Success, initialize the new pool header and add to end of list */
+ hdr_ptr->hdr.next = NULL;
+ hdr_ptr->hdr.bytes_used = 0;
+ hdr_ptr->hdr.bytes_left = sizeofobject + slop;
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ mem->small_list[pool_id] = hdr_ptr;
+ else
+ prev_hdr_ptr->hdr.next = hdr_ptr;
+ }
+
+ /* OK, allocate the object from the current pool */
+ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
+ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
+ hdr_ptr->hdr.bytes_used += sizeofobject;
+ hdr_ptr->hdr.bytes_left -= sizeofobject;
+
+ return (void *) data_ptr;
+}
+
+
+/*
+ * Allocation of "large" objects.
+ *
+ * The external semantics of these are the same as "small" objects,
+ * except that FAR pointers are used on 80x86. However the pool
+ * management heuristics are quite different. We assume that each
+ * request is large enough that it may as well be passed directly to
+ * jpeg_get_large; the pool management just links everything together
+ * so that we can free it all on demand.
+ * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
+ * structures. The routines that create these structures (see below)
+ * deliberately bunch rows together to ensure a large request size.
+ */
+
+METHODDEF(void FAR *)
+alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "large" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ large_pool_ptr hdr_ptr;
+ size_t odd_bytes;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
+ out_of_memory(cinfo, 3); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* Always make a new pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
+ SIZEOF(large_pool_hdr));
+ if (hdr_ptr == NULL)
+ out_of_memory(cinfo, 4); /* jpeg_get_large failed */
+ mem->total_space_allocated += (long)(sizeofobject + SIZEOF(large_pool_hdr));
+
+ /* Success, initialize the new pool header and add to list */
+ hdr_ptr->hdr.next = mem->large_list[pool_id];
+ /* We maintain space counts in each pool header for statistical purposes,
+ * even though they are not needed for allocation.
+ */
+ hdr_ptr->hdr.bytes_used = sizeofobject;
+ hdr_ptr->hdr.bytes_left = 0;
+ mem->large_list[pool_id] = hdr_ptr;
+
+ return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */
+}
+
+
+/*
+ * Creation of 2-D sample arrays.
+ * The pointers are in near heap, the samples themselves in FAR heap.
+ *
+ * To minimize allocation overhead and to allow I/O of large contiguous
+ * blocks, we allocate the sample rows in groups of as many rows as possible
+ * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
+ * NB: the virtual array control routines, later in this file, know about
+ * this chunking of rows. The rowsperchunk value is left in the mem manager
+ * object so that it can be saved away if this sarray is the workspace for
+ * a virtual array.
+ */
+
+METHODDEF(JSAMPARRAY)
+alloc_sarray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow, JDIMENSION numrows)
+/* Allocate a 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JSAMPARRAY result;
+ JSAMPROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) samplesperrow * SIZEOF(JSAMPLE));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JSAMPROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
+ * SIZEOF(JSAMPLE)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += samplesperrow;
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * Creation of 2-D coefficient-block arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JBLOCKARRAY)
+alloc_barray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow, JDIMENSION numrows)
+/* Allocate a 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JBLOCKARRAY result;
+ JBLOCKROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) blocksperrow * SIZEOF(JBLOCK));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JBLOCKROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
+ * SIZEOF(JBLOCK)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += blocksperrow;
+ }
+ }
+
+ return result;
+}
+
+
+#ifdef NEED_DARRAY
+
+/*
+ * Creation of 2-D difference arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JDIFFARRAY)
+alloc_darray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION diffsperrow, JDIMENSION numrows)
+/* Allocate a 2-D difference array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JDIFFARRAY result;
+ JDIFFROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) diffsperrow * SIZEOF(JDIFF));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JDIFFARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JDIFFROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JDIFFROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) diffsperrow
+ * SIZEOF(JDIFF)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += diffsperrow;
+ }
+ }
+
+ return result;
+}
+
+#endif
+
+
+/*
+ * About virtual array management:
+ *
+ * The above "normal" array routines are only used to allocate strip buffers
+ * (as wide as the image, but just a few rows high). Full-image-sized buffers
+ * are handled as "virtual" arrays. The array is still accessed a strip at a
+ * time, but the memory manager must save the whole array for repeated
+ * accesses. The intended implementation is that there is a strip buffer in
+ * memory (as high as is possible given the desired memory limit), plus a
+ * backing file that holds the rest of the array.
+ *
+ * The request_virt_array routines are told the total size of the image and
+ * the maximum number of rows that will be accessed at once. The in-memory
+ * buffer must be at least as large as the maxaccess value.
+ *
+ * The request routines create control blocks but not the in-memory buffers.
+ * That is postponed until realize_virt_arrays is called. At that time the
+ * total amount of space needed is known (approximately, anyway), so free
+ * memory can be divided up fairly.
+ *
+ * The access_virt_array routines are responsible for making a specific strip
+ * area accessible (after reading or writing the backing file, if necessary).
+ * Note that the access routines are told whether the caller intends to modify
+ * the accessed strip; during a read-only pass this saves having to rewrite
+ * data to disk. The access routines are also responsible for pre-zeroing
+ * any newly accessed rows, if pre-zeroing was requested.
+ *
+ * In current usage, the access requests are usually for nonoverlapping
+ * strips; that is, successive access start_row numbers differ by exactly
+ * num_rows = maxaccess. This means we can get good performance with simple
+ * buffer dump/reload logic, by making the in-memory buffer be a multiple
+ * of the access height; then there will never be accesses across bufferload
+ * boundaries. The code will still work with overlapping access requests,
+ * but it doesn't handle bufferload overlaps very efficiently.
+ */
+
+
+METHODDEF(jvirt_sarray_ptr)
+request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION samplesperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_sarray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_sarray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->samplesperrow = samplesperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
+ mem->virt_sarray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(jvirt_barray_ptr)
+request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION blocksperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_barray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_barray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->blocksperrow = blocksperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_barray_list; /* add to list of virtual arrays */
+ mem->virt_barray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(void)
+realize_virt_arrays (j_common_ptr cinfo)
+/* Allocate the in-memory buffers for any unrealized virtual arrays */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ long space_per_minheight, maximum_space, avail_mem;
+ long minheights, max_minheights;
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ /* Compute the minimum space needed (maxaccess rows in each buffer)
+ * and the maximum space needed (full image height in each buffer).
+ * These may be of use to the system-dependent jpeg_mem_available routine.
+ */
+ space_per_minheight = 0;
+ maximum_space = 0;
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) sptr->maxaccess *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ maximum_space += (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ }
+ }
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) bptr->maxaccess *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ maximum_space += (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ }
+ }
+
+ if (space_per_minheight <= 0)
+ return; /* no unrealized arrays, no work */
+
+ /* Determine amount of memory to actually use; this is system-dependent. */
+ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
+ mem->total_space_allocated);
+
+ /* If the maximum space needed is available, make all the buffers full
+ * height; otherwise parcel it out with the same number of minheights
+ * in each buffer.
+ */
+ if (avail_mem >= maximum_space)
+ max_minheights = 1000000000L;
+ else {
+ max_minheights = avail_mem / space_per_minheight;
+ /* If there doesn't seem to be enough space, try to get the minimum
+ * anyway. This allows a "stub" implementation of jpeg_mem_available().
+ */
+ if (max_minheights <= 0)
+ max_minheights = 1;
+ }
+
+ /* Allocate the in-memory buffers and initialize backing store as needed. */
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ sptr->rows_in_mem = sptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & sptr->b_s_info,
+ (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow *
+ (long) SIZEOF(JSAMPLE));
+ sptr->b_s_open = TRUE;
+ }
+ sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
+ sptr->samplesperrow, sptr->rows_in_mem);
+ sptr->rowsperchunk = mem->last_rowsperchunk;
+ sptr->cur_start_row = 0;
+ sptr->first_undef_row = 0;
+ sptr->dirty = FALSE;
+ }
+ }
+
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ bptr->rows_in_mem = bptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & bptr->b_s_info,
+ (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow *
+ (long) SIZEOF(JBLOCK));
+ bptr->b_s_open = TRUE;
+ }
+ bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
+ bptr->blocksperrow, bptr->rows_in_mem);
+ bptr->rowsperchunk = mem->last_rowsperchunk;
+ bptr->cur_start_row = 0;
+ bptr->first_undef_row = 0;
+ bptr->dirty = FALSE;
+ }
+ }
+}
+
+
+LOCAL(void)
+do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual sample array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+LOCAL(void)
+do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual coefficient-block array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+METHODDEF(JSAMPARRAY)
+access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual sample array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_sarray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_sarray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+METHODDEF(JBLOCKARRAY)
+access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual block array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_barray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_barray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+/*
+ * Release all objects belonging to a specified pool.
+ */
+
+METHODDEF(void)
+free_pool (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+ size_t space_freed;
+
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+#ifdef MEM_STATS
+ if (cinfo->err->trace_level > 1)
+ print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
+#endif
+
+ /* If freeing IMAGE pool, close any virtual arrays first */
+ if (pool_id == JPOOL_IMAGE) {
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->b_s_open) { /* there may be no backing store */
+ sptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+ }
+ }
+ mem->virt_sarray_list = NULL;
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->b_s_open) { /* there may be no backing store */
+ bptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+ }
+ }
+ mem->virt_barray_list = NULL;
+ }
+
+ /* Release large objects */
+ lhdr_ptr = mem->large_list[pool_id];
+ mem->large_list[pool_id] = NULL;
+
+ while (lhdr_ptr != NULL) {
+ large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
+ space_freed = lhdr_ptr->hdr.bytes_used +
+ lhdr_ptr->hdr.bytes_left +
+ SIZEOF(large_pool_hdr);
+ jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
+ mem->total_space_allocated -= (long)space_freed;
+ lhdr_ptr = next_lhdr_ptr;
+ }
+
+ /* Release small objects */
+ shdr_ptr = mem->small_list[pool_id];
+ mem->small_list[pool_id] = NULL;
+
+ while (shdr_ptr != NULL) {
+ small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
+ space_freed = shdr_ptr->hdr.bytes_used +
+ shdr_ptr->hdr.bytes_left +
+ SIZEOF(small_pool_hdr);
+ jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+ mem->total_space_allocated -= (long)space_freed;
+ shdr_ptr = next_shdr_ptr;
+ }
+}
+
+
+/*
+ * Close up shop entirely.
+ * Note that this cannot be called unless cinfo->mem is non-NULL.
+ */
+
+METHODDEF(void)
+self_destruct (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Close all backing store, release all memory.
+ * Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ free_pool(cinfo, pool);
+ }
+
+ /* Release the memory manager control block too. */
+ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
+ cinfo->mem = NULL; /* ensures I will be called only once */
+
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+}
+
+
+/*
+ * Memory manager initialization.
+ * When this is called, only the error manager pointer is valid in cinfo!
+ */
+
+GLOBAL(void)
+jinit_memory_mgr (j_common_ptr cinfo)
+{
+ my_mem_ptr mem;
+ long max_to_use;
+ int pool;
+ size_t test_mac;
+
+ cinfo->mem = NULL; /* for safety if init fails */
+
+ /* Check for configuration errors.
+ * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
+ * doesn't reflect any real hardware alignment requirement.
+ * The test is a little tricky: for X>0, X and X-1 have no one-bits
+ * in common if and only if X is a power of 2, ie has only one one-bit.
+ * Some compilers may give an "unreachable code" warning here; ignore it.
+ */
+ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
+ /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
+ * a multiple of SIZEOF(ALIGN_TYPE).
+ * Again, an "unreachable code" warning may be ignored here.
+ * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
+ */
+ test_mac = (size_t) MAX_ALLOC_CHUNK;
+ if ((long) test_mac != MAX_ALLOC_CHUNK ||
+ (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+
+ max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
+
+ /* Attempt to allocate memory manager's control block */
+ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
+
+ if (mem == NULL) {
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
+ }
+
+ /* OK, fill in the method pointers */
+ mem->pub.alloc_small = alloc_small;
+ mem->pub.alloc_large = alloc_large;
+ mem->pub.alloc_sarray = alloc_sarray;
+ mem->pub.alloc_barray = alloc_barray;
+#ifdef NEED_DARRAY
+ mem->pub.alloc_darray = alloc_darray;
+#endif
+ mem->pub.request_virt_sarray = request_virt_sarray;
+ mem->pub.request_virt_barray = request_virt_barray;
+ mem->pub.realize_virt_arrays = realize_virt_arrays;
+ mem->pub.access_virt_sarray = access_virt_sarray;
+ mem->pub.access_virt_barray = access_virt_barray;
+ mem->pub.free_pool = free_pool;
+ mem->pub.self_destruct = self_destruct;
+
+ /* Make MAX_ALLOC_CHUNK accessible to other modules */
+ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
+
+ /* Initialize working state */
+ mem->pub.max_memory_to_use = max_to_use;
+
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ mem->small_list[pool] = NULL;
+ mem->large_list[pool] = NULL;
+ }
+ mem->virt_sarray_list = NULL;
+ mem->virt_barray_list = NULL;
+
+ mem->total_space_allocated = SIZEOF(my_memory_mgr);
+
+ /* Declare ourselves open for business */
+ cinfo->mem = & mem->pub;
+
+ /* Check for an environment variable JPEGMEM; if found, override the
+ * default max_memory setting from jpeg_mem_init. Note that the
+ * surrounding application may again override this value.
+ * If your system doesn't support getenv(), define NO_GETENV to disable
+ * this feature.
+ */
+#ifndef NO_GETENV
+ { char * memenv;
+
+ if ((memenv = getenv("JPEGMEM")) != NULL) {
+ char ch = 'x';
+
+ if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
+ if (ch == 'm' || ch == 'M')
+ max_to_use *= 1000L;
+ mem->pub.max_memory_to_use = max_to_use * 1000L;
+ }
+ }
+ }
+#endif
+
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemnobs.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemnobs.cpp
new file mode 100644
index 00000000..ca89fd84
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemnobs.cpp
@@ -0,0 +1,110 @@
+/*
+ * jmemnobs.c
+ *
+ * Copyright (C) 1992-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a really simple implementation of the system-
+ * dependent portion of the JPEG memory manager. This implementation
+ * assumes that no backing-store files are needed: all required space
+ * can be obtained from malloc().
+ * This is very portable in the sense that it'll compile on almost anything,
+ * but you'd better have lots of main memory (or virtual memory) if you want
+ * to process big images.
+ * Note that the max_memory_to_use option is ignored by this implementation.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return max_bytes_needed;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ return 0; /* just set max_memory_to_use to 0 */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemsys.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemsys.h
new file mode 100644
index 00000000..6c3c6d34
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmemsys.h
@@ -0,0 +1,198 @@
+/*
+ * jmemsys.h
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file defines the interface between the system-independent
+ * and system-dependent portions of the JPEG memory manager. No other
+ * modules need include it. (The system-independent portion is jmemmgr.c;
+ * there are several different versions of the system-dependent portion.)
+ *
+ * This file works as-is for the system-dependent memory managers supplied
+ * in the IJG distribution. You may need to modify it if you write a
+ * custom memory manager. If system-dependent changes are needed in
+ * this file, the best method is to #ifdef them based on a configuration
+ * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR
+ * and USE_MAC_MEMMGR.
+ */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_get_small jGetSmall
+#define jpeg_free_small jFreeSmall
+#define jpeg_get_large jGetLarge
+#define jpeg_free_large jFreeLarge
+#define jpeg_mem_available jMemAvail
+#define jpeg_open_backing_store jOpenBackStore
+#define jpeg_mem_init jMemInit
+#define jpeg_mem_term jMemTerm
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * These two functions are used to allocate and release small chunks of
+ * memory. (Typically the total amount requested through jpeg_get_small is
+ * no more than 20K or so; this will be requested in chunks of a few K each.)
+ * Behavior should be the same as for the standard library functions malloc
+ * and free; in particular, jpeg_get_small must return NULL on failure.
+ * On most systems, these ARE malloc and free. jpeg_free_small is passed the
+ * size of the object being freed, just in case it's needed.
+ * On an 80x86 machine using small-data memory model, these manage near heap.
+ */
+
+EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
+EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
+ size_t sizeofobject));
+
+/*
+ * These two functions are used to allocate and release large chunks of
+ * memory (up to the total free space designated by jpeg_mem_available).
+ * The interface is the same as above, except that on an 80x86 machine,
+ * far pointers are used. On most other machines these are identical to
+ * the jpeg_get/free_small routines; but we keep them separate anyway,
+ * in case a different allocation strategy is desirable for large chunks.
+ */
+
+EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
+ size_t sizeofobject));
+EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
+ size_t sizeofobject));
+
+/*
+ * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
+ * be requested in a single call to jpeg_get_large (and jpeg_get_small for that
+ * matter, but that case should never come into play). This macro is needed
+ * to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
+ * On those machines, we expect that jconfig.h will provide a proper value.
+ * On machines with 32-bit flat address spaces, any large constant may be used.
+ *
+ * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
+ * size_t and will be a multiple of sizeof(align_type).
+ */
+
+#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
+#define MAX_ALLOC_CHUNK 1000000000L
+#endif
+
+/*
+ * This routine computes the total space still available for allocation by
+ * jpeg_get_large. If more space than this is needed, backing store will be
+ * used. NOTE: any memory already allocated must not be counted.
+ *
+ * There is a minimum space requirement, corresponding to the minimum
+ * feasible buffer sizes; jmemmgr.c will request that much space even if
+ * jpeg_mem_available returns zero. The maximum space needed, enough to hold
+ * all working storage in memory, is also passed in case it is useful.
+ * Finally, the total space already allocated is passed. If no better
+ * method is available, cinfo->mem->max_memory_to_use - already_allocated
+ * is often a suitable calculation.
+ *
+ * It is OK for jpeg_mem_available to underestimate the space available
+ * (that'll just lead to more backing-store access than is really necessary).
+ * However, an overestimate will lead to failure. Hence it's wise to subtract
+ * a slop factor from the true available space. 5% should be enough.
+ *
+ * On machines with lots of virtual memory, any large constant may be returned.
+ * Conversely, zero may be returned to always use the minimum amount of memory.
+ */
+
+EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
+ long min_bytes_needed,
+ long max_bytes_needed,
+ long already_allocated));
+
+
+/*
+ * This structure holds whatever state is needed to access a single
+ * backing-store object. The read/write/close method pointers are called
+ * by jmemmgr.c to manipulate the backing-store object; all other fields
+ * are private to the system-dependent backing store routines.
+ */
+
+#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
+
+
+#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
+
+typedef unsigned short XMSH; /* type of extended-memory handles */
+typedef unsigned short EMSH; /* type of expanded-memory handles */
+
+typedef union {
+ short file_handle; /* DOS file handle if it's a temp file */
+ XMSH xms_handle; /* handle if it's a chunk of XMS */
+ EMSH ems_handle; /* handle if it's a chunk of EMS */
+} handle_union;
+
+#endif /* USE_MSDOS_MEMMGR */
+
+#ifdef USE_MAC_MEMMGR /* Mac-specific junk */
+#include <Files.h>
+#endif /* USE_MAC_MEMMGR */
+
+
+typedef struct backing_store_struct * backing_store_ptr;
+
+typedef struct backing_store_struct {
+ /* Methods for reading/writing/closing this backing-store object */
+ JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info));
+
+ /* Private fields for system-dependent backing-store management */
+#ifdef USE_MSDOS_MEMMGR
+ /* For the MS-DOS manager (jmemdos.c), we need: */
+ handle_union handle; /* reference to backing-store storage object */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+#ifdef USE_MAC_MEMMGR
+ /* For the Mac manager (jmemmac.c), we need: */
+ short temp_file; /* file reference number to temp file */
+ FSSpec tempSpec; /* the FSSpec for the temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+ /* For a typical implementation with temp files, we need: */
+ FILE * temp_file; /* stdio reference to temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
+#endif
+#endif
+} backing_store_info;
+
+
+/*
+ * Initial opening of a backing-store object. This must fill in the
+ * read/write/close pointers in the object. The read/write routines
+ * may take an error exit if the specified maximum file size is exceeded.
+ * (If jpeg_mem_available always returns a large value, this routine can
+ * just take an error exit.)
+ */
+
+EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
+ backing_store_ptr info,
+ long total_bytes_needed));
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. jpeg_mem_init will be called before anything is
+ * allocated (and, therefore, nothing in cinfo is of use except the error
+ * manager pointer). It should return a suitable default value for
+ * max_memory_to_use; this may subsequently be overridden by the surrounding
+ * application. (Note that max_memory_to_use is only important if
+ * jpeg_mem_available chooses to consult it ... no one else will.)
+ * jpeg_mem_term may assume that all requested memory has been freed and that
+ * all opened backing-store objects have been closed.
+ */
+
+EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jmorecfg.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmorecfg.h
new file mode 100644
index 00000000..238d8ca2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jmorecfg.h
@@ -0,0 +1,403 @@
+/*
+ * jmorecfg.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains additional configuration options that customize the
+ * JPEG software for special applications or support machine-dependent
+ * optimizations. Most users will not need to touch this file.
+ */
+
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ * 8 for 8-bit sample values (the usual setting)
+ * 12 for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
+
+
+/*
+ * Maximum number of components (color channels) allowed in JPEG image.
+ * To meet the letter of the JPEG spec, set this to 255. However, darn
+ * few applications need more than 4 channels (maybe 5 for CMYK + alpha
+ * mask). We recommend 10 as a reasonable compromise; use 4 if you are
+ * really short on memory. (Each allowed component costs a hundred or so
+ * bytes of storage, whether actually used in an image or not.)
+ */
+
+#define MAX_COMPONENTS 10 /* maximum number of image components */
+
+
+/*
+ * Basic data types.
+ * You may need to change these if you have a machine with unusual data
+ * type sizes; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* Representation of a single sample (pixel element value).
+ * We frequently allocate large arrays of these, so it's important to keep
+ * them small. But if you have memory to burn and access to char or short
+ * arrays is very slow on your hardware, you might want to change these.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JSAMPLE;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJSAMPLE(value) ((int) (value))
+#else
+#define GETJSAMPLE(value) ((int) (value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE 255
+#define CENTERJSAMPLE 128
+
+#endif /* BITS_IN_JSAMPLE == 8 */
+
+
+#if BITS_IN_JSAMPLE == 12
+/* JSAMPLE should be the smallest type that will hold the values 0..4095.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 4095
+#define CENTERJSAMPLE 2048
+
+#endif /* BITS_IN_JSAMPLE == 12 */
+
+
+#if BITS_IN_JSAMPLE == 16
+/* JSAMPLE should be the smallest type that will hold the values 0..65535.
+ * You can use a signed short by having GETJSAMPLE mask it with 0xFFFF.
+ */
+
+#ifdef HAVE_UNSIGNED_SHORT
+
+typedef unsigned short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#else /* not HAVE_UNSIGNED_SHORT */
+
+typedef short JSAMPLE;
+#ifdef SHORT_IS_UNSIGNED
+#define GETJSAMPLE(value) ((int) (value))
+#else
+#define GETJSAMPLE(value) ((int) (value) & 0xFFFF)
+#endif /* SHORT_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_SHORT */
+
+#define MAXJSAMPLE 65535
+#define CENTERJSAMPLE 32768
+
+#endif /* BITS_IN_JSAMPLE == 16 */
+
+
+/* Representation of a DCT frequency coefficient.
+ * This should be a signed value of at least 16 bits; "short" is usually OK.
+ * Again, we allocate large arrays of these, but you can change to int
+ * if you have memory to burn and "short" is really slow.
+ */
+
+typedef short JCOEF;
+
+
+/* Representation of a spatial difference value.
+ * This should be a signed value of at least 16 bits; int is usually OK.
+ */
+
+typedef int JDIFF;
+
+
+/* Compressed datastreams are represented as arrays of JOCTET.
+ * These must be EXACTLY 8 bits wide, at least once they are written to
+ * external storage. Note that when using the stdio data source/destination
+ * managers, this is also the data type passed to fread/fwrite.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JOCTET;
+#define GETJOCTET(value) (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JOCTET;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJOCTET(value) (value)
+#else
+#define GETJOCTET(value) ((value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+/* These typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE. (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
+typedef short INT16;
+#endif
+
+/* INT32 must hold at least signed 32-bit values. */
+#define XMD_H
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
+typedef long INT32;
+#endif
+
+/* Datatype used for image dimensions. The JPEG standard only supports
+ * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
+ * "unsigned int" is sufficient on all machines. However, if you need to
+ * handle larger images and you don't mind deviating from the spec, you
+ * can change this datatype.
+ */
+
+typedef unsigned int JDIMENSION;
+
+#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
+
+
+/* These macros are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions;
+ * in particular, you'll need to do that to make the library a Windows DLL.
+ * Another application is to make all functions global for use with debuggers
+ * or code profilers that require it.
+ */
+
+/* a function called through method pointers: */
+#define METHODDEF(type) static type
+/* a function used only in its module: */
+#define LOCAL(type) static type
+/* a function referenced thru EXTERNs: */
+#define GLOBAL(type) type
+/* a reference to a GLOBAL function: */
+#define EXTERN(type) extern type
+
+
+/* This macro is used to declare a "method", that is, a function pointer.
+ * We want to supply prototype parameters if the compiler can cope.
+ * Note that the arglist parameter must be parenthesized!
+ * Again, you can customize this if you need special linkage keywords.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+#else
+#define JMETHOD(type,methodname,arglist) type (*methodname) ()
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines. Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed. In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifdef NEED_FAR_POINTERS
+#define FAR far
+#else
+#ifndef FAR
+#define FAR
+#endif
+#endif
+
+
+/*
+ * On a few systems, type boolean and/or its values FALSE, TRUE may appear
+ * in standard header files. Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
+ */
+
+#ifndef HAVE_BOOLEAN
+typedef int boolean;
+#endif
+#ifndef FALSE /* in case these macros already exist */
+#define FALSE 0 /* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+
+/*
+ * The remaining options affect code selection within the JPEG library,
+ * but they don't need to be visible to most applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+#define JPEG_INTERNAL_OPTIONS
+#endif
+
+#ifdef JPEG_INTERNAL_OPTIONS
+
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * library. Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
+
+/* Capability options common to encoder and decoder: */
+
+#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
+#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
+#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
+
+/* Encoder capability options: */
+
+#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */
+#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
+/* Note: if you selected 12-bit data precision, it is dangerous to turn off
+ * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
+ * precision, so jcshuff.c normally uses entropy optimization to compute
+ * usable tables for higher precision. If you don't want to do optimization,
+ * you'll have to supply different default Huffman tables.
+ * The exact same statements apply for progressive and lossless JPEG:
+ * the default tables don't work for progressive mode or lossless mode.
+ * (This may get fixed, however.)
+ */
+#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
+
+/* Decoder capability options: */
+
+#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? */
+#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
+#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
+#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
+#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
+#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
+#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
+#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Ordering of RGB data in scanlines passed to or from the application.
+ * If your application wants to deal with data in the order B,G,R, just
+ * change these macros. You can also deal with formats such as R,G,B,X
+ * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
+ * the offsets will also change the order in which colormap data is organized.
+ * RESTRICTIONS:
+ * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
+ * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
+ * useful if you are using JPEG color spaces other than YCbCr or grayscale.
+ * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
+ * is not 3 (they don't understand about dummy color components!). So you
+ * can't use color quantization if you change that value.
+ */
+
+#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
+#define RGB_GREEN 1 /* Offset of Green */
+#define RGB_BLUE 2 /* Offset of Blue */
+#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
+
+
+/* Definitions for speed-related optimizations. */
+
+
+/* If your compiler supports inline functions, define INLINE
+ * as the inline keyword; otherwise define it as empty.
+ */
+
+#ifndef INLINE
+#ifdef __GNUC__ /* for instance, GNU C knows about inline */
+#define INLINE __inline__
+#endif
+#ifndef INLINE
+#define INLINE /* default is to define it as empty */
+#endif
+#endif
+
+
+/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
+ * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
+ * as short on such a machine. MULTIPLIER must be at least 16 bits wide.
+ */
+
+#ifndef MULTIPLIER
+#define MULTIPLIER int /* type for fastest integer multiply */
+#endif
+
+
+/* FAST_FLOAT should be either float or double, whichever is done faster
+ * by your compiler. (Note that this type is only used in the floating point
+ * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
+ * Typically, float is faster in ANSI C compilers, while double is faster in
+ * pre-ANSI compilers (because they insist on converting to double anyway).
+ * The code below therefore chooses float if we have ANSI-style prototypes.
+ */
+
+#ifndef FAST_FLOAT
+#ifdef HAVE_PROTOTYPES
+#define FAST_FLOAT float
+#else
+#define FAST_FLOAT double
+#endif
+#endif
+
+#endif /* JPEG_INTERNAL_OPTIONS */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jpegint.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jpegint.h
new file mode 100644
index 00000000..98c3fed6
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jpegint.h
@@ -0,0 +1,355 @@
+/*
+ * jpegint.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides common declarations for the various JPEG modules.
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+
+/* Declarations for both compression & decompression */
+
+typedef enum { /* Operating modes for buffer controllers */
+ JBUF_PASS_THRU, /* Plain stripwise operation */
+ /* Remaining modes require a full-image buffer to have been created */
+ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
+ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
+ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
+} J_BUF_MODE;
+
+/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+
+
+/* Declarations for compression modules */
+
+/* Master control module */
+struct jpeg_comp_master {
+ JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean call_pass_startup; /* True if pass_startup must be called */
+ boolean is_last_pass; /* True during last pass */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_c_main_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail));
+};
+
+/* Compression preprocessing (downsampling input buffer control) */
+struct jpeg_c_prep_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf,
+ JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail));
+};
+
+/* Compression codec (compressor proper) */
+struct jpeg_c_codec {
+ JMETHOD(void, entropy_start_pass, (j_compress_ptr cinfo,
+ boolean gather_statistics));
+ JMETHOD(void, entropy_finish_pass, (j_compress_ptr cinfo));
+ JMETHOD(boolean, need_optimization_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf));
+};
+
+/* Colorspace conversion */
+struct jpeg_color_converter {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows));
+};
+
+/* Downsampling */
+struct jpeg_downsampler {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, downsample, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Marker writing */
+struct jpeg_marker_writer {
+ JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
+ JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
+ /* These routines are exported to allow insertion of extra markers */
+ /* Probably only COM and APPn markers should be written this way */
+ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
+ unsigned int datalen));
+ JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
+};
+
+
+/* Declarations for decompression modules */
+
+/* Master control module */
+struct jpeg_decomp_master {
+ JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
+};
+
+/* Input control module */
+struct jpeg_input_controller {
+ JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
+ JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean has_multiple_scans; /* True if file has multiple scans */
+ boolean eoi_reached; /* True when EOI has been consumed */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_d_main_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Decompression codec (decompressor proper) */
+struct jpeg_d_codec {
+ JMETHOD(void, calc_output_dimensions, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf));
+};
+
+/* Decompression postprocessing (color quantization buffer control) */
+struct jpeg_d_post_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Marker reading & parsing */
+struct jpeg_marker_reader {
+ JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
+ /* Read markers until SOS or EOI.
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+ JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
+ /* Read a restart marker --- exported for use by entropy decoder only */
+ jpeg_marker_parser_method read_restart_marker;
+
+ /* State of marker reader --- nominally internal, but applications
+ * supplying COM or APPn handlers might like to know the state.
+ */
+ boolean saw_SOI; /* found SOI? */
+ boolean saw_SOF; /* found SOF? */
+ int next_restart_num; /* next restart number expected (0-7) */
+ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
+};
+
+/* Upsampling (note that upsampler must also call color converter) */
+struct jpeg_upsampler {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Colorspace conversion */
+struct jpeg_color_deconverter {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows));
+};
+
+/* Color quantization or color precision reduction */
+struct jpeg_color_quantizer {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
+ JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+ int num_rows));
+ JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+};
+
+
+/* Miscellaneous useful macros */
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_c_codec jICCodec
+#define jinit_lossy_c_codec jILossyC
+#define jinit_compress_master jICompress
+#define jinit_c_master_control jICMaster
+#define jinit_c_main_controller jICMainC
+#define jinit_c_prep_controller jICPrepC
+#define jinit_c_coef_controller jICCoefC
+#define jinit_color_converter jICColor
+#define jinit_downsampler jIDownsampler
+#define jinit_forward_dct jIFDCT
+#define jinit_shuff_encoder jISHEncoder
+#define jinit_phuff_encoder jIPHEncoder
+#define jinit_marker_writer jIMWriter
+#define jinit_d_codec jIDCodec
+#define jinit_lossy_d_codec jILossyD
+#define jinit_lossless_d_codec jILosslsD
+#define jinit_master_decompress jIDMaster
+#define jinit_d_main_controller jIDMainC
+#define jinit_d_coef_controller jIDCoefC
+#define jinit_d_diff_controller jIDDiffC
+#define jinit_d_post_controller jIDPostC
+#define jinit_input_controller jIInCtlr
+#define jinit_marker_reader jIMReader
+#define jinit_shuff_decoder jISHDecoder
+#define jinit_phuff_decoder jIPHDecoder
+#define jinit_lhuff_decoder jILHDecoder
+#define jinit_undifferencer jIUndiff
+#define jinit_d_scaler jIDScaler
+#define jinit_inverse_dct jIIDCT
+#define jinit_upsampler jIUpsampler
+#define jinit_color_deconverter jIDColor
+#define jinit_1pass_quantizer jI1Quant
+#define jinit_2pass_quantizer jI2Quant
+#define jinit_merged_upsampler jIMUpsampler
+#define jinit_memory_mgr jIMemMgr
+#define jdiv_round_up jDivRound
+#define jround_up jRound
+#define jcopy_sample_rows jCopySamples
+#define jcopy_block_row jCopyBlocks
+#define jzero_far jZeroFar
+#define jpeg_zigzag_order jZIGTable
+#define jpeg_natural_order jZAGTable
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
+ boolean transcode_only));
+EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_compressor JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_decompressor JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
+/* Memory manager initialization */
+EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
+
+/* Utility routines in jutils.c */
+EXTERN(long) jdiv_round_up JPP((long a, long b));
+EXTERN(long) jround_up JPP((long a, long b));
+EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols));
+EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks));
+EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
+/* Constant tables in jutils.c */
+#if 0 /* This table is not actually needed in v6a */
+extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
+#endif
+extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
+
+/* Suppress undefined-structure complaints if necessary. */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+#endif
+#endif /* INCOMPLETE_TYPES_BROKEN */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jpeglib.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jpeglib.h
new file mode 100644
index 00000000..e6ac193d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jpeglib.h
@@ -0,0 +1,1131 @@
+/*
+ * jpeglib.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the application interface for the JPEG library.
+ * Most applications using the library need only include this file,
+ * and perhaps jerror.h if they want to know the exact error codes.
+ */
+
+#ifndef JPEGLIB_H
+#define JPEGLIB_H
+
+/*
+ * First we include the configuration files that record how this
+ * installation of the JPEG library is set up. jconfig.h can be
+ * generated automatically for many systems. jmorecfg.h contains
+ * manual configuration options that most people need not worry about.
+ */
+
+#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
+#include "jconfig.h" /* widely used configuration options */
+#endif
+#include "jmorecfg.h" /* seldom changed options */
+
+
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
+ */
+
+#define JPEG_LIB_VERSION 62 /* Version 6b */
+
+
+/* Various constants determining the sizes of things.
+ * All of these are specified by the JPEG standard, so don't change them
+ * if you want to be compatible.
+ */
+
+#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
+#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
+#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
+/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
+ * the PostScript DCT filter can emit files with many more than 10 data units
+ * per MCU.
+ * If you happen to run across such a file, you can up D_MAX_DATA_UNITS_IN_MCU
+ * to handle it. We even let you do this from the jconfig.h file. However,
+ * we strongly discourage changing C_MAX_DATA_UNITS_IN_MCU; just because Adobe
+ * sometimes emits noncompliant files doesn't mean you should too.
+ */
+#define C_MAX_DATA_UNITS_IN_MCU 10 /* compressor's limit on data units/MCU */
+#ifndef D_MAX_DATA_UNITS_IN_MCU
+#define D_MAX_DATA_UNITS_IN_MCU 10 /* decompressor's limit on data units/MCU */
+#endif
+
+
+/* Data structures for images (arrays of samples and of DCT coefficients).
+ * On 80x86 machines, the image arrays are too big for near pointers,
+ * but the pointer arrays can fit in near memory.
+ */
+
+typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
+
+typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
+
+typedef JDIFF FAR *JDIFFROW; /* pointer to one row of difference values */
+typedef JDIFFROW *JDIFFARRAY; /* ptr to some rows (a 2-D diff array) */
+typedef JDIFFARRAY *JDIFFIMAGE; /* a 3-D diff array: top index is color */
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+/* DCT coefficient quantization tables. */
+
+typedef struct {
+ /* This array gives the coefficient quantizers in natural array order
+ * (not the zigzag order in which they are stored in a JPEG DQT marker).
+ * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+ */
+ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JQUANT_TBL;
+
+
+/* Huffman coding tables. */
+
+typedef struct {
+ /* These two fields directly represent the contents of a JPEG DHT marker */
+ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
+ /* length k bits; bits[0] is unused */
+ UINT8 huffval[256]; /* The symbols, in order of incr code length */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JHUFF_TBL;
+
+
+/* Basic info about one component (color channel). */
+
+typedef struct {
+ /* These values are fixed over the whole image. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOF marker. */
+ int component_id; /* identifier for this component (0..255) */
+ int component_index; /* its index in SOF or cinfo->comp_info[] */
+ int h_samp_factor; /* horizontal sampling factor (1..4) */
+ int v_samp_factor; /* vertical sampling factor (1..4) */
+ int quant_tbl_no; /* quantization table selector (0..3) */
+ /* These values may vary between scans. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOS marker. */
+ /* The decompressor output side may not use these variables. */
+ int dc_tbl_no; /* DC entropy table selector (0..3) */
+ int ac_tbl_no; /* AC entropy table selector (0..3) */
+
+ /* Remaining fields should be treated as private by applications. */
+
+ /* These values are computed during compression or decompression startup: */
+ /* Component's size in data units.
+ * Any dummy data units added to complete an MCU are not counted; therefore
+ * these values do not depend on whether a scan is interleaved or not.
+ */
+ JDIMENSION width_in_data_units;
+ JDIMENSION height_in_data_units;
+ /* Size of a data unit in/output by the codec (in samples). Always
+ * data_unit for compression. For decompression this is the size of the
+ * output from one data_unit, reflecting any processing performed by the
+ * codec. For example, in the DCT-based codec, scaling may be applied
+ * during the IDCT step. Values of 1,2,4,8 are likely to be supported.
+ * Note that different components may have different codec_data_unit sizes.
+ */
+ int codec_data_unit;
+ /* The downsampled dimensions are the component's actual, unpadded number
+ * of samples at the main buffer (preprocessing/compression interface), thus
+ * downsampled_width = ceil(image_width * Hi/Hmax)
+ * and similarly for height. For decompression, codec-based processing is
+ * included (ie, IDCT scaling), so
+ * downsampled_width = ceil(image_width * Hi/Hmax * codec_data_unit/data_unit)
+ */
+ JDIMENSION downsampled_width; /* actual width in samples */
+ JDIMENSION downsampled_height; /* actual height in samples */
+ /* This flag is used only for decompression. In cases where some of the
+ * components will be ignored (eg grayscale output from YCbCr image),
+ * we can skip most computations for the unused components.
+ */
+ boolean component_needed; /* do we need the value of this component? */
+
+ /* These values are computed before starting a scan of the component. */
+ /* The decompressor output side may not use these variables. */
+ int MCU_width; /* number of data units per MCU, horizontally */
+ int MCU_height; /* number of data units per MCU, vertically */
+ int MCU_data_units; /* MCU_width * MCU_height */
+ int MCU_sample_width; /* MCU width in samples, MCU_width*codec_data_unit */
+ int last_col_width; /* # of non-dummy data_units across in last MCU */
+ int last_row_height; /* # of non-dummy data_units down in last MCU */
+
+ /* Saved quantization table for component; NULL if none yet saved.
+ * See jdinput.c comments about the need for this information.
+ * This field is currently used only for decompression.
+ */
+ JQUANT_TBL * quant_table;
+
+ /* Private per-component storage for DCT or IDCT subsystem. */
+ void * dct_table;
+} jpeg_component_info;
+
+
+/* The script for encoding a multiple-scan file is an array of these: */
+
+typedef struct {
+ int comps_in_scan; /* number of components encoded in this scan */
+ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
+ int Ss, Se; /* progressive JPEG spectral selection parms
+ lossless JPEG predictor select parm (Ss) */
+ int Ah, Al; /* progressive JPEG successive approx. parms
+ lossless JPEG point transform parm (Al) */
+} jpeg_scan_info;
+
+/* The decompressor can save APPn and COM markers in a list of these: */
+
+typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
+
+struct jpeg_marker_struct {
+ jpeg_saved_marker_ptr next; /* next in list, or NULL */
+ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
+ unsigned int original_length; /* # bytes of data in the file */
+ unsigned int data_length; /* # bytes of data saved at data[] */
+ JOCTET FAR * data; /* the data contained in the marker */
+ /* the marker length word is not counted in data_length or original_length */
+};
+
+/* Known codec processes. */
+
+typedef enum {
+ JPROC_SEQUENTIAL, /* baseline/extended sequential DCT */
+ JPROC_PROGRESSIVE, /* progressive DCT */
+ JPROC_LOSSLESS /* lossless (sequential) */
+} J_CODEC_PROCESS;
+
+/* Known color spaces. */
+
+typedef enum {
+ JCS_UNKNOWN, /* error/unspecified */
+ JCS_GRAYSCALE, /* monochrome */
+ JCS_RGB, /* red/green/blue */
+ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
+ JCS_CMYK, /* C/M/Y/K */
+ JCS_YCCK /* Y/Cb/Cr/K */
+} J_COLOR_SPACE;
+
+/* DCT/IDCT algorithm options. */
+
+typedef enum {
+ JDCT_ISLOW, /* slow but accurate integer algorithm */
+ JDCT_IFAST, /* faster, less accurate integer method */
+ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
+} J_DCT_METHOD;
+
+#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
+#define JDCT_DEFAULT JDCT_ISLOW
+#endif
+#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
+#define JDCT_FASTEST JDCT_IFAST
+#endif
+
+/* Dithering options for decompression. */
+
+typedef enum {
+ JDITHER_NONE, /* no dithering */
+ JDITHER_ORDERED, /* simple ordered dither */
+ JDITHER_FS /* Floyd-Steinberg error diffusion dither */
+} J_DITHER_MODE;
+
+
+/* Common fields between JPEG compression and decompression master structs. */
+
+#define jpeg_common_fields \
+ struct jpeg_error_mgr * err; /* Error handler module */\
+ struct jpeg_memory_mgr * mem; /* Memory manager module */\
+ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
+ void * client_data; /* Available for use by application */\
+ boolean is_decompressor; /* So common code can tell which is which */\
+ int global_state /* For checking call sequence validity */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure. There are no actual instances of
+ * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
+ */
+struct jpeg_common_struct {
+ jpeg_common_fields; /* Fields common to both master struct types */
+ /* Additional fields follow in an actual jpeg_compress_struct or
+ * jpeg_decompress_struct. All three structs must agree on these
+ * initial fields! (This would be a lot cleaner in C++.)
+ */
+};
+
+typedef struct jpeg_common_struct * j_common_ptr;
+typedef struct jpeg_compress_struct * j_compress_ptr;
+typedef struct jpeg_decompress_struct * j_decompress_ptr;
+
+
+/* Master record for a compression instance */
+
+struct jpeg_compress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
+
+ /* Destination for compressed data */
+ struct jpeg_destination_mgr * dest;
+
+ /* Description of source image --- these fields must be filled in by
+ * outer application before starting compression. in_color_space must
+ * be correct before you can even call jpeg_set_defaults().
+ */
+
+ JDIMENSION image_width; /* input image width */
+ JDIMENSION image_height; /* input image height */
+ int input_components; /* # of color components in input image */
+ J_COLOR_SPACE in_color_space; /* colorspace of input image */
+
+ double input_gamma; /* image gamma of input image */
+
+ /* Compression parameters --- these fields must be set before calling
+ * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
+ * initialize everything to reasonable defaults, then changing anything
+ * the application specifically wants to change. That way you won't get
+ * burnt when new parameters are added. Also note that there are several
+ * helper routines to simplify changing parameters.
+ */
+
+ boolean lossless; /* TRUE=lossless encoding, FALSE=lossy */
+
+ int data_precision; /* bits of precision in image data */
+
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ int num_scans; /* # of entries in scan_info array */
+ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
+ /* The default value of scan_info is NULL, which causes a single-scan
+ * sequential JPEG file to be emitted. To create a multi-scan file,
+ * set num_scans and scan_info to point to an array of scan definitions.
+ */
+
+ boolean raw_data_in; /* TRUE=caller supplies downsampled data */
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+ int smoothing_factor; /* 1..100, or 0 for no input smoothing */
+ J_DCT_METHOD dct_method; /* DCT algorithm selector */
+
+ /* The restart interval can be specified in absolute MCUs by setting
+ * restart_interval, or in MCU rows by setting restart_in_rows
+ * (in which case the correct restart_interval will be figured
+ * for each scan).
+ */
+ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
+ int restart_in_rows; /* if > 0, MCU rows per restart interval */
+
+ /* Parameters controlling emission of special markers. */
+
+ boolean write_JFIF_header; /* should a JFIF marker be written? */
+ UINT8 JFIF_major_version; /* What to write for the JFIF version number */
+ UINT8 JFIF_minor_version;
+ /* These three values are not used by the JPEG code, merely copied */
+ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
+ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
+ /* ratio is defined by X_density/Y_density even when density_unit=0. */
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean write_Adobe_marker; /* should an Adobe marker be written? */
+
+ /* State variable: index of next scanline to be written to
+ * jpeg_write_scanlines(). Application may use this to control its
+ * processing loop, e.g., "while (next_scanline < image_height)".
+ */
+
+ JDIMENSION next_scanline; /* 0 .. image_height-1 */
+
+ /* Remaining fields are known throughout compressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during compression startup
+ */
+ int data_unit; /* size of data unit in samples */
+ J_CODEC_PROCESS process; /* encoding process of JPEG image */
+
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to codec */
+ /* The codec receives data in units of MCU rows as defined for fully
+ * interleaved scans (whether the JPEG file is interleaved or not).
+ * There are v_samp_factor * data_unit sample rows of each component in an
+ * "iMCU" (interleaved MCU) row.
+ */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int data_units_in_MCU; /* # of data units per MCU */
+ int MCU_membership[C_MAX_DATA_UNITS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th block in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive/lossless JPEG parameters for scan */
+
+ /*
+ * Links to compression subobjects (methods and private variables of modules)
+ */
+ struct jpeg_comp_master * master;
+ struct jpeg_c_main_controller * main;
+ struct jpeg_c_prep_controller * prep;
+ struct jpeg_c_codec * codec;
+ struct jpeg_marker_writer * marker;
+ struct jpeg_color_converter * cconvert;
+ struct jpeg_downsampler * downsample;
+ jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
+ int script_space_size;
+};
+
+
+/* Master record for a decompression instance */
+
+struct jpeg_decompress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
+
+ /* Source of compressed data */
+ struct jpeg_source_mgr * src;
+
+ /* Basic description of image --- filled in by jpeg_read_header(). */
+ /* Application may inspect these values to decide how to process image. */
+
+ JDIMENSION image_width; /* nominal image width (from SOF marker) */
+ JDIMENSION image_height; /* nominal image height */
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ /* Decompression processing parameters --- these fields must be set before
+ * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
+ * them to default values.
+ */
+
+ J_COLOR_SPACE out_color_space; /* colorspace for output */
+
+ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+ double output_gamma; /* image gamma wanted in output */
+
+ boolean buffered_image; /* TRUE=multiple output passes */
+ boolean raw_data_out; /* TRUE=downsampled data wanted */
+
+ J_DCT_METHOD dct_method; /* IDCT algorithm selector */
+ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
+ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
+
+ boolean quantize_colors; /* TRUE=colormapped output wanted */
+ /* the following are ignored if not quantize_colors: */
+ J_DITHER_MODE dither_mode; /* type of color dithering to use */
+ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
+ int desired_number_of_colors; /* max # colors to use in created colormap */
+ /* these are significant only in buffered-image mode: */
+ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
+ boolean enable_external_quant;/* enable future use of external colormap */
+ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
+
+ /* Description of actual output image that will be returned to application.
+ * These fields are computed by jpeg_start_decompress().
+ * You can also use jpeg_calc_output_dimensions() to determine these values
+ * in advance of calling jpeg_start_decompress().
+ */
+
+ JDIMENSION output_width; /* scaled image width */
+ JDIMENSION output_height; /* scaled image height */
+ int out_color_components; /* # of color components in out_color_space */
+ int output_components; /* # of color components returned */
+ /* output_components is 1 (a colormap index) when quantizing colors;
+ * otherwise it equals out_color_components.
+ */
+ int rec_outbuf_height; /* min recommended height of scanline buffer */
+ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+ * high, space and time will be wasted due to unnecessary data copying.
+ * Usually rec_outbuf_height will be 1 or 2, at most 4.
+ */
+
+ /* When quantizing colors, the output colormap is described by these fields.
+ * The application can supply a colormap by setting colormap non-NULL before
+ * calling jpeg_start_decompress; otherwise a colormap is created during
+ * jpeg_start_decompress or jpeg_start_output.
+ * The map has out_color_components rows and actual_number_of_colors columns.
+ */
+ int actual_number_of_colors; /* number of entries in use */
+ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */
+
+ /* State variables: these variables indicate the progress of decompression.
+ * The application may examine these but must not modify them.
+ */
+
+ /* Row index of next scanline to be read from jpeg_read_scanlines().
+ * Application may use this to control its processing loop, e.g.,
+ * "while (output_scanline < output_height)".
+ */
+ JDIMENSION output_scanline; /* 0 .. output_height-1 */
+
+ /* Current input scan number and number of iMCU rows completed in scan.
+ * These indicate the progress of the decompressor input side.
+ */
+ int input_scan_number; /* Number of SOS markers seen so far */
+ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
+
+ /* The "output scan number" is the notional scan being displayed by the
+ * output side. The decompressor will not allow output scan/row number
+ * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+ */
+ int output_scan_number; /* Nominal scan number being displayed */
+ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
+
+ /* Current progression status. coef_bits[c][i] indicates the precision
+ * with which component c's DCT coefficient i (in zigzag order) is known.
+ * It is -1 when no data has yet been received, otherwise it is the point
+ * transform (shift) value for the most recent scan of the coefficient
+ * (thus, 0 at completion of the progression).
+ * This pointer is NULL when reading a non-progressive file.
+ */
+ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
+
+ /* Internal JPEG parameters --- the application usually need not look at
+ * these fields. Note that the decompressor output side may not use
+ * any parameters that can change between scans.
+ */
+
+ /* Quantization and Huffman tables are carried forward across input
+ * datastreams when processing abbreviated JPEG datastreams.
+ */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ /* These parameters are never carried across datastreams, since they
+ * are given in SOF/SOS markers or defined to be reset by SOI.
+ */
+
+ int data_precision; /* bits of precision in image data */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+ /* These fields record data obtained from optional markers recognized by
+ * the JPEG library.
+ */
+ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
+ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
+ UINT8 JFIF_major_version; /* JFIF version number */
+ UINT8 JFIF_minor_version;
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
+ UINT8 Adobe_transform; /* Color transform code from Adobe marker */
+
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+
+ /* Aside from the specific data retained from APPn markers known to the
+ * library, the uninterpreted contents of any or all APPn and COM markers
+ * can be saved in a list for examination by the application.
+ */
+ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
+
+ /* Remaining fields are known throughout decompressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during decompression startup
+ */
+ int data_unit; /* size of data unit in samples */
+ J_CODEC_PROCESS process; /* decoding process of JPEG image */
+
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ int min_codec_data_unit; /* smallest codec_data_unit of any component */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
+ /* The codec's input and output progress is measured in units of "iMCU"
+ * (interleaved MCU) rows. These are the same as MCU rows in fully
+ * interleaved JPEG scans, but are used whether the scan is interleaved
+ * or not. We define an iMCU row as v_samp_factor data_unit rows of each
+ * component. Therefore, the codec output contains
+ * v_samp_factor*codec_data_unit sample rows of a component per iMCU row.
+ */
+
+ JSAMPLE * sample_range_limit; /* table for fast range-limiting */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ * Note that the decompressor output side must not use these fields.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int data_units_in_MCU; /* # of data _units per MCU */
+ int MCU_membership[D_MAX_DATA_UNITS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th data unit in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive/lossless JPEG parms for scan */
+
+ /* This field is shared between entropy decoder and marker parser.
+ * It is either zero or the code of a JPEG marker that has been
+ * read from the data source, but has not yet been processed.
+ */
+ int unread_marker;
+
+ /*
+ * Links to decompression subobjects (methods, private variables of modules)
+ */
+ struct jpeg_decomp_master * master;
+ struct jpeg_d_main_controller * main;
+ struct jpeg_d_codec * codec;
+ struct jpeg_d_post_controller * post;
+ struct jpeg_input_controller * inputctl;
+ struct jpeg_marker_reader * marker;
+ struct jpeg_upsampler * upsample;
+ struct jpeg_color_deconverter * cconvert;
+ struct jpeg_color_quantizer * cquantize;
+};
+
+
+/* "Object" declarations for JPEG modules that may be supplied or called
+ * directly by the surrounding application.
+ * As with all objects in the JPEG library, these structs only define the
+ * publicly visible methods and state variables of a module. Additional
+ * private fields may exist after the public ones.
+ */
+
+
+/* Error handler object */
+
+struct jpeg_error_mgr {
+ /* Error exit handler: does not return to caller */
+ JMETHOD(void, error_exit, (j_common_ptr cinfo));
+ /* Conditionally emit a trace or warning message */
+ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
+ /* Routine that actually outputs a trace or error message */
+ JMETHOD(void, output_message, (j_common_ptr cinfo));
+ /* Format a message string for the most recent JPEG error or message */
+ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
+#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
+ /* Reset error state variables at start of a new image */
+ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
+
+ /* The message ID code and any parameters are saved here.
+ * A message can have one string parameter or up to 8 int parameters.
+ */
+ int msg_code;
+#define JMSG_STR_PARM_MAX 80
+ union {
+ int i[8];
+ char s[JMSG_STR_PARM_MAX];
+ } msg_parm;
+
+ /* Standard state variables for error facility */
+
+ int trace_level; /* max msg_level that will be displayed */
+
+ /* For recoverable corrupt-data errors, we emit a warning message,
+ * but keep going unless emit_message chooses to abort. emit_message
+ * should count warnings in num_warnings. The surrounding application
+ * can check for bad data by seeing if num_warnings is nonzero at the
+ * end of processing.
+ */
+ long num_warnings; /* number of corrupt-data warnings */
+
+ /* These fields point to the table(s) of error message strings.
+ * An application can change the table pointer to switch to a different
+ * message list (typically, to change the language in which errors are
+ * reported). Some applications may wish to add additional error codes
+ * that will be handled by the JPEG library error mechanism; the second
+ * table pointer is used for this purpose.
+ *
+ * First table includes all errors generated by JPEG library itself.
+ * Error code 0 is reserved for a "no such error string" message.
+ */
+ const char * const * jpeg_message_table; /* Library errors */
+ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
+ /* Second table can be added by application (see cjpeg/djpeg for example).
+ * It contains strings numbered first_addon_message..last_addon_message.
+ */
+ const char * const * addon_message_table; /* Non-library errors */
+ int first_addon_message; /* code for first string in addon table */
+ int last_addon_message; /* code for last string in addon table */
+};
+
+
+/* Progress monitor object */
+
+struct jpeg_progress_mgr {
+ JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
+
+ long pass_counter; /* work units completed in this pass */
+ long pass_limit; /* total number of work units in this pass */
+ int completed_passes; /* passes completed so far */
+ int total_passes; /* total number of passes expected */
+};
+
+
+/* Data destination object for compression */
+
+struct jpeg_destination_mgr {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+
+ JMETHOD(void, init_destination, (j_compress_ptr cinfo));
+ JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
+ JMETHOD(void, term_destination, (j_compress_ptr cinfo));
+};
+
+
+/* Data source object for decompression */
+
+struct jpeg_source_mgr {
+ const JOCTET * next_input_byte; /* => next byte to read from buffer */
+ size_t bytes_in_buffer; /* # of bytes remaining in buffer */
+
+ JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+ JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+ JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+ JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+
+
+/* Memory manager object.
+ * Allocates "small" objects (a few K total), "large" objects (tens of K),
+ * and "really big" objects (virtual arrays with backing store if needed).
+ * The memory manager does not allow individual objects to be freed; rather,
+ * each created object is assigned to a pool, and whole pools can be freed
+ * at once. This is faster and more convenient than remembering exactly what
+ * to free, especially where malloc()/free() are not too speedy.
+ * NB: alloc routines never return NULL. They exit to error_exit if not
+ * successful.
+ */
+
+#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
+#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS 2
+
+typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
+typedef struct jvirt_barray_control * jvirt_barray_ptr;
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+#define NEED_DARRAY
+#else
+#ifdef D_LOSSLESS_SUPPORTED
+#define NEED_DARRAY
+#endif
+#endif
+
+struct jpeg_memory_mgr {
+ /* Method pointers */
+ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows));
+ JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows));
+#ifdef NEED_DARRAY
+ JMETHOD(JDIFFARRAY, alloc_darray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION diffsperrow,
+ JDIMENSION numrows));
+#endif
+ JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
+ JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
+ jvirt_sarray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
+ jvirt_barray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
+ JMETHOD(void, self_destruct, (j_common_ptr cinfo));
+
+ /* Limit on memory allocation for this JPEG object. (Note that this is
+ * merely advisory, not a guaranteed maximum; it only affects the space
+ * used for virtual-array buffers.) May be changed by outer application
+ * after creating the JPEG object.
+ */
+ long max_memory_to_use;
+
+ /* Maximum allocation request accepted by alloc_large. */
+ long max_alloc_chunk;
+};
+
+
+/* Routine signature for application-supplied marker processing methods.
+ * Need not pass marker code since it is stored in cinfo->unread_marker.
+ */
+typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
+
+
+/* Declarations for routines called by application.
+ * The JPP macro hides prototype parameters from compilers that can't cope.
+ * Note JPP requires double parentheses.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JPP(arglist) arglist
+#else
+#define JPP(arglist) ()
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers.
+ * We shorten external names to be unique in the first six letters, which
+ * is good enough for all known systems.
+ * (If your compiler itself needs names to be unique in less than 15
+ * characters, you are out of luck. Get a better compiler.)
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_error jStdError
+#define jpeg_CreateCompress jCreaCompress
+#define jpeg_CreateDecompress jCreaDecompress
+#define jpeg_destroy_compress jDestCompress
+#define jpeg_destroy_decompress jDestDecompress
+#define jpeg_stdio_dest jStdDest
+#define jpeg_stdio_src jStdSrc
+#define jpeg_set_defaults jSetDefaults
+#define jpeg_set_colorspace jSetColorspace
+#define jpeg_default_colorspace jDefColorspace
+#define jpeg_set_quality jSetQuality
+#define jpeg_set_linear_quality jSetLQuality
+#define jpeg_add_quant_table jAddQuantTable
+#define jpeg_quality_scaling jQualityScaling
+#define jpeg_simple_lossless jSimLossless
+#define jpeg_simple_progression jSimProgress
+#define jpeg_suppress_tables jSuppressTables
+#define jpeg_alloc_quant_table jAlcQTable
+#define jpeg_alloc_huff_table jAlcHTable
+#define jpeg_start_compress jStrtCompress
+#define jpeg_write_scanlines jWrtScanlines
+#define jpeg_finish_compress jFinCompress
+#define jpeg_write_raw_data jWrtRawData
+#define jpeg_write_marker jWrtMarker
+#define jpeg_write_m_header jWrtMHeader
+#define jpeg_write_m_byte jWrtMByte
+#define jpeg_write_tables jWrtTables
+#define jpeg_read_header jReadHeader
+#define jpeg_start_decompress jStrtDecompress
+#define jpeg_read_scanlines jReadScanlines
+#define jpeg_finish_decompress jFinDecompress
+#define jpeg_read_raw_data jReadRawData
+#define jpeg_has_multiple_scans jHasMultScn
+#define jpeg_start_output jStrtOutput
+#define jpeg_finish_output jFinOutput
+#define jpeg_input_complete jInComplete
+#define jpeg_new_colormap jNewCMap
+#define jpeg_consume_input jConsumeInput
+#define jpeg_calc_output_dimensions jCalcDimensions
+#define jpeg_save_markers jSaveMarkers
+#define jpeg_set_marker_processor jSetMarker
+#define jpeg_read_coefficients jReadCoefs
+#define jpeg_write_coefficients jWrtCoefs
+#define jpeg_copy_critical_parameters jCopyCrit
+#define jpeg_abort_compress jAbrtCompress
+#define jpeg_abort_decompress jAbrtDecompress
+#define jpeg_abort jAbort
+#define jpeg_destroy jDestroy
+#define jpeg_resync_to_restart jResyncRestart
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Default error-management setup */
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error
+ JPP((struct jpeg_error_mgr * err));
+
+/* Initialization of JPEG compression objects.
+ * jpeg_create_compress() and jpeg_create_decompress() are the exported
+ * names that applications should call. These expand to calls on
+ * jpeg_CreateCompress and jpeg_CreateDecompress with additional information
+ * passed for version mismatch checking.
+ * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
+ */
+#define jpeg_create_compress(cinfo) \
+ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_compress_struct))
+#define jpeg_create_decompress(cinfo) \
+ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
+ int version, size_t structsize));
+EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
+ int version, size_t structsize));
+/* Destruction of JPEG compression objects */
+EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
+
+/* Standard data source and destination managers: stdio streams. */
+/* Caller is responsible for opening the file before and closing after. */
+EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
+EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* Default parameter setup for compression */
+EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
+/* Compression parameter setup aids */
+EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
+ J_COLOR_SPACE colorspace));
+EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
+ boolean force_baseline));
+EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(int) jpeg_quality_scaling JPP((int quality));
+EXTERN(void) jpeg_simple_lossless JPP((j_compress_ptr cinfo,
+ int predictor, int point_transform));
+EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
+ boolean suppress));
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
+
+/* Main entry points for compression */
+EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
+ boolean write_all_tables));
+EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION num_lines));
+EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
+
+/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION num_lines));
+
+/* Write a special marker. See libjpeg.doc concerning safe usage. */
+EXTERN(void) jpeg_write_marker
+ JPP((j_compress_ptr cinfo, int marker,
+ const JOCTET * dataptr, unsigned int datalen));
+/* Same, but piecemeal. */
+EXTERN(void) jpeg_write_m_header
+ JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
+EXTERN(void) jpeg_write_m_byte
+ JPP((j_compress_ptr cinfo, int val));
+
+/* Alternate compression function: just write an abbreviated table file */
+EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
+
+/* Decompression startup: read start of JPEG datastream to see what's there */
+EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
+ boolean require_image));
+/* Return value is one of: */
+#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK 1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
+/* If you pass require_image = TRUE (normal case), you need not check for
+ * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
+ * JPEG_SUSPENDED is only possible if you use a data source module that can
+ * give a suspension return (the stdio source module doesn't).
+ */
+
+/* Main entry points for decompression */
+EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION max_lines));
+EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
+
+/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION max_lines));
+
+/* Additional entry points for buffered-image mode. */
+EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
+ int scan_number));
+EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
+EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
+/* Return value is one of: */
+/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
+#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
+#define JPEG_REACHED_EOI 2 /* Reached end of image */
+#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
+#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
+
+/* Precalculate output dimensions for current decompression parameters. */
+EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
+
+/* Control saving of COM and APPn markers into marker_list. */
+EXTERN(void) jpeg_save_markers
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit));
+
+/* Install a special processing method for COM or APPn markers. */
+EXTERN(void) jpeg_set_marker_processor
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine));
+
+/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays));
+EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo));
+
+/* If you choose to abort compression or decompression before completing
+ * jpeg_finish_(de)compress, then you need to clean up to release memory,
+ * temporary files, etc. You can just call jpeg_destroy_(de)compress
+ * if you're done with the JPEG object, but if you want to clean it up and
+ * reuse it, call this:
+ */
+EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
+
+/* Generic versions of jpeg_abort and jpeg_destroy that work on either
+ * flavor of JPEG object. These may be more convenient in some places.
+ */
+EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
+
+/* Default restart-marker-resync procedure for use by data source modules */
+EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
+ int desired));
+
+
+/* These marker codes are exported since applications and data source modules
+ * are likely to want to use them.
+ */
+
+#define JPEG_RST0 0xD0 /* RST0 marker code */
+#define JPEG_EOI 0xD9 /* EOI marker code */
+#define JPEG_APP0 0xE0 /* APP0 marker code */
+#define JPEG_COM 0xFE /* COM marker code */
+
+
+/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
+ * for structure definitions that are never filled in, keep it quiet by
+ * supplying dummy definitions for the various substructures.
+ */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+struct jpeg_comp_master { long dummy; };
+struct jpeg_c_main_controller { long dummy; };
+struct jpeg_c_prep_controller { long dummy; };
+struct jpeg_c_coef_controller { long dummy; };
+struct jpeg_marker_writer { long dummy; };
+struct jpeg_color_converter { long dummy; };
+struct jpeg_downsampler { long dummy; };
+struct jpeg_forward_dct { long dummy; };
+struct jpeg_entropy_encoder { long dummy; };
+struct jpeg_decomp_master { long dummy; };
+struct jpeg_d_main_controller { long dummy; };
+struct jpeg_d_coef_controller { long dummy; };
+struct jpeg_d_post_controller { long dummy; };
+struct jpeg_input_controller { long dummy; };
+struct jpeg_marker_reader { long dummy; };
+struct jpeg_entropy_decoder { long dummy; };
+struct jpeg_inverse_dct { long dummy; };
+struct jpeg_upsampler { long dummy; };
+struct jpeg_color_deconverter { long dummy; };
+struct jpeg_color_quantizer { long dummy; };
+#endif /* JPEG_INTERNALS */
+#endif /* INCOMPLETE_TYPES_BROKEN */
+
+
+/*
+ * The JPEG library modules define JPEG_INTERNALS before including this file.
+ * The internal structure declarations are read only when that is true.
+ * Applications using the library should not include jpegint.h, but may wish
+ * to include jerror.h.
+ */
+
+#ifdef JPEG_INTERNALS
+//#include "jpegint.h" /* fetch private declarations */
+//#include "jerror.h" /* fetch error codes too */
+#endif
+
+#endif /* JPEGLIB_H */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant1.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant1.cpp
new file mode 100644
index 00000000..df19434f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant1.cpp
@@ -0,0 +1,857 @@
+/*
+ * jquant1.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 1-pass color quantization (color mapping) routines.
+ * These routines provide mapping to a fixed color map using equally spaced
+ * color values. Optional Floyd-Steinberg or ordered dithering is available.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#ifdef QUANT_1PASS_SUPPORTED
+
+
+/*
+ * The main purpose of 1-pass quantization is to provide a fast, if not very
+ * high quality, colormapped output capability. A 2-pass quantizer usually
+ * gives better visual quality; however, for quantized grayscale output this
+ * quantizer is perfectly adequate. Dithering is highly recommended with this
+ * quantizer, though you can turn it off if you really want to.
+ *
+ * In 1-pass quantization the colormap must be chosen in advance of seeing the
+ * image. We use a map consisting of all combinations of Ncolors[i] color
+ * values for the i'th component. The Ncolors[] values are chosen so that
+ * their product, the total number of colors, is no more than that requested.
+ * (In most cases, the product will be somewhat less.)
+ *
+ * Since the colormap is orthogonal, the representative value for each color
+ * component can be determined without considering the other components;
+ * then these indexes can be combined into a colormap index by a standard
+ * N-dimensional-array-subscript calculation. Most of the arithmetic involved
+ * can be precalculated and stored in the lookup table colorindex[].
+ * colorindex[i][j] maps pixel value j in component i to the nearest
+ * representative value (grid plane) for that component; this index is
+ * multiplied by the array stride for component i, so that the
+ * index of the colormap entry closest to a given pixel value is just
+ * sum( colorindex[component-number][pixel-component-value] )
+ * Aside from being fast, this scheme allows for variable spacing between
+ * representative values with no additional lookup cost.
+ *
+ * If gamma correction has been applied in color conversion, it might be wise
+ * to adjust the color grid spacing so that the representative colors are
+ * equidistant in linear space. At this writing, gamma correction is not
+ * implemented by jdcolor, so nothing is done here.
+ */
+
+
+/* Declarations for ordered dithering.
+ *
+ * We use a standard 16x16 ordered dither array. The basic concept of ordered
+ * dithering is described in many references, for instance Dale Schumacher's
+ * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
+ * In place of Schumacher's comparisons against a "threshold" value, we add a
+ * "dither" value to the input pixel and then round the result to the nearest
+ * output value. The dither value is equivalent to (0.5 - threshold) times
+ * the distance between output values. For ordered dithering, we assume that
+ * the output colors are equally spaced; if not, results will probably be
+ * worse, since the dither may be too much or too little at a given point.
+ *
+ * The normal calculation would be to form pixel value + dither, range-limit
+ * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
+ * We can skip the separate range-limiting step by extending the colorindex
+ * table in both directions.
+ */
+
+#define ODITHER_SIZE 16 /* dimension of dither matrix */
+/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
+#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */
+#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */
+
+typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
+typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
+
+static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
+ /* Bayer's order-4 dither array. Generated by the code given in
+ * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
+ * The values in this array must range from 0 to ODITHER_CELLS-1.
+ */
+ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
+ { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
+ { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
+ { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
+ { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
+ { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
+ { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
+ { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
+ { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
+ { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
+ { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
+ { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
+ { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
+ { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
+ { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
+ { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
+};
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array is indexed [component#][position].
+ * We provide (#columns + 2) entries per component; the extra entry at each
+ * end saves us from special-casing the first and last pixels.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+#define MAX_Q_COMPS 4 /* max components I can handle */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Initially allocated colormap is saved here */
+ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */
+ int sv_actual; /* number of entries in use */
+
+ JSAMPARRAY colorindex; /* Precomputed mapping for speed */
+ /* colorindex[i][j] = index of color closest to pixel value j in component i,
+ * premultiplied as described above. Since colormap indexes must fit into
+ * JSAMPLEs, the entries of this array will too.
+ */
+ boolean is_padded; /* is the colorindex padded for odither? */
+
+ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
+
+ /* Variables for ordered dithering */
+ int row_index; /* cur row's vertical index in dither matrix */
+ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Policy-making subroutines for create_colormap and create_colorindex.
+ * These routines determine the colormap to be used. The rest of the module
+ * only assumes that the colormap is orthogonal.
+ *
+ * * select_ncolors decides how to divvy up the available colors
+ * among the components.
+ * * output_value defines the set of representative values for a component.
+ * * largest_input_value defines the mapping from input values to
+ * representative values for a component.
+ * Note that the latter two routines may impose different policies for
+ * different components, though this is not currently done.
+ */
+
+
+LOCAL(int)
+select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+/* Determine allocation of desired colors to components, */
+/* and fill in Ncolors[] array to indicate choice. */
+/* Return value is total number of colors (product of Ncolors[] values). */
+{
+ int nc = cinfo->out_color_components; /* number of color components */
+ int max_colors = cinfo->desired_number_of_colors;
+ int total_colors, iroot, i, j;
+ boolean changed;
+ long temp;
+ static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
+
+ /* We can allocate at least the nc'th root of max_colors per component. */
+ /* Compute floor(nc'th root of max_colors). */
+ iroot = 1;
+ do {
+ iroot++;
+ temp = iroot; /* set temp = iroot ** nc */
+ for (i = 1; i < nc; i++)
+ temp *= iroot;
+ } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+ iroot--; /* now iroot = floor(root) */
+
+ /* Must have at least 2 color values per component */
+ if (iroot < 2)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+
+ /* Initialize to iroot color values for each component */
+ total_colors = 1;
+ for (i = 0; i < nc; i++) {
+ Ncolors[i] = iroot;
+ total_colors *= iroot;
+ }
+ /* We may be able to increment the count for one or more components without
+ * exceeding max_colors, though we know not all can be incremented.
+ * Sometimes, the first component can be incremented more than once!
+ * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
+ * In RGB colorspace, try to increment G first, then R, then B.
+ */
+ do {
+ changed = FALSE;
+ for (i = 0; i < nc; i++) {
+ j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
+ /* calculate new total_colors if Ncolors[j] is incremented */
+ temp = total_colors / Ncolors[j];
+ temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
+ if (temp > (long) max_colors)
+ break; /* won't fit, done with this pass */
+ Ncolors[j]++; /* OK, apply the increment */
+ total_colors = (int) temp;
+ changed = TRUE;
+ }
+ } while (changed);
+
+ return total_colors;
+}
+
+
+LOCAL(int)
+output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return j'th output value, where j will range from 0 to maxj */
+/* The output values must fall in 0..MAXJSAMPLE in increasing order */
+{
+ /* We always provide values 0 and MAXJSAMPLE for each component;
+ * any additional values are equally spaced between these limits.
+ * (Forcing the upper and lower values to the limits ensures that
+ * dithering can't produce a color outside the selected gamut.)
+ */
+ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
+}
+
+
+LOCAL(int)
+largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return largest input value that should map to j'th output value */
+/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
+{
+ /* Breakpoints are halfway between values returned by output_value */
+ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+}
+
+
+/*
+ * Create the colormap.
+ */
+
+LOCAL(void)
+create_colormap (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colormap; /* Created colormap */
+ int total_colors; /* Number of distinct output colors */
+ int i,j,k, nci, blksize, blkdist, ptr, val;
+
+ /* Select number of colors for each component */
+ total_colors = select_ncolors(cinfo, cquantize->Ncolors);
+
+ /* Report selected color counts */
+ if (cinfo->out_color_components == 3)
+ TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
+ total_colors, cquantize->Ncolors[0],
+ cquantize->Ncolors[1], cquantize->Ncolors[2]);
+ else
+ TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
+
+ /* Allocate and fill in the colormap. */
+ /* The colors are ordered in the map in standard row-major order, */
+ /* i.e. rightmost (highest-indexed) color changes most rapidly. */
+
+ colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ /* blkdist is distance between groups of identical entries for a component */
+ blkdist = total_colors;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colormap entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blkdist / nci;
+ for (j = 0; j < nci; j++) {
+ /* Compute j'th output value (out of nci) for component */
+ val = output_value(cinfo, i, j, nci-1);
+ /* Fill in all colormap entries that have this value of this component */
+ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
+ /* fill in blksize entries beginning at ptr */
+ for (k = 0; k < blksize; k++)
+ colormap[i][ptr+k] = (JSAMPLE) val;
+ }
+ }
+ blkdist = blksize; /* blksize of this color is blkdist of next */
+ }
+
+ /* Save the colormap in private storage,
+ * where it will survive color quantization mode changes.
+ */
+ cquantize->sv_colormap = colormap;
+ cquantize->sv_actual = total_colors;
+}
+
+
+/*
+ * Create the color index table.
+ */
+
+LOCAL(void)
+create_colorindex (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPROW indexptr;
+ int i,j,k, nci, blksize, val, pad;
+
+ /* For ordered dither, we pad the color index tables by MAXJSAMPLE in
+ * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
+ * This is not necessary in the other dithering modes. However, we
+ * flag whether it was done in case user changes dithering mode.
+ */
+ if (cinfo->dither_mode == JDITHER_ORDERED) {
+ pad = MAXJSAMPLE*2;
+ cquantize->is_padded = TRUE;
+ } else {
+ pad = 0;
+ cquantize->is_padded = FALSE;
+ }
+
+ cquantize->colorindex = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (MAXJSAMPLE+1 + pad),
+ (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ blksize = cquantize->sv_actual;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colorindex entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blksize / nci;
+
+ /* adjust colorindex pointers to provide padding at negative indexes. */
+ if (pad)
+ cquantize->colorindex[i] += MAXJSAMPLE;
+
+ /* in loop, val = index of current output value, */
+ /* and k = largest j that maps to current val */
+ indexptr = cquantize->colorindex[i];
+ val = 0;
+ k = largest_input_value(cinfo, i, 0, nci-1);
+ for (j = 0; j <= MAXJSAMPLE; j++) {
+ while (j > k) /* advance val if past boundary */
+ k = largest_input_value(cinfo, i, ++val, nci-1);
+ /* premultiply so that no multiplication needed in main processing */
+ indexptr[j] = (JSAMPLE) (val * blksize);
+ }
+ /* Pad at both ends if necessary */
+ if (pad)
+ for (j = 1; j <= MAXJSAMPLE; j++) {
+ indexptr[-j] = indexptr[0];
+ indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+ }
+ }
+}
+
+
+/*
+ * Create an ordered-dither array for a component having ncolors
+ * distinct output values.
+ */
+
+LOCAL(ODITHER_MATRIX_PTR)
+make_odither_array (j_decompress_ptr cinfo, int ncolors)
+{
+ ODITHER_MATRIX_PTR odither;
+ int j,k;
+ INT32 num,den;
+
+ odither = (ODITHER_MATRIX_PTR)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ODITHER_MATRIX));
+ /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
+ * Hence the dither value for the matrix cell with fill order f
+ * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
+ * On 16-bit-int machine, be careful to avoid overflow.
+ */
+ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
+ for (j = 0; j < ODITHER_SIZE; j++) {
+ for (k = 0; k < ODITHER_SIZE; k++) {
+ num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
+ * MAXJSAMPLE;
+ /* Ensure round towards zero despite C's lack of consistency
+ * about rounding negative values in integer division...
+ */
+ odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+ }
+ }
+ return odither;
+}
+
+
+/*
+ * Create the ordered-dither tables.
+ * Components having the same number of representative colors may
+ * share a dither table.
+ */
+
+LOCAL(void)
+create_odither_tables (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ ODITHER_MATRIX_PTR odither;
+ int i, j, nci;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ odither = NULL; /* search for matching prior component */
+ for (j = 0; j < i; j++) {
+ if (nci == cquantize->Ncolors[j]) {
+ odither = cquantize->odither[j];
+ break;
+ }
+ }
+ if (odither == NULL) /* need a new table? */
+ odither = make_odither_array(cinfo, nci);
+ cquantize->odither[i] = odither;
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colorindex = cquantize->colorindex;
+ register int pixcode, ci;
+ register JSAMPROW ptrin, ptrout;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ register int nc = cinfo->out_color_components;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = 0;
+ for (ci = 0; ci < nc; ci++) {
+ pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
+ }
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW ptrin, ptrout;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ int * dither; /* points to active row of dither matrix */
+ int row_index, col_index; /* current indexes into dither matrix */
+ int nc = cinfo->out_color_components;
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ row_index = cquantize->row_index;
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ colorindex_ci = cquantize->colorindex[ci];
+ dither = cquantize->odither[ci][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
+ * select output value, accumulate into output code for this pixel.
+ * Range-limiting need not be done explicitly, as we have extended
+ * the colorindex table to produce the right answers for out-of-range
+ * inputs. The maximum dither is +- MAXJSAMPLE; this sets the
+ * required amount of padding.
+ */
+ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+ input_ptr += nc;
+ output_ptr++;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ }
+ /* Advance row index for next row */
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int * dither0; /* points to active row of dither matrix */
+ int * dither1;
+ int * dither2;
+ int row_index, col_index; /* current indexes into dither matrix */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ row_index = cquantize->row_index;
+ input_ptr = input_buf[row];
+ output_ptr = output_buf[row];
+ dither0 = cquantize->odither[0][row_index];
+ dither1 = cquantize->odither[1][row_index];
+ dither2 = cquantize->odither[2][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
+ dither0[col_index]]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
+ dither1[col_index]]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
+ dither2[col_index]]);
+ *output_ptr++ = (JSAMPLE) pixcode;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register LOCFSERROR cur; /* current error or pixel value */
+ LOCFSERROR belowerr; /* error for pixel below cur */
+ LOCFSERROR bpreverr; /* error for below/prev col */
+ LOCFSERROR bnexterr; /* error for below/next col */
+ LOCFSERROR delta;
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ JSAMPROW colormap_ci;
+ int pixcode;
+ int nc = cinfo->out_color_components;
+ int dir; /* 1 for left-to-right, -1 for right-to-left */
+ int dirnc; /* dir * nc */
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ input_ptr += (width-1) * nc; /* so point to rightmost pixel */
+ output_ptr += width-1;
+ dir = -1;
+ dirnc = -nc;
+ errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dirnc = nc;
+ errorptr = cquantize->fserrors[ci]; /* => entry before first column */
+ }
+ colorindex_ci = cquantize->colorindex[ci];
+ colormap_ci = cquantize->sv_colormap[ci];
+ /* Preset error values: no error propagated to first pixel from left */
+ cur = 0;
+ /* and no error propagated to row below yet */
+ belowerr = bpreverr = 0;
+
+ for (col = width; col > 0; col--) {
+ /* cur holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE; this sets the required size
+ * of the range_limit array.
+ */
+ cur += GETJSAMPLE(*input_ptr);
+ cur = GETJSAMPLE(range_limit[cur]);
+ /* Select output value, accumulate into output code for this pixel */
+ pixcode = GETJSAMPLE(colorindex_ci[cur]);
+ *output_ptr += (JSAMPLE) pixcode;
+ /* Compute actual representation error at this pixel */
+ /* Note: we can do this even though we don't have the final */
+ /* pixel code, because the colormap is orthogonal. */
+ cur -= GETJSAMPLE(colormap_ci[pixcode]);
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ bnexterr = cur;
+ delta = cur * 2;
+ cur += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr + cur);
+ cur += delta; /* form error * 5 */
+ bpreverr = belowerr + cur;
+ belowerr = bnexterr;
+ cur += delta; /* form error * 7 */
+ /* At this point cur contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ input_ptr += dirnc; /* advance input ptr to next column */
+ output_ptr += dir; /* advance output ptr to next column */
+ errorptr += dir; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error value into the
+ * final fserrors[] entry. Note we need not unload belowerr because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+ }
+ cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
+ }
+}
+
+
+/*
+ * Allocate workspace for Floyd-Steinberg errors.
+ */
+
+LOCAL(void)
+alloc_fs_workspace (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ cquantize->fserrors[i] = (FSERRPTR)
+ (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ }
+}
+
+
+/*
+ * Initialize for one-pass color quantization.
+ */
+
+METHODDEF(void)
+start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ /* Install my colormap. */
+ cinfo->colormap = cquantize->sv_colormap;
+ cinfo->actual_number_of_colors = cquantize->sv_actual;
+
+ /* Initialize for desired dithering mode. */
+ switch (cinfo->dither_mode) {
+ case JDITHER_NONE:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = color_quantize3;
+ else
+ cquantize->pub.color_quantize = color_quantize;
+ break;
+ case JDITHER_ORDERED:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = quantize3_ord_dither;
+ else
+ cquantize->pub.color_quantize = quantize_ord_dither;
+ cquantize->row_index = 0; /* initialize state for ordered dither */
+ /* If user changed to ordered dither from another mode,
+ * we must recreate the color index table with padding.
+ * This will cost extra space, but probably isn't very likely.
+ */
+ if (! cquantize->is_padded)
+ create_colorindex(cinfo);
+ /* Create ordered-dither tables if we didn't already. */
+ if (cquantize->odither[0] == NULL)
+ create_odither_tables(cinfo);
+ break;
+ case JDITHER_FS:
+ cquantize->pub.color_quantize = quantize_fs_dither;
+ cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
+ /* Allocate Floyd-Steinberg workspace if didn't already. */
+ if (cquantize->fserrors[0] == NULL)
+ alloc_fs_workspace(cinfo);
+ /* Initialize the propagated errors to zero. */
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++)
+ jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+}
+
+
+/*
+ * Finish up at the end of the pass.
+ */
+
+METHODDEF(void)
+finish_pass_1_quant (j_decompress_ptr cinfo)
+{
+ /* no work in 1-pass case */
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ * Shouldn't get to this module!
+ */
+
+METHODDEF(void)
+new_color_map_1_quant (j_decompress_ptr cinfo)
+{
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+
+/*
+ * Module initialization routine for 1-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_1pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_1_quant;
+ cquantize->pub.finish_pass = finish_pass_1_quant;
+ cquantize->pub.new_color_map = new_color_map_1_quant;
+ cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
+ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */
+
+ /* Make sure my internal arrays won't overflow */
+ if (cinfo->out_color_components > MAX_Q_COMPS)
+ ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+
+ /* Create the colormap and color index table. */
+ create_colormap(cinfo);
+ create_colorindex(cinfo);
+
+ /* Allocate Floyd-Steinberg workspace now if requested.
+ * We do this now since it is FAR storage and may affect the memory
+ * manager's space calculations. If the user changes to FS dither
+ * mode in a later pass, we will allocate the space then, and will
+ * possibly overrun the max_memory_to_use setting.
+ */
+ if (cinfo->dither_mode == JDITHER_FS)
+ alloc_fs_workspace(cinfo);
+}
+
+#endif /* QUANT_1PASS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant2.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant2.cpp
new file mode 100644
index 00000000..ec5e11ed
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jquant2.cpp
@@ -0,0 +1,1311 @@
+/*
+ * jquant2.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 2-pass color quantization (color mapping) routines.
+ * These routines provide selection of a custom color map for an image,
+ * followed by mapping of the image to that color map, with optional
+ * Floyd-Steinberg dithering.
+ * It is also possible to use just the second pass to map to an arbitrary
+ * externally-given color map.
+ *
+ * Note: ordered dithering is not supported, since there isn't any fast
+ * way to compute intercolor distances; it's unclear that ordered dither's
+ * fundamental assumptions even hold with an irregularly spaced color map.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
+/*
+ * This module implements the well-known Heckbert paradigm for color
+ * quantization. Most of the ideas used here can be traced back to
+ * Heckbert's seminal paper
+ * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display",
+ * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
+ *
+ * In the first pass over the image, we accumulate a histogram showing the
+ * usage count of each possible color. To keep the histogram to a reasonable
+ * size, we reduce the precision of the input; typical practice is to retain
+ * 5 or 6 bits per color, so that 8 or 4 different input values are counted
+ * in the same histogram cell.
+ *
+ * Next, the color-selection step begins with a box representing the whole
+ * color space, and repeatedly splits the "largest" remaining box until we
+ * have as many boxes as desired colors. Then the mean color in each
+ * remaining box becomes one of the possible output colors.
+ *
+ * The second pass over the image maps each input pixel to the closest output
+ * color (optionally after applying a Floyd-Steinberg dithering correction).
+ * This mapping is logically trivial, but making it go fast enough requires
+ * considerable care.
+ *
+ * Heckbert-style quantizers vary a good deal in their policies for choosing
+ * the "largest" box and deciding where to cut it. The particular policies
+ * used here have proved out well in experimental comparisons, but better ones
+ * may yet be found.
+ *
+ * In earlier versions of the IJG code, this module quantized in YCbCr color
+ * space, processing the raw upsampled data without a color conversion step.
+ * This allowed the color conversion math to be done only once per colormap
+ * entry, not once per pixel. However, that optimization precluded other
+ * useful optimizations (such as merging color conversion with upsampling)
+ * and it also interfered with desired capabilities such as quantizing to an
+ * externally-supplied colormap. We have therefore abandoned that approach.
+ * The present code works in the post-conversion color space, typically RGB.
+ *
+ * To improve the visual quality of the results, we actually work in scaled
+ * RGB space, giving G distances more weight than R, and R in turn more than
+ * B. To do everything in integer math, we must use integer scale factors.
+ * The 2/3/1 scale factors used here correspond loosely to the relative
+ * weights of the colors in the NTSC grayscale equation.
+ * If you want to use this code to quantize a non-RGB color space, you'll
+ * probably need to change these scale factors.
+ */
+
+#define R_SCALE 2 /* scale R distances by this much */
+#define G_SCALE 3 /* scale G distances by this much */
+#define B_SCALE 1 /* and B by this much */
+
+/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
+ * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B
+ * and B,G,R orders. If you define some other weird order in jmorecfg.h,
+ * you'll get compile errors until you extend this logic. In that case
+ * you'll probably want to tweak the histogram sizes too.
+ */
+
+#if RGB_RED == 0
+#define C0_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 0
+#define C0_SCALE B_SCALE
+#endif
+#if RGB_GREEN == 1
+#define C1_SCALE G_SCALE
+#endif
+#if RGB_RED == 2
+#define C2_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 2
+#define C2_SCALE B_SCALE
+#endif
+
+
+/*
+ * First we have the histogram data structure and routines for creating it.
+ *
+ * The number of bits of precision can be adjusted by changing these symbols.
+ * We recommend keeping 6 bits for G and 5 each for R and B.
+ * If you have plenty of memory and cycles, 6 bits all around gives marginally
+ * better results; if you are short of memory, 5 bits all around will save
+ * some space but degrade the results.
+ * To maintain a fully accurate histogram, we'd need to allocate a "long"
+ * (preferably unsigned long) for each cell. In practice this is overkill;
+ * we can get by with 16 bits per cell. Few of the cell counts will overflow,
+ * and clamping those that do overflow to the maximum value will give close-
+ * enough results. This reduces the recommended histogram size from 256Kb
+ * to 128Kb, which is a useful savings on PC-class machines.
+ * (In the second pass the histogram space is re-used for pixel mapping data;
+ * in that capacity, each cell must be able to store zero to the number of
+ * desired colors. 16 bits/cell is plenty for that too.)
+ * Since the JPEG code is intended to run in small memory model on 80x86
+ * machines, we can't just allocate the histogram in one chunk. Instead
+ * of a true 3-D array, we use a row of pointers to 2-D arrays. Each
+ * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
+ * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that
+ * on 80x86 machines, the pointer row is in near memory but the actual
+ * arrays are in far memory (same arrangement as we use for image arrays).
+ */
+
+#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */
+
+/* These will do the right thing for either R,G,B or B,G,R color order,
+ * but you may not like the results for other color orders.
+ */
+#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */
+#define HIST_C1_BITS 6 /* bits of precision in G histogram */
+#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */
+
+/* Number of elements along histogram axes. */
+#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
+#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
+#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+
+/* These are the amounts to shift an input value to get a histogram index. */
+#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS)
+#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS)
+#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS)
+
+
+typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */
+
+typedef histcell FAR * histptr; /* for pointers to histogram cells */
+
+typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
+typedef hist1d FAR * hist2d; /* type for the 2nd-level pointers */
+typedef hist2d * hist3d; /* type for top-level pointer */
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array has (#columns + 2) entries; the extra entry at
+ * each end saves us from special-casing the first and last pixels.
+ * Each entry is three values long, one value for each color component.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Space for the eventually created colormap is stashed here */
+ JSAMPARRAY sv_colormap; /* colormap allocated at init time */
+ int desired; /* desired # of colors = size of colormap */
+
+ /* Variables for accumulating image statistics */
+ hist3d histogram; /* pointer to the histogram */
+
+ boolean needs_zeroed; /* TRUE if next pass must zero histogram */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+ int * error_limiter; /* table for clamping the applied error */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Prescan some rows of pixels.
+ * In this module the prescan simply updates the histogram, which has been
+ * initialized to zeroes by start_pass.
+ * An output_buf parameter is required by the method signature, but no data
+ * is actually output (in fact the buffer controller is probably passing a
+ * NULL pointer).
+ */
+
+METHODDEF(void)
+prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW ptr;
+ register histptr histp;
+ register hist3d histogram = cquantize->histogram;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptr = input_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the histogram */
+ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+ [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+ [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
+ /* increment, check for overflow and undo increment if so. */
+ if (++(*histp) <= 0)
+ (*histp)--;
+ ptr += 3;
+ }
+ }
+}
+
+
+/*
+ * Next we have the really interesting routines: selection of a colormap
+ * given the completed histogram.
+ * These routines work with a list of "boxes", each representing a rectangular
+ * subset of the input color space (to histogram precision).
+ */
+
+typedef struct {
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
+ int c0min, c0max;
+ int c1min, c1max;
+ int c2min, c2max;
+ /* The volume (actually 2-norm) of the box */
+ INT32 volume;
+ /* The number of nonzero histogram cells within this box */
+ long colorcount;
+} box;
+
+typedef box * boxptr;
+
+
+LOCAL(boxptr)
+find_biggest_color_pop (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest color population */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register long maxc = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->colorcount > maxc && boxp->volume > 0) {
+ which = boxp;
+ maxc = boxp->colorcount;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(boxptr)
+find_biggest_volume (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest (scaled) volume */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register INT32 maxv = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->volume > maxv) {
+ which = boxp;
+ maxv = boxp->volume;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(void)
+update_box (j_decompress_ptr cinfo, boxptr boxp)
+/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
+/* and recompute its volume and population */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ INT32 dist0,dist1,dist2;
+ long ccount;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ if (c0max > c0min)
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0min = c0min = c0;
+ goto have_c0min;
+ }
+ }
+ have_c0min:
+ if (c0max > c0min)
+ for (c0 = c0max; c0 >= c0min; c0--)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0max = c0max = c0;
+ goto have_c0max;
+ }
+ }
+ have_c0max:
+ if (c1max > c1min)
+ for (c1 = c1min; c1 <= c1max; c1++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1min = c1min = c1;
+ goto have_c1min;
+ }
+ }
+ have_c1min:
+ if (c1max > c1min)
+ for (c1 = c1max; c1 >= c1min; c1--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1max = c1max = c1;
+ goto have_c1max;
+ }
+ }
+ have_c1max:
+ if (c2max > c2min)
+ for (c2 = c2min; c2 <= c2max; c2++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2min = c2min = c2;
+ goto have_c2min;
+ }
+ }
+ have_c2min:
+ if (c2max > c2min)
+ for (c2 = c2max; c2 >= c2min; c2--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2max = c2max = c2;
+ goto have_c2max;
+ }
+ }
+ have_c2max:
+
+ /* Update box volume.
+ * We use 2-norm rather than real volume here; this biases the method
+ * against making long narrow boxes, and it has the side benefit that
+ * a box is splittable iff norm > 0.
+ * Since the differences are expressed in histogram-cell units,
+ * we have to shift back to JSAMPLE units to get consistent distances;
+ * after which, we scale according to the selected distance scale factors.
+ */
+ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
+ dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+ dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+ boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+
+ /* Now scan remaining volume of box and compute population */
+ ccount = 0;
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++, histp++)
+ if (*histp != 0) {
+ ccount++;
+ }
+ }
+ boxp->colorcount = ccount;
+}
+
+
+LOCAL(int)
+median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+ int desired_colors)
+/* Repeatedly select and split the largest box until we have enough boxes */
+{
+ int n,lb;
+ int c0,c1,c2,cmax;
+ register boxptr b1,b2;
+
+ while (numboxes < desired_colors) {
+ /* Select box to split.
+ * Current algorithm: by population for first half, then by volume.
+ */
+ if (numboxes*2 <= desired_colors) {
+ b1 = find_biggest_color_pop(boxlist, numboxes);
+ } else {
+ b1 = find_biggest_volume(boxlist, numboxes);
+ }
+ if (b1 == NULL) /* no splittable boxes left! */
+ break;
+ b2 = &boxlist[numboxes]; /* where new box will go */
+ /* Copy the color bounds to the new box. */
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ /* Choose which axis to split the box on.
+ * Current algorithm: longest scaled axis.
+ * See notes in update_box about scaling distances.
+ */
+ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
+ c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
+ c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
+ /* We want to break any ties in favor of green, then red, blue last.
+ * This code does the right thing for R,G,B or B,G,R color orders only.
+ */
+#if RGB_RED == 0
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
+ if (c2 > cmax) { n = 2; }
+#else
+ cmax = c1; n = 1;
+ if (c2 > cmax) { cmax = c2; n = 2; }
+ if (c0 > cmax) { n = 0; }
+#endif
+ /* Choose split point along selected axis, and update box bounds.
+ * Current algorithm: split at halfway point.
+ * (Since the box has been shrunk to minimum volume,
+ * any split will produce two nonempty subboxes.)
+ * Note that lb value is max for lower box, so must be < old max.
+ */
+ switch (n) {
+ case 0:
+ lb = (b1->c0max + b1->c0min) / 2;
+ b1->c0max = lb;
+ b2->c0min = lb+1;
+ break;
+ case 1:
+ lb = (b1->c1max + b1->c1min) / 2;
+ b1->c1max = lb;
+ b2->c1min = lb+1;
+ break;
+ case 2:
+ lb = (b1->c2max + b1->c2min) / 2;
+ b1->c2max = lb;
+ b2->c2min = lb+1;
+ break;
+ }
+ /* Update stats for boxes */
+ update_box(cinfo, b1);
+ update_box(cinfo, b2);
+ numboxes++;
+ }
+ return numboxes;
+}
+
+
+LOCAL(void)
+compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+/* Compute representative color for a box, put it in colormap[icolor] */
+{
+ /* Current algorithm: mean weighted by pixels (not colors) */
+ /* Note it is important to get the rounding correct! */
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ long count;
+ long total = 0;
+ long c0total = 0;
+ long c1total = 0;
+ long c2total = 0;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++) {
+ if ((count = *histp++) != 0) {
+ total += count;
+ c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ }
+ }
+ }
+
+ cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+ cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+ cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+}
+
+
+LOCAL(void)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
+/* Master routine for color selection */
+{
+ boxptr boxlist;
+ int numboxes;
+ int i;
+
+ /* Allocate workspace for box list */
+ boxlist = (boxptr) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
+ /* Initialize one box containing whole space */
+ numboxes = 1;
+ boxlist[0].c0min = 0;
+ boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
+ boxlist[0].c1min = 0;
+ boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
+ boxlist[0].c2min = 0;
+ boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
+ /* Shrink it to actually-used volume and set its statistics */
+ update_box(cinfo, & boxlist[0]);
+ /* Perform median-cut to produce final box list */
+ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
+ /* Compute the representative color for each box, fill colormap */
+ for (i = 0; i < numboxes; i++)
+ compute_color(cinfo, & boxlist[i], i);
+ cinfo->actual_number_of_colors = numboxes;
+ TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
+}
+
+
+/*
+ * These routines are concerned with the time-critical task of mapping input
+ * colors to the nearest color in the selected colormap.
+ *
+ * We re-use the histogram space as an "inverse color map", essentially a
+ * cache for the results of nearest-color searches. All colors within a
+ * histogram cell will be mapped to the same colormap entry, namely the one
+ * closest to the cell's center. This may not be quite the closest entry to
+ * the actual input color, but it's almost as good. A zero in the cache
+ * indicates we haven't found the nearest color for that cell yet; the array
+ * is cleared to zeroes before starting the mapping pass. When we find the
+ * nearest color for a cell, its colormap index plus one is recorded in the
+ * cache for future use. The pass2 scanning routines call fill_inverse_cmap
+ * when they need to use an unfilled entry in the cache.
+ *
+ * Our method of efficiently finding nearest colors is based on the "locally
+ * sorted search" idea described by Heckbert and on the incremental distance
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
+ * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
+ * the distances from a given colormap entry to each cell of the histogram can
+ * be computed quickly using an incremental method: the differences between
+ * distances to adjacent cells themselves differ by a constant. This allows a
+ * fairly fast implementation of the "brute force" approach of computing the
+ * distance from every colormap entry to every histogram cell. Unfortunately,
+ * it needs a work array to hold the best-distance-so-far for each histogram
+ * cell (because the inner loop has to be over cells, not colormap entries).
+ * The work array elements have to be INT32s, so the work array would need
+ * 256Kb at our recommended precision. This is not feasible in DOS machines.
+ *
+ * To get around these problems, we apply Thomas' method to compute the
+ * nearest colors for only the cells within a small subbox of the histogram.
+ * The work array need be only as big as the subbox, so the memory usage
+ * problem is solved. Furthermore, we need not fill subboxes that are never
+ * referenced in pass2; many images use only part of the color gamut, so a
+ * fair amount of work is saved. An additional advantage of this
+ * approach is that we can apply Heckbert's locality criterion to quickly
+ * eliminate colormap entries that are far away from the subbox; typically
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
+ * and we need not compute their distances to individual cells in the subbox.
+ * The speed of this approach is heavily influenced by the subbox size: too
+ * small means too much overhead, too big loses because Heckbert's criterion
+ * can't eliminate as many colormap entries. Empirically the best subbox
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
+ *
+ * Thomas' article also describes a refined method which is asymptotically
+ * faster than the brute-force method, but it is also far more complex and
+ * cannot efficiently be applied to small subboxes. It is therefore not
+ * useful for programs intended to be portable to DOS machines. On machines
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
+ * refined method might be faster than the present code --- but then again,
+ * it might not be any faster, and it's certainly more complicated.
+ */
+
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_C0_LOG (HIST_C0_BITS-3)
+#define BOX_C1_LOG (HIST_C1_BITS-3)
+#define BOX_C2_LOG (HIST_C2_BITS-3)
+
+#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
+#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+
+#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
+#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
+#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG)
+
+
+/*
+ * The next three routines implement inverse colormap filling. They could
+ * all be folded into one big routine, but splitting them up this way saves
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
+ * and may allow some compilers to produce better code by registerizing more
+ * inner-loop variables.
+ */
+
+LOCAL(int)
+find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ JSAMPLE colorlist[])
+/* Locate the colormap entries close enough to an update box to be candidates
+ * for the nearest entry to some cell(s) in the update box. The update box
+ * is specified by the center coordinates of its first cell. The number of
+ * candidate colormap entries is returned, and their colormap indexes are
+ * placed in colorlist[].
+ * This routine uses Heckbert's "locally sorted search" criterion to select
+ * the colors that need further consideration.
+ */
+{
+ int numcolors = cinfo->actual_number_of_colors;
+ int maxc0, maxc1, maxc2;
+ int centerc0, centerc1, centerc2;
+ int i, x, ncolors;
+ INT32 minmaxdist, min_dist, max_dist, tdist;
+ INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
+
+ /* Compute true coordinates of update box's upper corner and center.
+ * Actually we compute the coordinates of the center of the upper-corner
+ * histogram cell, which are the upper bounds of the volume we care about.
+ * Note that since ">>" rounds down, the "center" values may be closer to
+ * min than to max; hence comparisons to them must be "<=", not "<".
+ */
+ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
+ centerc0 = (minc0 + maxc0) >> 1;
+ maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
+ centerc1 = (minc1 + maxc1) >> 1;
+ maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
+ centerc2 = (minc2 + maxc2) >> 1;
+
+ /* For each color in colormap, find:
+ * 1. its minimum squared-distance to any point in the update box
+ * (zero if color is within update box);
+ * 2. its maximum squared-distance to any point in the update box.
+ * Both of these can be found by considering only the corners of the box.
+ * We save the minimum distance for each color in mindist[];
+ * only the smallest maximum distance is of interest.
+ */
+ minmaxdist = 0x7FFFFFFFL;
+
+ for (i = 0; i < numcolors; i++) {
+ /* We compute the squared-c0-distance term, then add in the other two. */
+ x = GETJSAMPLE(cinfo->colormap[0][i]);
+ if (x < minc0) {
+ tdist = (x - minc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else if (x > maxc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ min_dist = 0;
+ if (x <= centerc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[1][i]);
+ if (x < minc1) {
+ tdist = (x - minc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[2][i]);
+ if (x < minc2) {
+ tdist = (x - minc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ mindist[i] = min_dist; /* save away the results */
+ if (max_dist < minmaxdist)
+ minmaxdist = max_dist;
+ }
+
+ /* Now we know that no cell in the update box is more than minmaxdist
+ * away from some colormap entry. Therefore, only colors that are
+ * within minmaxdist of some part of the box need be considered.
+ */
+ ncolors = 0;
+ for (i = 0; i < numcolors; i++) {
+ if (mindist[i] <= minmaxdist)
+ colorlist[ncolors++] = (JSAMPLE) i;
+ }
+ return ncolors;
+}
+
+
+LOCAL(void)
+find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+/* Find the closest colormap entry for each cell in the update box,
+ * given the list of candidate colors prepared by find_nearby_colors.
+ * Return the indexes of the closest entries in the bestcolor[] array.
+ * This routine uses Thomas' incremental distance calculation method to
+ * find the distance from a colormap entry to successive cells in the box.
+ */
+{
+ int ic0, ic1, ic2;
+ int i, icolor;
+ register INT32 * bptr; /* pointer into bestdist[] array */
+ JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ INT32 dist0, dist1; /* initial distance values */
+ register INT32 dist2; /* current distance in inner loop */
+ INT32 xx0, xx1; /* distance increments */
+ register INT32 xx2;
+ INT32 inc0, inc1, inc2; /* initial values for increments */
+ /* This array holds the distance to the nearest-so-far color for each cell */
+ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Initialize best-distance for each cell of the update box */
+ bptr = bestdist;
+ for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ *bptr++ = 0x7FFFFFFFL;
+
+ /* For each color selected by find_nearby_colors,
+ * compute its distance to the center of each cell in the box.
+ * If that's less than best-so-far, update best distance and color number.
+ */
+
+ /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE)
+#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE)
+#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
+
+ for (i = 0; i < numcolors; i++) {
+ icolor = GETJSAMPLE(colorlist[i]);
+ /* Compute (square of) distance from minc0/c1/c2 to this color */
+ inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
+ dist0 = inc0*inc0;
+ inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
+ dist0 += inc1*inc1;
+ inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
+ dist0 += inc2*inc2;
+ /* Form the initial difference increments */
+ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
+ inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
+ inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
+ /* Now loop over all cells in box, updating distance per Thomas method */
+ bptr = bestdist;
+ cptr = bestcolor;
+ xx0 = inc0;
+ for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ dist1 = dist0;
+ xx1 = inc1;
+ for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ dist2 = dist1;
+ xx2 = inc2;
+ for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ if (dist2 < *bptr) {
+ *bptr = dist2;
+ *cptr = (JSAMPLE) icolor;
+ }
+ dist2 += xx2;
+ xx2 += 2 * STEP_C2 * STEP_C2;
+ bptr++;
+ cptr++;
+ }
+ dist1 += xx1;
+ xx1 += 2 * STEP_C1 * STEP_C1;
+ }
+ dist0 += xx0;
+ xx0 += 2 * STEP_C0 * STEP_C0;
+ }
+ }
+}
+
+
+LOCAL(void)
+fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+/* Fill the inverse-colormap entries in the update box that contains */
+/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */
+/* we can fill as many others as we wish.) */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int minc0, minc1, minc2; /* lower left corner of update box */
+ int ic0, ic1, ic2;
+ register JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ register histptr cachep; /* pointer into main cache array */
+ /* This array lists the candidate colormap indexes. */
+ JSAMPLE colorlist[MAXNUMCOLORS];
+ int numcolors; /* number of candidate colors */
+ /* This array holds the actually closest colormap index for each cell. */
+ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Convert cell coordinates to update box ID */
+ c0 >>= BOX_C0_LOG;
+ c1 >>= BOX_C1_LOG;
+ c2 >>= BOX_C2_LOG;
+
+ /* Compute true coordinates of update box's origin corner.
+ * Actually we compute the coordinates of the center of the corner
+ * histogram cell, which are the lower bounds of the volume we care about.
+ */
+ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+ minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+ minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+
+ /* Determine which colormap entries are close enough to be candidates
+ * for the nearest entry to some cell in the update box.
+ */
+ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
+
+ /* Determine the actually nearest colors. */
+ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
+ bestcolor);
+
+ /* Save the best color numbers (plus 1) in the main cache array */
+ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */
+ c1 <<= BOX_C1_LOG;
+ c2 <<= BOX_C2_LOG;
+ cptr = bestcolor;
+ for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
+ for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
+ cachep = & histogram[c0+ic0][c1+ic1][c2];
+ for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
+ *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+ }
+ }
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+pass2_no_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register JSAMPROW inptr, outptr;
+ register histptr cachep;
+ register int c0, c1, c2;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the cache */
+ c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
+ c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
+ c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
+ cachep = & histogram[c0][c1][c2];
+ /* If we have not seen this color before, find nearest colormap entry */
+ /* and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, c0,c1,c2);
+ /* Now emit the colormap index for this cell */
+ *outptr++ = (JSAMPLE) (*cachep - 1);
+ }
+ }
+}
+
+
+METHODDEF(void)
+pass2_fs_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
+ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
+ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ JSAMPROW inptr; /* => current input pixel */
+ JSAMPROW outptr; /* => current output pixel */
+ histptr cachep;
+ int dir; /* +1 or -1 depending on direction */
+ int dir3; /* 3*dir, for advancing inptr & errorptr */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *error_limit = cquantize->error_limiter;
+ JSAMPROW colormap0 = cinfo->colormap[0];
+ JSAMPROW colormap1 = cinfo->colormap[1];
+ JSAMPROW colormap2 = cinfo->colormap[2];
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ inptr += (width-1) * 3; /* so point to rightmost pixel */
+ outptr += width-1;
+ dir = -1;
+ dir3 = -3;
+ errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+ cquantize->on_odd_row = FALSE; /* flip for next time */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dir3 = 3;
+ errorptr = cquantize->fserrors; /* => entry before first real column */
+ cquantize->on_odd_row = TRUE; /* flip for next time */
+ }
+ /* Preset error values: no error propagated to first pixel from left */
+ cur0 = cur1 = cur2 = 0;
+ /* and no error propagated to row below yet */
+ belowerr0 = belowerr1 = belowerr2 = 0;
+ bpreverr0 = bpreverr1 = bpreverr2 = 0;
+
+ for (col = width; col > 0; col--) {
+ /* curN holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
+ cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
+ cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+ /* Limit the error using transfer function set by init_error_limit.
+ * See comments with init_error_limit for rationale.
+ */
+ cur0 = error_limit[cur0];
+ cur1 = error_limit[cur1];
+ cur2 = error_limit[cur2];
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE (or less with error limiting);
+ * this sets the required size of the range_limit array.
+ */
+ cur0 += GETJSAMPLE(inptr[0]);
+ cur1 += GETJSAMPLE(inptr[1]);
+ cur2 += GETJSAMPLE(inptr[2]);
+ cur0 = GETJSAMPLE(range_limit[cur0]);
+ cur1 = GETJSAMPLE(range_limit[cur1]);
+ cur2 = GETJSAMPLE(range_limit[cur2]);
+ /* Index into the cache with adjusted pixel value */
+ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+ /* If we have not seen this color before, find nearest colormap */
+ /* entry and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+ /* Now emit the colormap index for this cell */
+ { register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE) pixcode;
+ /* Compute representation error for this pixel */
+ cur0 -= GETJSAMPLE(colormap0[pixcode]);
+ cur1 -= GETJSAMPLE(colormap1[pixcode]);
+ cur2 -= GETJSAMPLE(colormap2[pixcode]);
+ }
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ { register LOCFSERROR bnexterr, delta;
+
+ bnexterr = cur0; /* Process component 0 */
+ delta = cur0 * 2;
+ cur0 += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr0 + cur0);
+ cur0 += delta; /* form error * 5 */
+ bpreverr0 = belowerr0 + cur0;
+ belowerr0 = bnexterr;
+ cur0 += delta; /* form error * 7 */
+ bnexterr = cur1; /* Process component 1 */
+ delta = cur1 * 2;
+ cur1 += delta; /* form error * 3 */
+ errorptr[1] = (FSERROR) (bpreverr1 + cur1);
+ cur1 += delta; /* form error * 5 */
+ bpreverr1 = belowerr1 + cur1;
+ belowerr1 = bnexterr;
+ cur1 += delta; /* form error * 7 */
+ bnexterr = cur2; /* Process component 2 */
+ delta = cur2 * 2;
+ cur2 += delta; /* form error * 3 */
+ errorptr[2] = (FSERROR) (bpreverr2 + cur2);
+ cur2 += delta; /* form error * 5 */
+ bpreverr2 = belowerr2 + cur2;
+ belowerr2 = bnexterr;
+ cur2 += delta; /* form error * 7 */
+ }
+ /* At this point curN contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ inptr += dir3; /* Advance pixel pointers to next column */
+ outptr += dir;
+ errorptr += dir3; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error values into the
+ * final fserrors[] entry. Note we need not unload belowerrN because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR) bpreverr1;
+ errorptr[2] = (FSERROR) bpreverr2;
+ }
+}
+
+
+/*
+ * Initialize the error-limiting transfer function (lookup table).
+ * The raw F-S error computation can potentially compute error values of up to
+ * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be
+ * much less, otherwise obviously wrong pixels will be created. (Typical
+ * effects include weird fringes at color-area boundaries, isolated bright
+ * pixels in a dark area, etc.) The standard advice for avoiding this problem
+ * is to ensure that the "corners" of the color cube are allocated as output
+ * colors; then repeated errors in the same direction cannot cause cascading
+ * error buildup. However, that only prevents the error from getting
+ * completely out of hand; Aaron Giles reports that error limiting improves
+ * the results even with corner colors allocated.
+ * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
+ * well, but the smoother transfer function used below is even better. Thanks
+ * to Aaron Giles for this idea.
+ */
+
+LOCAL(void)
+init_error_limit (j_decompress_ptr cinfo)
+/* Allocate and fill in the error_limiter table */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ int * table;
+ int in, out;
+
+ table = (int *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
+ table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
+ cquantize->error_limiter = table;
+
+#define STEPSIZE ((MAXJSAMPLE+1)/16)
+ /* Map errors 1:1 up to +- MAXJSAMPLE/16 */
+ out = 0;
+ for (in = 0; in < STEPSIZE; in++, out++) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
+ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
+ for (; in <= MAXJSAMPLE; in++) {
+ table[in] = out; table[-in] = -out;
+ }
+#undef STEPSIZE
+}
+
+
+/*
+ * Finish up at the end of each pass.
+ */
+
+METHODDEF(void)
+finish_pass1 (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Select the representative colors and fill in cinfo->colormap */
+ cinfo->colormap = cquantize->sv_colormap;
+ select_colors(cinfo, cquantize->desired);
+ /* Force next pass to zero the color index table */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+METHODDEF(void)
+finish_pass2 (j_decompress_ptr cinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * Initialize for each processing pass.
+ */
+
+METHODDEF(void)
+start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int i;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ if (is_pre_scan) {
+ /* Set up method pointers */
+ cquantize->pub.color_quantize = prescan_quantize;
+ cquantize->pub.finish_pass = finish_pass1;
+ cquantize->needs_zeroed = TRUE; /* Always zero histogram */
+ } else {
+ /* Set up method pointers */
+ if (cinfo->dither_mode == JDITHER_FS)
+ cquantize->pub.color_quantize = pass2_fs_dither;
+ else
+ cquantize->pub.color_quantize = pass2_no_dither;
+ cquantize->pub.finish_pass = finish_pass2;
+
+ /* Make sure color count is acceptable */
+ i = cinfo->actual_number_of_colors;
+ if (i < 1)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+ if (i > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+ if (cinfo->dither_mode == JDITHER_FS) {
+ size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+ (3 * SIZEOF(FSERROR)));
+ /* Allocate Floyd-Steinberg workspace if we didn't already. */
+ if (cquantize->fserrors == NULL)
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ /* Initialize the propagated errors to zero. */
+ jzero_far((void FAR *) cquantize->fserrors, arraysize);
+ /* Make the error-limit table if we didn't already. */
+ if (cquantize->error_limiter == NULL)
+ init_error_limit(cinfo);
+ cquantize->on_odd_row = FALSE;
+ }
+
+ }
+ /* Zero the histogram or inverse color map, if necessary */
+ if (cquantize->needs_zeroed) {
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ jzero_far((void FAR *) histogram[i],
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = FALSE;
+ }
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF(void)
+new_color_map_2_quant (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Reset the inverse color map */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+/*
+ * Module initialization routine for 2-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_2pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+ int i;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_2_quant;
+ cquantize->pub.new_color_map = new_color_map_2_quant;
+ cquantize->fserrors = NULL; /* flag optional arrays not allocated */
+ cquantize->error_limiter = NULL;
+
+ /* Make sure jdmaster didn't give me a case I can't handle */
+ if (cinfo->out_color_components != 3)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+
+ /* Allocate the histogram/inverse colormap storage */
+ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
+
+ /* Allocate storage for the completed colormap, if required.
+ * We do this now since it is FAR storage and may affect
+ * the memory manager's space calculations.
+ */
+ if (cinfo->enable_2pass_quant) {
+ /* Make sure color count is acceptable */
+ int desired = cinfo->desired_number_of_colors;
+ /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+ if (desired < 8)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (desired > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+ cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ cquantize->desired = desired;
+ } else
+ cquantize->sv_colormap = NULL;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ /* Allocate Floyd-Steinberg workspace if necessary.
+ * This isn't really needed until pass 2, but again it is FAR storage.
+ * Although we will cope with a later change in dither_mode,
+ * we do not promise to honor max_memory_to_use if dither_mode changes.
+ */
+ if (cinfo->dither_mode == JDITHER_FS) {
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+ /* Might as well create the error-limiting table too. */
+ init_error_limit(cinfo);
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jutils.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/jutils.cpp
new file mode 100644
index 00000000..a4f56764
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jutils.cpp
@@ -0,0 +1,180 @@
+/*
+ * jutils.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains tables and miscellaneous utility routines needed
+ * for both compression and decompression.
+ * Note we prefix all global names with "j" to minimize conflicts with
+ * a surrounding application.
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+//#include "jinclude.h"
+//#include "jpeglib.h"
+
+
+/*
+ * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
+ * of a DCT block read in natural order (left to right, top to bottom).
+ */
+
+#if 0 /* This table is not actually needed in v6a */
+
+const int jpeg_zigzag_order[DCTSIZE2] = {
+ 0, 1, 5, 6, 14, 15, 27, 28,
+ 2, 4, 7, 13, 16, 26, 29, 42,
+ 3, 8, 12, 17, 25, 30, 41, 43,
+ 9, 11, 18, 24, 31, 40, 44, 53,
+ 10, 19, 23, 32, 39, 45, 52, 54,
+ 20, 22, 33, 38, 46, 51, 55, 60,
+ 21, 34, 37, 47, 50, 56, 59, 61,
+ 35, 36, 48, 49, 57, 58, 62, 63
+};
+
+#endif
+
+/*
+ * jpeg_natural_order[i] is the natural-order position of the i'th element
+ * of zigzag order.
+ *
+ * When reading corrupted data, the Huffman decoders could attempt
+ * to reference an entry beyond the end of this array (if the decoded
+ * zero run length reaches past the end of the block). To prevent
+ * wild stores without adding an inner-loop test, we put some extra
+ * "63"s after the real entries. This will cause the extra coefficient
+ * to be stored in location 63 of the block, not somewhere random.
+ * The worst case would be a run-length of 15, which means we need 16
+ * fake entries.
+ */
+
+const int jpeg_natural_order[DCTSIZE2+16] = {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
+ 63, 63, 63, 63, 63, 63, 63, 63
+};
+
+
+/*
+ * Arithmetic utilities
+ */
+
+GLOBAL(long)
+jdiv_round_up (long a, long b)
+/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
+/* Assumes a >= 0, b > 0 */
+{
+ return (a + b - 1L) / b;
+}
+
+
+GLOBAL(long)
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+ a += b - 1L;
+ return a - (a % b);
+}
+
+
+/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
+ * and coefficient-block arrays. This won't work on 80x86 because the arrays
+ * are FAR and we're assuming a small-pointer memory model. However, some
+ * DOS compilers provide far-pointer versions of memcpy() and memset() even
+ * in the small-model libraries. These will be used if USE_FMEM is defined.
+ * Otherwise, the routines below do it the hard way. (The performance cost
+ * is not all that great, because these routines aren't very heavily used.)
+ */
+
+#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */
+#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size)
+#define FMEMZERO(target,size) MEMZERO(target,size)
+#else /* 80x86 case, define if we can */
+#ifdef USE_FMEM
+#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
+#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
+#endif
+#endif
+
+
+GLOBAL(void)
+jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas may overlap for duplication.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+ register JSAMPROW inptr, outptr;
+#ifdef FMEMCOPY
+ register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
+#else
+ register JDIMENSION count;
+#endif
+ register int row;
+
+ input_array += source_row;
+ output_array += dest_row;
+
+ for (row = num_rows; row > 0; row--) {
+ inptr = *input_array++;
+ outptr = *output_array++;
+#ifdef FMEMCOPY
+ FMEMCOPY(outptr, inptr, count);
+#else
+ for (count = num_cols; count > 0; count--)
+ *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
+#endif
+ }
+}
+
+
+GLOBAL(void)
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+#ifdef FMEMCOPY
+ FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
+#else
+ register JCOEFPTR inptr, outptr;
+ register long count;
+
+ inptr = (JCOEFPTR) input_row;
+ outptr = (JCOEFPTR) output_row;
+ for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
+ *outptr++ = *inptr++;
+ }
+#endif
+}
+
+
+GLOBAL(void)
+jzero_far (void FAR * target, size_t bytestozero)
+/* Zero out a chunk of FAR memory. */
+/* This might be sample-array data, block-array data, or alloc_large data. */
+{
+#ifdef FMEMZERO
+ FMEMZERO(target, bytestozero);
+#else
+ register char FAR * ptr = (char FAR *) target;
+ register size_t count;
+
+ for (count = bytestozero; count > 0; count--) {
+ *ptr++ = 0;
+ }
+#endif
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/jversion.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/jversion.h
new file mode 100644
index 00000000..6472c58d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/jversion.h
@@ -0,0 +1,14 @@
+/*
+ * jversion.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains software version identification.
+ */
+
+
+#define JVERSION "6b 27-Mar-1998"
+
+#define JCOPYRIGHT "Copyright (C) 1998, Thomas G. Lane"
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdbmp.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdbmp.cpp
new file mode 100644
index 00000000..4f6b4d12
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdbmp.cpp
@@ -0,0 +1,440 @@
+/*
+ * rdbmp.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Microsoft "BMP"
+ * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
+ * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
+ * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
+ * Also, we don't support RLE-compressed files.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed BMP format).
+ *
+ * This code contributed by James Arthur Boucher.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef BMP_SUPPORTED
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/* Private version of data source object */
+
+typedef struct _bmp_source_struct * bmp_source_ptr;
+
+typedef struct _bmp_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ j_compress_ptr cinfo; /* back link saves passing separate parm */
+
+ JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
+
+ jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
+ JDIMENSION source_row; /* Current source row number */
+ JDIMENSION row_width; /* Physical width of scanlines in file */
+
+ int bits_per_pixel; /* remembers 8- or 24-bit format */
+} bmp_source_struct;
+
+
+LOCAL(int)
+read_byte (bmp_source_ptr sinfo)
+/* Read next byte from BMP file */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int c;
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
+ return c;
+}
+
+
+LOCAL(void)
+read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
+/* Read the colormap from a BMP file */
+{
+ int i;
+
+ switch (mapentrysize) {
+ case 3:
+ /* BGR format (occurs in OS/2 files) */
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ }
+ break;
+ case 4:
+ /* BGR0 format (occurs in MS Windows files) */
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ (void) read_byte(sinfo);
+ }
+ break;
+ default:
+ ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
+ break;
+ }
+}
+
+
+/*
+ * Read one row of pixels.
+ * The image has been read into the whole_image array, but is otherwise
+ * unprocessed. We must read it out in top-to-bottom row order, and if
+ * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
+ */
+
+METHODDEF(JDIMENSION)
+get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit colormap indexes */
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ register JSAMPARRAY colormap = source->colormap;
+ JSAMPARRAY image_ptr;
+ register int t;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+
+ /* Fetch next row from virtual array */
+ source->source_row--;
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source->source_row, (JDIMENSION) 1, FALSE);
+
+ /* Expand the colormap indexes to real data */
+ inptr = image_ptr[0];
+ outptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ t = GETJSAMPLE(*inptr++);
+ *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
+ *outptr++ = colormap[1][t];
+ *outptr++ = colormap[2][t];
+ }
+
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 24-bit pixels */
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+
+ /* Fetch next row from virtual array */
+ source->source_row--;
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source->source_row, (JDIMENSION) 1, FALSE);
+
+ /* Transfer data. Note source values are in BGR order
+ * (even though Microsoft's own documents say the opposite).
+ */
+ inptr = image_ptr[0];
+ outptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
+ outptr[1] = *inptr++;
+ outptr[0] = *inptr++;
+ outptr += 3;
+ }
+
+ return 1;
+}
+
+
+/*
+ * This method loads the image into whole_image during the first call on
+ * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
+ * get_8bit_row or get_24bit_row on subsequent calls.
+ */
+
+METHODDEF(JDIMENSION)
+preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ register FILE *infile = source->pub.input_file;
+ register int c;
+ register JSAMPROW out_ptr;
+ JSAMPARRAY image_ptr;
+ JDIMENSION row, col;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Read the data into a virtual array in input-file row order. */
+ for (row = 0; row < cinfo->image_height; row++) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) row;
+ progress->pub.pass_limit = (long) cinfo->image_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ row, (JDIMENSION) 1, TRUE);
+ out_ptr = image_ptr[0];
+ for (col = source->row_width; col > 0; col--) {
+ /* inline copy of read_byte() for speed */
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ *out_ptr++ = (JSAMPLE) c;
+ }
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Set up to read from the virtual array in top-to-bottom order */
+ switch (source->bits_per_pixel) {
+ case 8:
+ source->pub.get_pixel_rows = get_8bit_row;
+ break;
+ case 24:
+ source->pub.get_pixel_rows = get_24bit_row;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ }
+ source->source_row = cinfo->image_height;
+
+ /* And read the first row */
+ return (*source->pub.get_pixel_rows) (cinfo, sinfo);
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ U_CHAR bmpfileheader[14];
+ U_CHAR bmpinfoheader[64];
+#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
+ (((unsigned int) UCH(array[offset+1])) << 8))
+#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
+ (((INT32) UCH(array[offset+1])) << 8) + \
+ (((INT32) UCH(array[offset+2])) << 16) + \
+ (((INT32) UCH(array[offset+3])) << 24))
+ INT32 bfOffBits;
+ INT32 headerSize;
+ INT32 biWidth = 0; /* initialize to avoid compiler warning */
+ INT32 biHeight = 0;
+ unsigned int biPlanes;
+ INT32 biCompression;
+ INT32 biXPelsPerMeter,biYPelsPerMeter;
+ INT32 biClrUsed = 0;
+ int mapentrysize = 0; /* 0 indicates no colormap */
+ INT32 bPad;
+ JDIMENSION row_width;
+
+ /* Read and verify the bitmap file header */
+ if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
+ ERREXIT(cinfo, JERR_BMP_NOT);
+ bfOffBits = (INT32) GET_4B(bmpfileheader,10);
+ /* We ignore the remaining fileheader fields */
+
+ /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
+ * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
+ */
+ if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ headerSize = (INT32) GET_4B(bmpinfoheader,0);
+ if (headerSize < 12 || headerSize > 64)
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+
+ switch ((int) headerSize) {
+ case 12:
+ /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
+ biWidth = (INT32) GET_2B(bmpinfoheader,4);
+ biHeight = (INT32) GET_2B(bmpinfoheader,6);
+ biPlanes = GET_2B(bmpinfoheader,8);
+ source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
+
+ switch (source->bits_per_pixel) {
+ case 8: /* colormapped image */
+ mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
+ TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
+ break;
+ case 24: /* RGB image */
+ TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ break;
+ }
+ if (biPlanes != 1)
+ ERREXIT(cinfo, JERR_BMP_BADPLANES);
+ break;
+ case 40:
+ case 64:
+ /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
+ /* or OS/2 2.x header, which has additional fields that we ignore */
+ biWidth = GET_4B(bmpinfoheader,4);
+ biHeight = GET_4B(bmpinfoheader,8);
+ biPlanes = GET_2B(bmpinfoheader,12);
+ source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
+ biCompression = GET_4B(bmpinfoheader,16);
+ biXPelsPerMeter = GET_4B(bmpinfoheader,24);
+ biYPelsPerMeter = GET_4B(bmpinfoheader,28);
+ biClrUsed = GET_4B(bmpinfoheader,32);
+ /* biSizeImage, biClrImportant fields are ignored */
+
+ switch (source->bits_per_pixel) {
+ case 8: /* colormapped image */
+ mapentrysize = 4; /* Windows uses RGBQUAD colormap */
+ TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
+ break;
+ case 24: /* RGB image */
+ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ break;
+ }
+ if (biPlanes != 1)
+ ERREXIT(cinfo, JERR_BMP_BADPLANES);
+ if (biCompression != 0)
+ ERREXIT(cinfo, JERR_BMP_COMPRESSED);
+
+ if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
+ /* Set JFIF density parameters from the BMP data */
+ cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
+ cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
+ cinfo->density_unit = 2; /* dots/cm */
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ break;
+ }
+
+ /* Compute distance to bitmap data --- will adjust for colormap below */
+ bPad = bfOffBits - (headerSize + 14);
+
+ /* Read the colormap, if any */
+ if (mapentrysize > 0) {
+ if (biClrUsed <= 0)
+ biClrUsed = 256; /* assume it's 256 */
+ else if (biClrUsed > 256)
+ ERREXIT(cinfo, JERR_BMP_BADCMAP);
+ /* Allocate space to store the colormap */
+ source->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) biClrUsed, (JDIMENSION) 3);
+ /* and read it from the file */
+ read_colormap(source, (int) biClrUsed, mapentrysize);
+ /* account for size of colormap */
+ bPad -= biClrUsed * mapentrysize;
+ }
+
+ /* Skip any remaining pad bytes */
+ if (bPad < 0) /* incorrect bfOffBits value? */
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ while (--bPad >= 0) {
+ (void) read_byte(source);
+ }
+
+ /* Compute row width in file, including padding to 4-byte boundary */
+ if (source->bits_per_pixel == 24)
+ row_width = (JDIMENSION) (biWidth * 3);
+ else
+ row_width = (JDIMENSION) biWidth;
+ while ((row_width & 3) != 0) row_width++;
+ source->row_width = row_width;
+
+ /* Allocate space for inversion array, prepare for preload pass */
+ source->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
+ source->pub.get_pixel_rows = preload_image;
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+
+ /* Allocate one-row buffer for returned data */
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+
+ cinfo->in_color_space = JCS_RGB;
+ cinfo->input_components = 3;
+ cinfo->data_precision = 8;
+ cinfo->image_width = (JDIMENSION) biWidth;
+ cinfo->image_height = (JDIMENSION) biHeight;
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for BMP format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_bmp (j_compress_ptr cinfo)
+{
+ bmp_source_ptr source;
+
+ /* Create module interface object */
+ source = (bmp_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(bmp_source_struct));
+ source->cinfo = cinfo; /* make back link for subroutines */
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_bmp;
+ source->pub.finish_input = finish_input_bmp;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* BMP_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdcolmap.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdcolmap.cpp
new file mode 100644
index 00000000..19969274
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdcolmap.cpp
@@ -0,0 +1,254 @@
+/*
+ * rdcolmap.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file implements djpeg's "-map file" switch. It reads a source image
+ * and constructs a colormap to be supplied to the JPEG decompressor.
+ *
+ * Currently, these file formats are supported for the map file:
+ * GIF: the contents of the GIF's global colormap are used.
+ * PPM (either text or raw flavor): the entire file is read and
+ * each unique pixel value is entered in the map.
+ * Note that reading a large PPM file will be horrendously slow.
+ * Typically, a PPM-format map file should contain just one pixel
+ * of each desired color. Such a file can be extracted from an
+ * ordinary image PPM file with ppmtomap(1).
+ *
+ * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
+ * currently implemented.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
+
+/* Portions of this code are based on the PBMPLUS library, which is:
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+
+/*
+ * Add a (potentially) new color to the color map.
+ */
+
+LOCAL(void)
+add_map_entry (j_decompress_ptr cinfo, int R, int G, int B)
+{
+ JSAMPROW colormap0 = cinfo->colormap[0];
+ JSAMPROW colormap1 = cinfo->colormap[1];
+ JSAMPROW colormap2 = cinfo->colormap[2];
+ int ncolors = cinfo->actual_number_of_colors;
+ int index;
+
+ /* Check for duplicate color. */
+ for (index = 0; index < ncolors; index++) {
+ if (GETJSAMPLE(colormap0[index]) == R &&
+ GETJSAMPLE(colormap1[index]) == G &&
+ GETJSAMPLE(colormap2[index]) == B)
+ return; /* color is already in map */
+ }
+
+ /* Check for map overflow. */
+ if (ncolors >= (MAXJSAMPLE+1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
+
+ /* OK, add color to map. */
+ colormap0[ncolors] = (JSAMPLE) R;
+ colormap1[ncolors] = (JSAMPLE) G;
+ colormap2[ncolors] = (JSAMPLE) B;
+ cinfo->actual_number_of_colors++;
+}
+
+
+/*
+ * Extract color map from a GIF file.
+ */
+
+LOCAL(void)
+read_gif_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ int header[13];
+ int i, colormaplen;
+ int R, G, B;
+
+ /* Initial 'G' has already been read by read_color_map */
+ /* Read the rest of the GIF header and logical screen descriptor */
+ for (i = 1; i < 13; i++) {
+ if ((header[i] = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ }
+
+ /* Verify GIF Header */
+ if (header[1] != 'I' || header[2] != 'F')
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* There must be a global color map. */
+ if ((header[10] & 0x80) == 0)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* OK, fetch it. */
+ colormaplen = 2 << (header[10] & 0x07);
+
+ for (i = 0; i < colormaplen; i++) {
+ R = getc(infile);
+ G = getc(infile);
+ B = getc(infile);
+ if (R == EOF || G == EOF || B == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ add_map_entry(cinfo,
+ R << (BITS_IN_JSAMPLE-8),
+ G << (BITS_IN_JSAMPLE-8),
+ B << (BITS_IN_JSAMPLE-8));
+ }
+}
+
+
+/* Support routines for reading PPM */
+
+
+LOCAL(int)
+pbm_getc (FILE * infile)
+/* Read next char, skipping over any comments */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(infile);
+ if (ch == '#') {
+ do {
+ ch = getc(infile);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(unsigned int)
+read_pbm_integer (j_decompress_ptr cinfo, FILE * infile)
+/* Read an unsigned decimal integer from the PPM file */
+/* Swallows one trailing character after the integer */
+/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
+/* This should not be a problem in practice. */
+{
+ register int ch;
+ register unsigned int val;
+
+ /* Skip any leading whitespace */
+ do {
+ ch = pbm_getc(infile);
+ if (ch == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
+
+ if (ch < '0' || ch > '9')
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ val = ch - '0';
+ while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
+ val *= 10;
+ val += ch - '0';
+ }
+ return val;
+}
+
+
+/*
+ * Extract color map from a PPM file.
+ */
+
+LOCAL(void)
+read_ppm_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ int c;
+ unsigned int w, h, maxval, row, col;
+ int R, G, B;
+
+ /* Initial 'P' has already been read by read_color_map */
+ c = getc(infile); /* save format discriminator for a sec */
+
+ /* while we fetch the remaining header info */
+ w = read_pbm_integer(cinfo, infile);
+ h = read_pbm_integer(cinfo, infile);
+ maxval = read_pbm_integer(cinfo, infile);
+
+ if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* For now, we don't support rescaling from an unusual maxval. */
+ if (maxval != (unsigned int) MAXJSAMPLE)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ switch (c) {
+ case '3': /* it's a text-format PPM file */
+ for (row = 0; row < h; row++) {
+ for (col = 0; col < w; col++) {
+ R = read_pbm_integer(cinfo, infile);
+ G = read_pbm_integer(cinfo, infile);
+ B = read_pbm_integer(cinfo, infile);
+ add_map_entry(cinfo, R, G, B);
+ }
+ }
+ break;
+
+ case '6': /* it's a raw-format PPM file */
+ for (row = 0; row < h; row++) {
+ for (col = 0; col < w; col++) {
+ R = getc(infile);
+ G = getc(infile);
+ B = getc(infile);
+ if (R == EOF || G == EOF || B == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ add_map_entry(cinfo, R, G, B);
+ }
+ }
+ break;
+
+ default:
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ break;
+ }
+}
+
+
+/*
+ * Main entry point from djpeg.c.
+ * Input: opened input file (from file name argument on command line).
+ * Output: colormap and actual_number_of_colors fields are set in cinfo.
+ */
+
+GLOBAL(void)
+read_color_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ /* Allocate space for a color map of maximum supported size. */
+ cinfo->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3);
+ cinfo->actual_number_of_colors = 0; /* initialize map to empty */
+
+ /* Read first byte to determine file format */
+ switch (getc(infile)) {
+ case 'G':
+ read_gif_map(cinfo, infile);
+ break;
+ case 'P':
+ read_ppm_map(cinfo, infile);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ break;
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdgif.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdgif.cpp
new file mode 100644
index 00000000..3bf98ee0
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdgif.cpp
@@ -0,0 +1,39 @@
+/*
+ * rdgif.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in GIF format.
+ *
+ *****************************************************************************
+ * NOTE: to avoid entanglements with Unisys' patent on LZW compression, *
+ * the ability to read GIF files has been removed from the IJG distribution. *
+ * Sorry about that. *
+ *****************************************************************************
+ *
+ * We are required to state that
+ * "The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated."
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef GIF_SUPPORTED
+
+/*
+ * The module selection routine for GIF format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_gif (j_compress_ptr cinfo)
+{
+ fprintf(stderr, "GIF input is unsupported for legal reasons. Sorry.\n");
+ exit(EXIT_FAILURE);
+ return NULL; /* keep compiler happy */
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdppm.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdppm.cpp
new file mode 100644
index 00000000..6102b830
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdppm.cpp
@@ -0,0 +1,461 @@
+/*
+ * rdppm.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in PPM/PGM format.
+ * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
+ * The PBMPLUS library is NOT required to compile this software
+ * (but it is highly useful as a set of PPM image manipulation programs).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed PPM format).
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef PPM_SUPPORTED
+
+
+/* Portions of this code are based on the PBMPLUS library, which is:
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/*
+ * On most systems, reading individual bytes with getc() is drastically less
+ * efficient than buffering a row at a time with fread(). On PCs, we must
+ * allocate the buffer in near data space, because we are assuming small-data
+ * memory model, wherein fread() can't reach far memory. If you need to
+ * process very wide images on a PC, you might have to compile in large-memory
+ * model, or else replace fread() with a getc() loop --- which will be much
+ * slower.
+ */
+
+
+/* Private version of data source object */
+
+typedef struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */
+ JSAMPROW pixrow; /* FAR pointer to same */
+ size_t buffer_width; /* width of I/O buffer */
+ JSAMPLE *rescale; /* => maxval-remapping array, or NULL */
+} ppm_source_struct;
+
+typedef ppm_source_struct * ppm_source_ptr;
+
+
+LOCAL(int)
+pbm_getc (FILE * infile)
+/* Read next char, skipping over any comments */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(infile);
+ if (ch == '#') {
+ do {
+ ch = getc(infile);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(unsigned int)
+read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
+/* Read an unsigned decimal integer from the PPM file */
+/* Swallows one trailing character after the integer */
+/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
+/* This should not be a problem in practice. */
+{
+ register int ch;
+ register unsigned int val;
+
+ /* Skip any leading whitespace */
+ do {
+ ch = pbm_getc(infile);
+ if (ch == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
+
+ if (ch < '0' || ch > '9')
+ ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
+
+ val = ch - '0';
+ while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
+ val *= 10;
+ val += ch - '0';
+ }
+ return val;
+}
+
+
+/*
+ * Read one row of pixels.
+ *
+ * We provide several different versions depending on input file format.
+ * In all cases, input is scaled to the size of JSAMPLE.
+ *
+ * A really fast path is provided for reading byte/sample raw files with
+ * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
+ */
+
+
+METHODDEF(JDIMENSION)
+get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading text-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ FILE * infile = source->pub.input_file;
+ register JSAMPROW ptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading text-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ FILE * infile = source->pub.input_file;
+ register JSAMPROW ptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
+ * In this case we just read right into the JSAMPLE buffer!
+ * Note that same code works for PPM and PGM files.
+ */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-word-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ register int temp;
+ temp = UCH(*bufferptr++);
+ temp |= UCH(*bufferptr++) << 8;
+ *ptr++ = rescale[temp];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-word-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ register int temp;
+ temp = UCH(*bufferptr++);
+ temp |= UCH(*bufferptr++) << 8;
+ *ptr++ = rescale[temp];
+ temp = UCH(*bufferptr++);
+ temp |= UCH(*bufferptr++) << 8;
+ *ptr++ = rescale[temp];
+ temp = UCH(*bufferptr++);
+ temp |= UCH(*bufferptr++) << 8;
+ *ptr++ = rescale[temp];
+ }
+ return 1;
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ int c;
+ unsigned int w, h, maxval;
+ boolean need_iobuffer, use_raw_buffer, need_rescale;
+
+ if (getc(source->pub.input_file) != 'P')
+ ERREXIT(cinfo, JERR_PPM_NOT);
+
+ c = getc(source->pub.input_file); /* subformat discriminator character */
+
+ /* detect unsupported variants (ie, PBM) before trying to read header */
+ switch (c) {
+ case '2': /* it's a text-format PGM file */
+ case '3': /* it's a text-format PPM file */
+ case '5': /* it's a raw-format PGM file */
+ case '6': /* it's a raw-format PPM file */
+ break;
+ default:
+ ERREXIT(cinfo, JERR_PPM_NOT);
+ break;
+ }
+
+ /* fetch the remaining header info */
+ w = read_pbm_integer(cinfo, source->pub.input_file);
+ h = read_pbm_integer(cinfo, source->pub.input_file);
+ maxval = read_pbm_integer(cinfo, source->pub.input_file);
+
+ if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
+ ERREXIT(cinfo, JERR_PPM_NOT);
+
+ cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
+ cinfo->image_width = (JDIMENSION) w;
+ cinfo->image_height = (JDIMENSION) h;
+
+ /* initialize flags to most common settings */
+ need_iobuffer = TRUE; /* do we need an I/O buffer? */
+ use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */
+ need_rescale = TRUE; /* do we need a rescale array? */
+
+ switch (c) {
+ case '2': /* it's a text-format PGM file */
+ cinfo->input_components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
+ source->pub.get_pixel_rows = get_text_gray_row;
+ need_iobuffer = FALSE;
+ break;
+
+ case '3': /* it's a text-format PPM file */
+ cinfo->input_components = 3;
+ cinfo->in_color_space = JCS_RGB;
+ TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
+ source->pub.get_pixel_rows = get_text_rgb_row;
+ need_iobuffer = FALSE;
+ break;
+
+ case '5': /* it's a raw-format PGM file */
+ cinfo->input_components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
+ if (maxval > 255) {
+ source->pub.get_pixel_rows = get_word_gray_row;
+ } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
+ source->pub.get_pixel_rows = get_raw_row;
+ use_raw_buffer = TRUE;
+ need_rescale = FALSE;
+ } else {
+ source->pub.get_pixel_rows = get_scaled_gray_row;
+ }
+ break;
+
+ case '6': /* it's a raw-format PPM file */
+ cinfo->input_components = 3;
+ cinfo->in_color_space = JCS_RGB;
+ TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
+ if (maxval > 255) {
+ source->pub.get_pixel_rows = get_word_rgb_row;
+ } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
+ source->pub.get_pixel_rows = get_raw_row;
+ use_raw_buffer = TRUE;
+ need_rescale = FALSE;
+ } else {
+ source->pub.get_pixel_rows = get_scaled_rgb_row;
+ }
+ break;
+ }
+
+ /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
+ if (need_iobuffer) {
+ source->buffer_width = (size_t) w * cinfo->input_components *
+ ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR)));
+ source->iobuffer = (U_CHAR *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ source->buffer_width);
+ }
+
+ /* Create compressor input buffer. */
+ if (use_raw_buffer) {
+ /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
+ /* Synthesize a JSAMPARRAY pointer structure */
+ /* Cast here implies near->far pointer conversion on PCs */
+ source->pixrow = (JSAMPROW) source->iobuffer;
+ source->pub.buffer = & source->pixrow;
+ source->pub.buffer_height = 1;
+ } else {
+ /* Need to translate anyway, so make a separate sample buffer. */
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+ }
+
+ /* Compute the rescaling array if required. */
+ if (need_rescale) {
+ INT32 val, half_maxval;
+
+ /* On 16-bit-int machines we have to be careful of maxval = 65535 */
+ source->rescale = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
+ half_maxval = maxval / 2;
+ for (val = 0; val <= (INT32) maxval; val++) {
+ /* The multiplication here must be done in 32 bits to avoid overflow */
+ source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
+ }
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for PPM format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_ppm (j_compress_ptr cinfo)
+{
+ ppm_source_ptr source;
+
+ /* Create module interface object */
+ source = (ppm_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ppm_source_struct));
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_ppm;
+ source->pub.finish_input = finish_input_ppm;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdrle.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdrle.cpp
new file mode 100644
index 00000000..46258548
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdrle.cpp
@@ -0,0 +1,388 @@
+/*
+ * rdrle.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Utah RLE format.
+ * The Utah Raster Toolkit library is required (version 3.1 or later).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed RLE format).
+ *
+ * Based on code contributed by Mike Lijewski,
+ * with updates from Robert Hutchinson.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef RLE_SUPPORTED
+
+/* rle.h is provided by the Utah Raster Toolkit. */
+
+#include <rle.h>
+
+/*
+ * We assume that JSAMPLE has the same representation as rle_pixel,
+ * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+/*
+ * We support the following types of RLE files:
+ *
+ * GRAYSCALE - 8 bits, no colormap
+ * MAPPEDGRAY - 8 bits, 1 channel colomap
+ * PSEUDOCOLOR - 8 bits, 3 channel colormap
+ * TRUECOLOR - 24 bits, 3 channel colormap
+ * DIRECTCOLOR - 24 bits, no colormap
+ *
+ * For now, we ignore any alpha channel in the image.
+ */
+
+typedef enum
+ { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
+
+
+/*
+ * Since RLE stores scanlines bottom-to-top, we have to invert the image
+ * to conform to JPEG's top-to-bottom order. To do this, we read the
+ * incoming image into a virtual array on the first get_pixel_rows call,
+ * then fetch the required row from the virtual array on subsequent calls.
+ */
+
+typedef struct _rle_source_struct * rle_source_ptr;
+
+typedef struct _rle_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ rle_kind visual; /* actual type of input file */
+ jvirt_sarray_ptr image; /* virtual array to hold the image */
+ JDIMENSION row; /* current row # in the virtual array */
+ rle_hdr header; /* Input file information */
+ rle_pixel** rle_row; /* holds a row returned by rle_getrow() */
+
+} rle_source_struct;
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JDIMENSION width, height;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /* Use RLE library routine to get the header info */
+ source->header = *rle_hdr_init(NULL);
+ source->header.rle_file = source->pub.input_file;
+ switch (rle_get_setup(&(source->header))) {
+ case RLE_SUCCESS:
+ /* A-OK */
+ break;
+ case RLE_NOT_RLE:
+ ERREXIT(cinfo, JERR_RLE_NOT);
+ break;
+ case RLE_NO_SPACE:
+ ERREXIT(cinfo, JERR_RLE_MEM);
+ break;
+ case RLE_EMPTY:
+ ERREXIT(cinfo, JERR_RLE_EMPTY);
+ break;
+ case RLE_EOF:
+ ERREXIT(cinfo, JERR_RLE_EOF);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_RLE_BADERROR);
+ break;
+ }
+
+ /* Figure out what we have, set private vars and return values accordingly */
+
+ width = source->header.xmax - source->header.xmin + 1;
+ height = source->header.ymax - source->header.ymin + 1;
+ source->header.xmin = 0; /* realign horizontally */
+ source->header.xmax = width-1;
+
+ cinfo->image_width = width;
+ cinfo->image_height = height;
+ cinfo->data_precision = 8; /* we can only handle 8 bit data */
+
+ if (source->header.ncolors == 1 && source->header.ncmap == 0) {
+ source->visual = GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
+ } else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
+ source->visual = MAPPEDGRAY;
+ TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
+ source->visual = PSEUDOCOLOR;
+ TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
+ source->visual = TRUECOLOR;
+ TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
+ source->visual = DIRECTCOLOR;
+ TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
+ } else
+ ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
+
+ if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ cinfo->input_components = 1;
+ } else {
+ cinfo->in_color_space = JCS_RGB;
+ cinfo->input_components = 3;
+ }
+
+ /*
+ * A place to hold each scanline while it's converted.
+ * (GRAYSCALE scanlines don't need converting)
+ */
+ if (source->visual != GRAYSCALE) {
+ source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) width, (JDIMENSION) cinfo->input_components);
+ }
+
+ /* request a virtual array to hold the image */
+ source->image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) (width * source->header.ncolors),
+ (JDIMENSION) height, (JDIMENSION) 1);
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ /* count file input as separate pass */
+ progress->total_extra_passes++;
+ }
+#endif
+
+ source->pub.buffer_height = 1;
+}
+
+
+/*
+ * Read one row of pixels.
+ * Called only after load_image has read the image into the virtual array.
+ * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
+ */
+
+METHODDEF(JDIMENSION)
+get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+
+ source->row--;
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
+
+ return 1;
+}
+
+/*
+ * Read one row of pixels.
+ * Called only after load_image has read the image into the virtual array.
+ * Used for PSEUDOCOLOR images.
+ */
+
+METHODDEF(JDIMENSION)
+get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JSAMPROW src_row, dest_row;
+ JDIMENSION col;
+ rle_map *colormap;
+ int val;
+
+ colormap = source->header.cmap;
+ dest_row = source->pub.buffer[0];
+ source->row--;
+ src_row = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
+
+ for (col = cinfo->image_width; col > 0; col--) {
+ val = GETJSAMPLE(*src_row++);
+ *dest_row++ = (JSAMPLE) (colormap[val ] >> 8);
+ *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8);
+ *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8);
+ }
+
+ return 1;
+}
+
+
+/*
+ * Load the image into a virtual array. We have to do this because RLE
+ * files start at the lower left while the JPEG standard has them starting
+ * in the upper left. This is called the first time we want to get a row
+ * of input. What we do is load the RLE data into the array and then call
+ * the appropriate routine to read one row from the array. Before returning,
+ * we set source->pub.get_pixel_rows so that subsequent calls go straight to
+ * the appropriate row-reading routine.
+ */
+
+METHODDEF(JDIMENSION)
+load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JDIMENSION row, col;
+ JSAMPROW scanline, red_ptr, green_ptr, blue_ptr;
+ rle_pixel **rle_row;
+ rle_map *colormap;
+ char channel;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ colormap = source->header.cmap;
+ rle_row = source->rle_row;
+
+ /* Read the RLE data into our virtual array.
+ * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
+ * and (b) we are not on a machine where FAR pointers differ from regular.
+ */
+ RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_limit = cinfo->image_height;
+ progress->pub.pass_counter = 0;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+
+ switch (source->visual) {
+
+ case GRAYSCALE:
+ case PSEUDOCOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_getrow(&source->header, rle_row);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ break;
+
+ case MAPPEDGRAY:
+ case TRUECOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ scanline = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_row = source->rle_row;
+ rle_getrow(&source->header, rle_row);
+
+ for (col = 0; col < cinfo->image_width; col++) {
+ for (channel = 0; channel < source->header.ncolors; channel++) {
+ *scanline++ = (JSAMPLE)
+ (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8);
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ break;
+
+ case DIRECTCOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ scanline = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_getrow(&source->header, rle_row);
+
+ red_ptr = rle_row[0];
+ green_ptr = rle_row[1];
+ blue_ptr = rle_row[2];
+
+ for (col = cinfo->image_width; col > 0; col--) {
+ *scanline++ = *red_ptr++;
+ *scanline++ = *green_ptr++;
+ *scanline++ = *blue_ptr++;
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+#endif
+
+ /* Set up to call proper row-extraction routine in future */
+ if (source->visual == PSEUDOCOLOR) {
+ source->pub.buffer = source->rle_row;
+ source->pub.get_pixel_rows = get_pseudocolor_row;
+ } else {
+ source->pub.get_pixel_rows = get_rle_row;
+ }
+ source->row = cinfo->image_height;
+
+ /* And fetch the topmost (bottommost) row */
+ return (*source->pub.get_pixel_rows) (cinfo, sinfo);
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for RLE format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_rle (j_compress_ptr cinfo)
+{
+ rle_source_ptr source;
+
+ /* Create module interface object */
+ source = (rle_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(rle_source_struct));
+ /* Fill in method ptrs */
+ source->pub.start_input = start_input_rle;
+ source->pub.finish_input = finish_input_rle;
+ source->pub.get_pixel_rows = load_image;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* RLE_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.cpp
new file mode 100644
index 00000000..a9023fbe
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.cpp
@@ -0,0 +1,358 @@
+/*
+ * rdswitch.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to process some of cjpeg's more complicated
+ * command-line switches. Switches processed here are:
+ * -qtables file Read quantization tables from text file
+ * -scans file Read scan script from text file
+ * -qslots N[,N,...] Set component quantization table selectors
+ * -sample HxV[,HxV,...] Set component sampling factors
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include <ctype.h> /* to declare isdigit(), isspace() */
+
+
+LOCAL(int)
+text_getc (FILE * file)
+/* Read next char, skipping over any comments (# to end of line) */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(file);
+ if (ch == '#') {
+ do {
+ ch = getc(file);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(boolean)
+read_text_integer (FILE * file, long * result, int * termchar)
+/* Read an unsigned decimal integer from a file, store it in result */
+/* Reads one trailing character after the integer; returns it in termchar */
+{
+ register int ch;
+ register long val;
+
+ /* Skip any leading whitespace, detect EOF */
+ do {
+ ch = text_getc(file);
+ if (ch == EOF) {
+ *termchar = ch;
+ return FALSE;
+ }
+ } while (isspace(ch));
+
+ if (! isdigit(ch)) {
+ *termchar = ch;
+ return FALSE;
+ }
+
+ val = ch - '0';
+ while ((ch = text_getc(file)) != EOF) {
+ if (! isdigit(ch))
+ break;
+ val *= 10;
+ val += ch - '0';
+ }
+ *result = val;
+ *termchar = ch;
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+read_quant_tables (j_compress_ptr cinfo, char * filename,
+ int scale_factor, boolean force_baseline)
+/* Read a set of quantization tables from the specified file.
+ * The file is plain ASCII text: decimal numbers with whitespace between.
+ * Comments preceded by '#' may be included in the file.
+ * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
+ * The tables are implicitly numbered 0,1,etc.
+ * NOTE: does not affect the qslots mapping, which will default to selecting
+ * table 0 for luminance (or primary) components, 1 for chrominance components.
+ * You must use -qslots if you want a different component->table mapping.
+ */
+{
+ FILE * fp;
+ int tblno, i, termchar;
+ long val;
+ unsigned int table[DCTSIZE2];
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Can't open table file %s\n", filename);
+ return FALSE;
+ }
+ tblno = 0;
+
+ while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */
+ if (tblno >= NUM_QUANT_TBLS) {
+ fprintf(stderr, "Too many tables in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ table[0] = (unsigned int) val;
+ for (i = 1; i < DCTSIZE2; i++) {
+ if (! read_text_integer(fp, &val, &termchar)) {
+ fprintf(stderr, "Invalid table data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ table[i] = (unsigned int) val;
+ }
+ jpeg_add_quant_table(cinfo, tblno, table, scale_factor, force_baseline);
+ tblno++;
+ }
+
+ if (termchar != EOF) {
+ fprintf(stderr, "Non-numeric data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+
+LOCAL(boolean)
+read_scan_integer (FILE * file, long * result, int * termchar)
+/* Variant of read_text_integer that always looks for a non-space termchar;
+ * this simplifies parsing of punctuation in scan scripts.
+ */
+{
+ register int ch;
+
+ if (! read_text_integer(file, result, termchar))
+ return FALSE;
+ ch = *termchar;
+ while (ch != EOF && isspace(ch))
+ ch = text_getc(file);
+ if (isdigit(ch)) { /* oops, put it back */
+ if (ungetc(ch, file) == EOF)
+ return FALSE;
+ ch = ' ';
+ } else {
+ /* Any separators other than ';' and ':' are ignored;
+ * this allows user to insert commas, etc, if desired.
+ */
+ if (ch != EOF && ch != ';' && ch != ':')
+ ch = ' ';
+ }
+ *termchar = ch;
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+read_scan_script (j_compress_ptr cinfo, char * filename)
+/* Read a scan script from the specified text file.
+ * Each entry in the file defines one scan to be emitted.
+ * Entries are separated by semicolons ';'.
+ * An entry contains one to four component indexes,
+ * optionally followed by a colon ':' and four progressive-JPEG parameters.
+ * The component indexes denote which component(s) are to be transmitted
+ * in the current scan. The first component has index 0.
+ * Sequential JPEG is used if the progressive-JPEG parameters are omitted.
+ * The file is free format text: any whitespace may appear between numbers
+ * and the ':' and ';' punctuation marks. Also, other punctuation (such
+ * as commas or dashes) can be placed between numbers if desired.
+ * Comments preceded by '#' may be included in the file.
+ * Note: we do very little validity checking here;
+ * jcmaster.c will validate the script parameters.
+ */
+{
+ FILE * fp;
+ int scanno, ncomps, termchar;
+ long val;
+ jpeg_scan_info * scanptr;
+#define MAX_SCANS 100 /* quite arbitrary limit */
+ jpeg_scan_info scans[MAX_SCANS];
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Can't open scan definition file %s\n", filename);
+ return FALSE;
+ }
+ scanptr = scans;
+ scanno = 0;
+
+ while (read_scan_integer(fp, &val, &termchar)) {
+ if (scanno >= MAX_SCANS) {
+ fprintf(stderr, "Too many scans defined in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ scanptr->component_index[0] = (int) val;
+ ncomps = 1;
+ while (termchar == ' ') {
+ if (ncomps >= MAX_COMPS_IN_SCAN) {
+ fprintf(stderr, "Too many components in one scan in file %s\n",
+ filename);
+ fclose(fp);
+ return FALSE;
+ }
+ if (! read_scan_integer(fp, &val, &termchar))
+ goto bogus;
+ scanptr->component_index[ncomps] = (int) val;
+ ncomps++;
+ }
+ scanptr->comps_in_scan = ncomps;
+ if (termchar == ':') {
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Ss = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Se = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Ah = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar))
+ goto bogus;
+ scanptr->Al = (int) val;
+ } else {
+ /* set non-progressive parameters */
+ scanptr->Ss = 0;
+ scanptr->Se = DCTSIZE2-1;
+ scanptr->Ah = 0;
+ scanptr->Al = 0;
+ }
+ if (termchar != ';' && termchar != EOF) {
+bogus:
+ fprintf(stderr, "Invalid scan entry format in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ scanptr++, scanno++;
+ }
+
+ if (termchar != EOF) {
+ fprintf(stderr, "Non-numeric data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+
+ if (scanno > 0) {
+ /* Stash completed scan list in cinfo structure.
+ * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data,
+ * but if you want to compress multiple images you'd want JPOOL_PERMANENT.
+ */
+ scanptr = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ scanno * SIZEOF(jpeg_scan_info));
+ MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info));
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = scanno;
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+
+#endif /* C_MULTISCAN_FILES_SUPPORTED */
+
+
+GLOBAL(boolean)
+set_quant_slots (j_compress_ptr cinfo, char *arg)
+/* Process a quantization-table-selectors parameter string, of the form
+ * N[,N,...]
+ * If there are more components than parameters, the last value is replicated.
+ */
+{
+ int val = 0; /* default table # */
+ int ci;
+ char ch;
+
+ for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+ if (*arg) {
+ ch = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c", &val, &ch) < 1)
+ return FALSE;
+ if (ch != ',') /* syntax check */
+ return FALSE;
+ if (val < 0 || val >= NUM_QUANT_TBLS) {
+ fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
+ NUM_QUANT_TBLS-1);
+ return FALSE;
+ }
+ cinfo->comp_info[ci].quant_tbl_no = val;
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ } else {
+ /* reached end of parameter, set remaining components to last table */
+ cinfo->comp_info[ci].quant_tbl_no = val;
+ }
+ }
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+set_sample_factors (j_compress_ptr cinfo, char *arg)
+/* Process a sample-factors parameter string, of the form
+ * HxV[,HxV,...]
+ * If there are more components than parameters, "1x1" is assumed for the rest.
+ */
+{
+ int ci, val1, val2;
+ char ch1, ch2;
+
+ for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+ if (*arg) {
+ ch2 = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
+ return FALSE;
+ if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
+ return FALSE;
+ if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
+ fprintf(stderr, "JPEG sampling factors must be 1..4\n");
+ return FALSE;
+ }
+ cinfo->comp_info[ci].h_samp_factor = val1;
+ cinfo->comp_info[ci].v_samp_factor = val2;
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ } else {
+ /* reached end of parameter, set remaining components to 1x1 sampling */
+ cinfo->comp_info[ci].h_samp_factor = 1;
+ cinfo->comp_info[ci].v_samp_factor = 1;
+ }
+ }
+ return TRUE;
+}
+
+
+#ifdef C_LOSSLESS_SUPPORTED
+
+GLOBAL(boolean) set_simple_lossless (j_compress_ptr cinfo, char *arg)
+{
+ int pred, pt = 0;
+ char ch;
+
+ ch = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c", &pred, &ch) < 1)
+ return FALSE;
+ if (ch != ',') /* syntax check */
+ return FALSE;
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ if (*arg) {
+ if (sscanf(arg, "%d", &pt) != 1)
+ pt = 0;
+ }
+ jpeg_simple_lossless(cinfo, pred, pt);
+ return TRUE;
+}
+
+#endif /* C_LOSSLESS_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.h
new file mode 100644
index 00000000..645b22c9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdswitch.h
@@ -0,0 +1 @@
+GLOBAL(boolean) set_simple_lossless (j_compress_ptr cinfo, char *arg); \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/rdtarga.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdtarga.cpp
new file mode 100644
index 00000000..abb38258
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/rdtarga.cpp
@@ -0,0 +1,501 @@
+/*
+ * rdtarga.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Targa format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed Targa format).
+ *
+ * Based on code contributed by Lee Daniel Crocker.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef TARGA_SUPPORTED
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/* Private version of data source object */
+
+typedef struct _tga_source_struct * tga_source_ptr;
+
+typedef struct _tga_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ j_compress_ptr cinfo; /* back link saves passing separate parm */
+
+ JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
+
+ jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
+ JDIMENSION current_row; /* Current logical row number to read */
+
+ /* Pointer to routine to extract next Targa pixel from input file */
+ JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
+
+ /* Result of read_pixel is delivered here: */
+ U_CHAR tga_pixel[4];
+
+ int pixel_size; /* Bytes per Targa pixel (1 to 4) */
+
+ /* State info for reading RLE-coded pixels; both counts must be init to 0 */
+ int block_count; /* # of pixels remaining in RLE block */
+ int dup_pixel_count; /* # of times to duplicate previous pixel */
+
+ /* This saves the correct pixel-row-expansion method for preload_image */
+ JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+} tga_source_struct;
+
+
+/* For expanding 5-bit pixel values to 8-bit with best rounding */
+
+static const UINT8 c5to8bits[32] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+
+
+LOCAL(int)
+read_byte (tga_source_ptr sinfo)
+/* Read next byte from Targa file */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int c;
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
+ return c;
+}
+
+
+LOCAL(void)
+read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
+/* Read the colormap from a Targa file */
+{
+ int i;
+
+ /* Presently only handles 24-bit BGR format */
+ if (mapentrysize != 24)
+ ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
+
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ }
+}
+
+
+/*
+ * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
+ */
+
+METHODDEF(void)
+read_non_rle_pixel (tga_source_ptr sinfo)
+/* Read one Targa pixel from the input file; no RLE expansion */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int i;
+
+ for (i = 0; i < sinfo->pixel_size; i++) {
+ sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
+ }
+}
+
+
+METHODDEF(void)
+read_rle_pixel (tga_source_ptr sinfo)
+/* Read one Targa pixel from the input file, expanding RLE data as needed */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int i;
+
+ /* Duplicate previously read pixel? */
+ if (sinfo->dup_pixel_count > 0) {
+ sinfo->dup_pixel_count--;
+ return;
+ }
+
+ /* Time to read RLE block header? */
+ if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
+ i = read_byte(sinfo);
+ if (i & 0x80) { /* Start of duplicate-pixel block? */
+ sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
+ sinfo->block_count = 0; /* then read new block header */
+ } else {
+ sinfo->block_count = i & 0x7F; /* number of pixels after this one */
+ }
+ }
+
+ /* Read next pixel */
+ for (i = 0; i < sinfo->pixel_size; i++) {
+ sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
+ }
+}
+
+
+/*
+ * Read one row of pixels.
+ *
+ * We provide several different versions depending on input file format.
+ */
+
+
+METHODDEF(JDIMENSION)
+get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit grayscale pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit colormap indexes */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register int t;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+ register JSAMPARRAY colormap = source->colormap;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ t = UCH(source->tga_pixel[0]);
+ *ptr++ = colormap[0][t];
+ *ptr++ = colormap[1][t];
+ *ptr++ = colormap[2][t];
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 16-bit pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register int t;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ t = UCH(source->tga_pixel[0]);
+ t += UCH(source->tga_pixel[1]) << 8;
+ /* We expand 5 bit data to 8 bit sample width.
+ * The format of the 16-bit (LSB first) input word is
+ * xRRRRRGGGGGBBBBB
+ */
+ ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
+ t >>= 5;
+ ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
+ t >>= 5;
+ ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
+ ptr += 3;
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 24-bit pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
+ }
+ return 1;
+}
+
+/*
+ * Targa also defines a 32-bit pixel format with order B,G,R,A.
+ * We presently ignore the attribute byte, so the code for reading
+ * these pixels is identical to the 24-bit routine above.
+ * This works because the actual pixel length is only known to read_pixel.
+ */
+
+#define get_32bit_row get_24bit_row
+
+
+/*
+ * This method is for re-reading the input data in standard top-down
+ * row order. The entire image has already been read into whole_image
+ * with proper conversion of pixel format, but it's in a funny row order.
+ */
+
+METHODDEF(JDIMENSION)
+get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ JDIMENSION source_row;
+
+ /* Compute row of source that maps to current_row of normal order */
+ /* For now, assume image is bottom-up and not interlaced. */
+ /* NEEDS WORK to support interlaced images! */
+ source_row = cinfo->image_height - source->current_row - 1;
+
+ /* Fetch that row from virtual array */
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source_row, (JDIMENSION) 1, FALSE);
+
+ source->current_row++;
+ return 1;
+}
+
+
+/*
+ * This method loads the image into whole_image during the first call on
+ * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
+ * get_memory_row on subsequent calls.
+ */
+
+METHODDEF(JDIMENSION)
+preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ JDIMENSION row;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Read the data into a virtual array in input-file row order. */
+ for (row = 0; row < cinfo->image_height; row++) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) row;
+ progress->pub.pass_limit = (long) cinfo->image_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
+ (*source->get_pixel_rows) (cinfo, sinfo);
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Set up to read from the virtual array in unscrambled order */
+ source->pub.get_pixel_rows = get_memory_row;
+ source->current_row = 0;
+ /* And read the first row */
+ return get_memory_row(cinfo, sinfo);
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ U_CHAR targaheader[18];
+ int idlen, cmaptype, subtype, flags, interlace_type, components;
+ unsigned int width, height, maplen;
+ boolean is_bottom_up;
+
+#define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \
+ (((unsigned int) UCH(targaheader[offset+1])) << 8))
+
+ if (! ReadOK(source->pub.input_file, targaheader, 18))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+
+ /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
+ if (targaheader[16] == 15)
+ targaheader[16] = 16;
+
+ idlen = UCH(targaheader[0]);
+ cmaptype = UCH(targaheader[1]);
+ subtype = UCH(targaheader[2]);
+ maplen = GET_2B(5);
+ width = GET_2B(12);
+ height = GET_2B(14);
+ source->pixel_size = UCH(targaheader[16]) >> 3;
+ flags = UCH(targaheader[17]); /* Image Descriptor byte */
+
+ is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
+ interlace_type = flags >> 6; /* bits 6/7 are interlace code */
+
+ if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
+ source->pixel_size < 1 || source->pixel_size > 4 ||
+ (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
+ interlace_type != 0) /* currently don't allow interlaced image */
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+
+ if (subtype > 8) {
+ /* It's an RLE-coded file */
+ source->read_pixel = read_rle_pixel;
+ source->block_count = source->dup_pixel_count = 0;
+ subtype -= 8;
+ } else {
+ /* Non-RLE file */
+ source->read_pixel = read_non_rle_pixel;
+ }
+
+ /* Now should have subtype 1, 2, or 3 */
+ components = 3; /* until proven different */
+ cinfo->in_color_space = JCS_RGB;
+
+ switch (subtype) {
+ case 1: /* Colormapped image */
+ if (source->pixel_size == 1 && cmaptype == 1)
+ source->get_pixel_rows = get_8bit_row;
+ else
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
+ break;
+ case 2: /* RGB image */
+ switch (source->pixel_size) {
+ case 2:
+ source->get_pixel_rows = get_16bit_row;
+ break;
+ case 3:
+ source->get_pixel_rows = get_24bit_row;
+ break;
+ case 4:
+ source->get_pixel_rows = get_32bit_row;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ break;
+ }
+ TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
+ break;
+ case 3: /* Grayscale image */
+ components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ if (source->pixel_size == 1)
+ source->get_pixel_rows = get_8bit_gray_row;
+ else
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ break;
+ }
+
+ if (is_bottom_up) {
+ /* Create a virtual array to buffer the upside-down image. */
+ source->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+ /* source->pub.buffer will point to the virtual array. */
+ source->pub.buffer_height = 1; /* in case anyone looks at it */
+ source->pub.get_pixel_rows = preload_image;
+ } else {
+ /* Don't need a virtual array, but do need a one-row input buffer. */
+ source->whole_image = NULL;
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) width * components, (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+ source->pub.get_pixel_rows = source->get_pixel_rows;
+ }
+
+ while (idlen--) /* Throw away ID field */
+ (void) read_byte(source);
+
+ if (maplen > 0) {
+ if (maplen > 256 || GET_2B(3) != 0)
+ ERREXIT(cinfo, JERR_TGA_BADCMAP);
+ /* Allocate space to store the colormap */
+ source->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
+ /* and read it from the file */
+ read_colormap(source, (int) maplen, UCH(targaheader[7]));
+ } else {
+ if (cmaptype) /* but you promised a cmap! */
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ source->colormap = NULL;
+ }
+
+ cinfo->input_components = components;
+ cinfo->data_precision = 8;
+ cinfo->image_width = width;
+ cinfo->image_height = height;
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for Targa format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_targa (j_compress_ptr cinfo)
+{
+ tga_source_ptr source;
+
+ /* Create module interface object */
+ source = (tga_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(tga_source_struct));
+ source->cinfo = cinfo; /* make back link for subroutines */
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_tga;
+ source->pub.finish_input = finish_input_tga;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* TARGA_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.cpp
new file mode 100644
index 00000000..87051419
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// IJGWin32.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.h
new file mode 100644
index 00000000..141dab7b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/stdafx.h
@@ -0,0 +1,42 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+// TODO: reference additional headers your program requires here
+#include <stdio.h>
+#include <windows.h>
+
+#define JPEG_CJPEG_DJPEG
+#define JPEG_INTERNALS
+#define JPEG_CJPEG_DJPEG
+#define PPM_SUPPORTED
+#define TARGA_SUPPORTED
+#define RLE_SUPPORTED
+#define BMP_SUPPORTED
+#define GIF_SUPPORTED
+
+#include "cderror.h"
+#include "cdjpeg.h"
+#include "jchuff.h"
+#include "jconfig.h"
+#include "jdct.h"
+#include "jdhuff.h"
+#include "jerror.h"
+#include "jinclude.h"
+#include "jpegint.h"
+#include "jlossls.h"
+#include "jlossy.h"
+#include "jmemsys.h"
+#include "jmorecfg.h"
+#include "jpeglib.h"
+#include "jversion.h"
+#include "transupp.h"
+#include "rdswitch.h"
+#include "jcodec.h"
+#include "jcdiffct.h"
+#include "jddiffct.h"
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.cpp
new file mode 100644
index 00000000..ff7a1cc7
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.cpp
@@ -0,0 +1,930 @@
+/*
+ * transupp.c
+ *
+ * Copyright (C) 1997-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains image transformation routines and other utility code
+ * used by the jpegtran sample application. These are NOT part of the core
+ * JPEG library. But we keep these routines separate from jpegtran.c to
+ * ease the task of maintaining jpegtran-like programs that have other user
+ * interfaces.
+ */
+
+/* Although this file really shouldn't have access to the library internals,
+ * it's helpful to let it call jround_up() and jcopy_block_row().
+ */
+#include "stdafx.h"
+
+#define JPEG_INTERNALS
+
+//#include "jinclude.h"
+//#include "jpeglib.h"
+//#include "transupp.h" /* My own external interface */
+
+
+#if TRANSFORMS_SUPPORTED
+
+/*
+ * Lossless image transformation routines. These routines work on DCT
+ * coefficient arrays and thus do not require any lossy decompression
+ * or recompression of the image.
+ * Thanks to Guido Vollbeding for the initial design and code of this feature.
+ *
+ * Horizontal flipping is done in-place, using a single top-to-bottom
+ * pass through the virtual source array. It will thus be much the
+ * fastest option for images larger than main memory.
+ *
+ * The other routines require a set of destination virtual arrays, so they
+ * need twice as much memory as jpegtran normally does. The destination
+ * arrays are always written in normal scan order (top to bottom) because
+ * the virtual array manager expects this. The source arrays will be scanned
+ * in the corresponding order, which means multiple passes through the source
+ * arrays for most of the transforms. That could result in much thrashing
+ * if the image is larger than main memory.
+ *
+ * Some notes about the operating environment of the individual transform
+ * routines:
+ * 1. Both the source and destination virtual arrays are allocated from the
+ * source JPEG object, and therefore should be manipulated by calling the
+ * source's memory manager.
+ * 2. The destination's component count should be used. It may be smaller
+ * than the source's when forcing to grayscale.
+ * 3. Likewise the destination's sampling factors should be used. When
+ * forcing to grayscale the destination's sampling factors will be all 1,
+ * and we may as well take that as the effective iMCU size.
+ * 4. When "trim" is in effect, the destination's dimensions will be the
+ * trimmed values but the source's will be untrimmed.
+ * 5. All the routines assume that the source and destination buffers are
+ * padded out to a full iMCU boundary. This is true, although for the
+ * source buffer it is an undocumented property of jdcoefct.c.
+ * Notes 2,3,4 boil down to this: generally we should use the destination's
+ * dimensions and ignore the source's.
+ */
+
+
+LOCAL(void)
+do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays)
+/* Horizontal flip; done in-place, so no separate dest array is required */
+{
+ JDIMENSION MCU_cols, comp_width, blk_x, blk_y;
+ int ci, k, offset_y;
+ JBLOCKARRAY buffer;
+ JCOEFPTR ptr1, ptr2;
+ JCOEF temp1, temp2;
+ jpeg_component_info *compptr;
+
+ /* Horizontal mirroring of DCT blocks is accomplished by swapping
+ * pairs of blocks in-place. Within a DCT block, we perform horizontal
+ * mirroring by changing the signs of odd-numbered columns.
+ * Partial iMCUs at the right edge are left untouched.
+ */
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ for (blk_y = 0; blk_y < compptr->height_in_data_units;
+ blk_y += compptr->v_samp_factor) {
+ buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
+ ptr1 = buffer[offset_y][blk_x];
+ ptr2 = buffer[offset_y][comp_width - blk_x - 1];
+ /* this unrolled loop doesn't need to know which row it's on... */
+ for (k = 0; k < DCTSIZE2; k += 2) {
+ temp1 = *ptr1; /* swap even column */
+ temp2 = *ptr2;
+ *ptr1++ = temp2;
+ *ptr2++ = temp1;
+ temp1 = *ptr1; /* swap odd column with sign change */
+ temp2 = *ptr2;
+ *ptr1++ = -temp2;
+ *ptr2++ = -temp1;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Vertical flip */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* We output into a separate array because we can't touch different
+ * rows of the source virtual array simultaneously. Otherwise, this
+ * is a pretty straightforward analog of horizontal flip.
+ * Within a DCT block, vertical mirroring is done by changing the signs
+ * of odd-numbered rows.
+ * Partial iMCUs at the bottom edge are copied verbatim.
+ */
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge blocks will be copied verbatim. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units;
+ dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* copy even row */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ /* copy odd row with sign change */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ } else {
+ /* Just copy row verbatim. */
+ jcopy_block_row(src_buffer[offset_y], dst_buffer[offset_y],
+ compptr->width_in_data_units);
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transpose source into destination */
+{
+ JDIMENSION dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Transposing pixels within a block just requires transposing the
+ * DCT coefficients.
+ * Partial iMCUs at the edges require no special treatment; we simply
+ * process all the available DCT blocks for every component.
+ */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 90 degree rotation is equivalent to
+ * 1. Transposing the image;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) right edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ if (dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 270 degree rotation is equivalent to
+ * 1. Horizontal mirroring;
+ * 2. Transposing the image.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) bottom edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ if (dst_blk_y < comp_height) {
+ /* Block is within the mirrorable area. */
+ src_ptr = src_buffer[offset_x]
+ [comp_height - dst_blk_y - offset_y - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 180 degree rotation is equivalent to
+ * 1. Vertical mirroring;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (dst_blk_y < comp_height) {
+ /* Row is within the vertically mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - dst_blk_y - (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge rows are only mirrored horizontally. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ if (dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ /* Process the blocks that can be mirrored both ways. */
+ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* For even row, negate every odd column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ /* For odd row, negate every even column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = - *src_ptr++;
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+ /* Any remaining right-edge blocks are only mirrored vertically. */
+ for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ } else {
+ /* Remaining rows are just mirrored horizontally. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[offset_y];
+ /* Process the blocks that can be mirrored. */
+ for (dst_blk_x = 0; dst_blk_x < comp_width; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE2; i += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ /* Any remaining right-edge blocks are only copied. */
+ for (; dst_blk_x < compptr->width_in_data_units; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE2; i++)
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transverse transpose is equivalent to
+ * 1. 180 degree rotation;
+ * 2. Transposition;
+ * or
+ * 1. Horizontal mirroring;
+ * 2. Transposition;
+ * 3. Horizontal mirroring.
+ * These steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = dstinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = dstinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_data_units;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_data_units;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], dst_blk_x,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ if (dst_blk_y < comp_height) {
+ src_ptr = src_buffer[offset_x]
+ [comp_height - dst_blk_y - offset_y - 1];
+ if (dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ i++;
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Right-edge blocks are mirrored in y only */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ } else {
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y];
+ if (dst_blk_x < comp_width) {
+ /* Bottom-edge blocks are mirrored in x only */
+ dst_ptr = dst_buffer[offset_y]
+ [comp_width - dst_blk_x - offset_x - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* At lower right corner, just transpose, no mirroring */
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* Request any required workspace.
+ *
+ * We allocate the workspace virtual arrays from the source decompression
+ * object, so that all the arrays (both the original data and the workspace)
+ * will be taken into account while making memory management decisions.
+ * Hence, this routine must be called after jpeg_read_header (which reads
+ * the image dimensions) and before jpeg_read_coefficients (which realizes
+ * the source's virtual arrays).
+ */
+
+GLOBAL(void)
+jtransform_request_workspace (j_decompress_ptr srcinfo,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *coef_arrays = NULL;
+ jpeg_component_info *compptr;
+ int ci;
+
+ if (info->force_grayscale &&
+ srcinfo->jpeg_color_space == JCS_YCbCr &&
+ srcinfo->num_components == 3) {
+ /* We'll only process the first component */
+ info->num_components = 1;
+ } else {
+ /* Process all the components */
+ info->num_components = srcinfo->num_components;
+ }
+
+ switch (info->transform) {
+ case JXFORM_NONE:
+ case JXFORM_FLIP_H:
+ /* Don't need a workspace array */
+ break;
+ case JXFORM_FLIP_V:
+ case JXFORM_ROT_180:
+ /* Need workspace arrays having same dimensions as source image.
+ * Note that we allocate arrays padded out to the next iMCU boundary,
+ * so that transform routines need not worry about missing edge blocks.
+ */
+ coef_arrays = (jvirt_barray_ptr *)
+ (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+ SIZEOF(jvirt_barray_ptr) * info->num_components);
+ for (ci = 0; ci < info->num_components; ci++) {
+ compptr = srcinfo->comp_info + ci;
+ coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+ ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+ break;
+ case JXFORM_TRANSPOSE:
+ case JXFORM_TRANSVERSE:
+ case JXFORM_ROT_90:
+ case JXFORM_ROT_270:
+ /* Need workspace arrays having transposed dimensions.
+ * Note that we allocate arrays padded out to the next iMCU boundary,
+ * so that transform routines need not worry about missing edge blocks.
+ */
+ coef_arrays = (jvirt_barray_ptr *)
+ (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+ SIZEOF(jvirt_barray_ptr) * info->num_components);
+ for (ci = 0; ci < info->num_components; ci++) {
+ compptr = srcinfo->comp_info + ci;
+ coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+ ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->height_in_data_units,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->width_in_data_units,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) compptr->h_samp_factor);
+ }
+ break;
+ }
+ info->workspace_coef_arrays = coef_arrays;
+}
+
+
+/* Transpose destination image parameters */
+
+LOCAL(void)
+transpose_critical_parameters (j_compress_ptr dstinfo)
+{
+ int tblno, i, j, ci, itemp;
+ jpeg_component_info *compptr;
+ JQUANT_TBL *qtblptr;
+ JDIMENSION dtemp;
+ UINT16 qtemp;
+
+ /* Transpose basic image dimensions */
+ dtemp = dstinfo->image_width;
+ dstinfo->image_width = dstinfo->image_height;
+ dstinfo->image_height = dtemp;
+
+ /* Transpose sampling factors */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ itemp = compptr->h_samp_factor;
+ compptr->h_samp_factor = compptr->v_samp_factor;
+ compptr->v_samp_factor = itemp;
+ }
+
+ /* Transpose quantization tables */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ qtblptr = dstinfo->quant_tbl_ptrs[tblno];
+ if (qtblptr != NULL) {
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < i; j++) {
+ qtemp = qtblptr->quantval[i*DCTSIZE+j];
+ qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
+ qtblptr->quantval[j*DCTSIZE+i] = qtemp;
+ }
+ }
+ }
+ }
+}
+
+
+/* Trim off any partial iMCUs on the indicated destination edge */
+
+LOCAL(void)
+trim_right_edge (j_compress_ptr dstinfo)
+{
+ int ci, max_h_samp_factor;
+ JDIMENSION MCU_cols;
+
+ /* We have to compute max_h_samp_factor ourselves,
+ * because it hasn't been set yet in the destination
+ * (and we don't want to use the source's value).
+ */
+ max_h_samp_factor = 1;
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ int h_samp_factor = dstinfo->comp_info[ci].h_samp_factor;
+ max_h_samp_factor = MAX(max_h_samp_factor, h_samp_factor);
+ }
+ MCU_cols = dstinfo->image_width / (max_h_samp_factor * DCTSIZE);
+ if (MCU_cols > 0) /* can't trim to 0 pixels */
+ dstinfo->image_width = MCU_cols * (max_h_samp_factor * DCTSIZE);
+}
+
+LOCAL(void)
+trim_bottom_edge (j_compress_ptr dstinfo)
+{
+ int ci, max_v_samp_factor;
+ JDIMENSION MCU_rows;
+
+ /* We have to compute max_v_samp_factor ourselves,
+ * because it hasn't been set yet in the destination
+ * (and we don't want to use the source's value).
+ */
+ max_v_samp_factor = 1;
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ int v_samp_factor = dstinfo->comp_info[ci].v_samp_factor;
+ max_v_samp_factor = MAX(max_v_samp_factor, v_samp_factor);
+ }
+ MCU_rows = dstinfo->image_height / (max_v_samp_factor * DCTSIZE);
+ if (MCU_rows > 0) /* can't trim to 0 pixels */
+ dstinfo->image_height = MCU_rows * (max_v_samp_factor * DCTSIZE);
+}
+
+
+/* Adjust output image parameters as needed.
+ *
+ * This must be called after jpeg_copy_critical_parameters()
+ * and before jpeg_write_coefficients().
+ *
+ * The return value is the set of virtual coefficient arrays to be written
+ * (either the ones allocated by jtransform_request_workspace, or the
+ * original source data arrays). The caller will need to pass this value
+ * to jpeg_write_coefficients().
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jtransform_adjust_parameters (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ /* If force-to-grayscale is requested, adjust destination parameters */
+ if (info->force_grayscale) {
+ /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
+ * properly. Among other things, the target h_samp_factor & v_samp_factor
+ * will get set to 1, which typically won't match the source.
+ * In fact we do this even if the source is already grayscale; that
+ * provides an easy way of coercing a grayscale JPEG with funny sampling
+ * factors to the customary 1,1. (Some decoders fail on other factors.)
+ */
+ if ((dstinfo->jpeg_color_space == JCS_YCbCr &&
+ dstinfo->num_components == 3) ||
+ (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
+ dstinfo->num_components == 1)) {
+ /* We have to preserve the source's quantization table number. */
+ int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
+ jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
+ dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
+ } else {
+ /* Sorry, can't do it */
+ ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ }
+
+ /* Correct the destination's image dimensions etc if necessary */
+ switch (info->transform) {
+ case JXFORM_NONE:
+ /* Nothing to do */
+ break;
+ case JXFORM_FLIP_H:
+ if (info->trim)
+ trim_right_edge(dstinfo);
+ break;
+ case JXFORM_FLIP_V:
+ if (info->trim)
+ trim_bottom_edge(dstinfo);
+ break;
+ case JXFORM_TRANSPOSE:
+ transpose_critical_parameters(dstinfo);
+ /* transpose does NOT have to trim anything */
+ break;
+ case JXFORM_TRANSVERSE:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim) {
+ trim_right_edge(dstinfo);
+ trim_bottom_edge(dstinfo);
+ }
+ break;
+ case JXFORM_ROT_90:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim)
+ trim_right_edge(dstinfo);
+ break;
+ case JXFORM_ROT_180:
+ if (info->trim) {
+ trim_right_edge(dstinfo);
+ trim_bottom_edge(dstinfo);
+ }
+ break;
+ case JXFORM_ROT_270:
+ transpose_critical_parameters(dstinfo);
+ if (info->trim)
+ trim_bottom_edge(dstinfo);
+ break;
+ }
+
+ /* Return the appropriate output data set */
+ if (info->workspace_coef_arrays != NULL)
+ return info->workspace_coef_arrays;
+ return src_coef_arrays;
+}
+
+
+/* Execute the actual transformation, if any.
+ *
+ * This must be called *after* jpeg_write_coefficients, because it depends
+ * on jpeg_write_coefficients to have computed subsidiary values such as
+ * the per-component width and height fields in the destination object.
+ *
+ * Note that some transformations will modify the source data arrays!
+ */
+
+GLOBAL(void)
+jtransform_execute_transformation (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
+
+ switch (info->transform) {
+ case JXFORM_NONE:
+ break;
+ case JXFORM_FLIP_H:
+ do_flip_h(srcinfo, dstinfo, src_coef_arrays);
+ break;
+ case JXFORM_FLIP_V:
+ do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSPOSE:
+ do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSVERSE:
+ do_transverse(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_90:
+ do_rot_90(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_180:
+ do_rot_180(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_270:
+ do_rot_270(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+ break;
+ }
+}
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/* Setup decompression object to save desired markers in memory.
+ * This must be called before jpeg_read_header() to have the desired effect.
+ */
+
+GLOBAL(void)
+jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
+{
+#ifdef SAVE_MARKERS_SUPPORTED
+ int m;
+
+ /* Save comments except under NONE option */
+ if (option != JCOPYOPT_NONE) {
+ jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
+ }
+ /* Save all types of APPn markers iff ALL option */
+ if (option == JCOPYOPT_ALL) {
+ for (m = 0; m < 16; m++)
+ jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
+ }
+#endif /* SAVE_MARKERS_SUPPORTED */
+}
+
+/* Copy markers saved in the given source object to the destination object.
+ * This should be called just after jpeg_start_compress() or
+ * jpeg_write_coefficients().
+ * Note that those routines will have written the SOI, and also the
+ * JFIF APP0 or Adobe APP14 markers if selected.
+ */
+
+GLOBAL(void)
+jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION option)
+{
+ jpeg_saved_marker_ptr marker;
+
+ /* In the current implementation, we don't actually need to examine the
+ * option flag here; we just copy everything that got saved.
+ * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
+ * if the encoder library already wrote one.
+ */
+ for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (dstinfo->write_JFIF_header &&
+ marker->marker == JPEG_APP0 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x4A &&
+ GETJOCTET(marker->data[1]) == 0x46 &&
+ GETJOCTET(marker->data[2]) == 0x49 &&
+ GETJOCTET(marker->data[3]) == 0x46 &&
+ GETJOCTET(marker->data[4]) == 0)
+ continue; /* reject duplicate JFIF */
+ if (dstinfo->write_Adobe_marker &&
+ marker->marker == JPEG_APP0+14 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x41 &&
+ GETJOCTET(marker->data[1]) == 0x64 &&
+ GETJOCTET(marker->data[2]) == 0x6F &&
+ GETJOCTET(marker->data[3]) == 0x62 &&
+ GETJOCTET(marker->data[4]) == 0x65)
+ continue; /* reject duplicate Adobe */
+#ifdef NEED_FAR_POINTERS
+ /* We could use jpeg_write_marker if the data weren't FAR... */
+ {
+ unsigned int i;
+ jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
+ for (i = 0; i < marker->data_length; i++)
+ jpeg_write_m_byte(dstinfo, marker->data[i]);
+ }
+#else
+ jpeg_write_marker(dstinfo, marker->marker,
+ marker->data, marker->data_length);
+#endif
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.h b/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.h
new file mode 100644
index 00000000..5c2d32af
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/transupp.h
@@ -0,0 +1,135 @@
+/*
+ * transupp.h
+ *
+ * Copyright (C) 1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for image transformation routines and
+ * other utility code used by the jpegtran sample application. These are
+ * NOT part of the core JPEG library. But we keep these routines separate
+ * from jpegtran.c to ease the task of maintaining jpegtran-like programs
+ * that have other user interfaces.
+ *
+ * NOTE: all the routines declared here have very specific requirements
+ * about when they are to be executed during the reading and writing of the
+ * source and destination files. See the comments in transupp.c, or see
+ * jpegtran.c for an example of correct usage.
+ */
+
+/* If you happen not to want the image transform support, disable it here */
+#ifndef TRANSFORMS_SUPPORTED
+#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
+#endif
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jtransform_request_workspace jTrRequest
+#define jtransform_adjust_parameters jTrAdjust
+#define jtransform_execute_transformation jTrExec
+#define jcopy_markers_setup jCMrkSetup
+#define jcopy_markers_execute jCMrkExec
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * Codes for supported types of image transformations.
+ */
+
+typedef enum {
+ JXFORM_NONE, /* no transformation */
+ JXFORM_FLIP_H, /* horizontal flip */
+ JXFORM_FLIP_V, /* vertical flip */
+ JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
+ JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
+ JXFORM_ROT_90, /* 90-degree clockwise rotation */
+ JXFORM_ROT_180, /* 180-degree rotation */
+ JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
+} JXFORM_CODE;
+
+/*
+ * Although rotating and flipping data expressed as DCT coefficients is not
+ * hard, there is an asymmetry in the JPEG format specification for images
+ * whose dimensions aren't multiples of the iMCU size. The right and bottom
+ * image edges are padded out to the next iMCU boundary with junk data; but
+ * no padding is possible at the top and left edges. If we were to flip
+ * the whole image including the pad data, then pad garbage would become
+ * visible at the top and/or left, and real pixels would disappear into the
+ * pad margins --- perhaps permanently, since encoders & decoders may not
+ * bother to preserve DCT blocks that appear to be completely outside the
+ * nominal image area. So, we have to exclude any partial iMCUs from the
+ * basic transformation.
+ *
+ * Transpose is the only transformation that can handle partial iMCUs at the
+ * right and bottom edges completely cleanly. flip_h can flip partial iMCUs
+ * at the bottom, but leaves any partial iMCUs at the right edge untouched.
+ * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
+ * The other transforms are defined as combinations of these basic transforms
+ * and process edge blocks in a way that preserves the equivalence.
+ *
+ * The "trim" option causes untransformable partial iMCUs to be dropped;
+ * this is not strictly lossless, but it usually gives the best-looking
+ * result for odd-size images. Note that when this option is active,
+ * the expected mathematical equivalences between the transforms may not hold.
+ * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
+ * followed by -rot 180 -trim trims both edges.)
+ *
+ * We also offer a "force to grayscale" option, which simply discards the
+ * chrominance channels of a YCbCr image. This is lossless in the sense that
+ * the luminance channel is preserved exactly. It's not the same kind of
+ * thing as the rotate/flip transformations, but it's convenient to handle it
+ * as part of this package, mainly because the transformation routines have to
+ * be aware of the option to know how many components to work on.
+ */
+
+typedef struct {
+ /* Options: set by caller */
+ JXFORM_CODE transform; /* image transform operator */
+ boolean trim; /* if TRUE, trim partial MCUs as needed */
+ boolean force_grayscale; /* if TRUE, convert color image to grayscale */
+
+ /* Internal workspace: caller should not touch these */
+ int num_components; /* # of components in workspace */
+ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
+} jpeg_transform_info;
+
+
+#if TRANSFORMS_SUPPORTED
+
+/* Request any required workspace */
+EXTERN(void) jtransform_request_workspace
+ JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
+/* Adjust output image parameters */
+EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+/* Execute the actual transformation, if any */
+EXTERN(void) jtransform_execute_transformation
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/*
+ * Support for copying optional markers from source to destination file.
+ */
+
+typedef enum {
+ JCOPYOPT_NONE, /* copy no optional markers */
+ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
+ JCOPYOPT_ALL /* copy all optional markers */
+} JCOPY_OPTION;
+
+#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
+
+/* Setup decompression object to save desired markers in memory */
+EXTERN(void) jcopy_markers_setup
+ JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
+/* Copy markers saved in the given source object to the destination object */
+EXTERN(void) jcopy_markers_execute
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION option));
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/wrbmp.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrbmp.cpp
new file mode 100644
index 00000000..db9b8875
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrbmp.cpp
@@ -0,0 +1,443 @@
+/*
+ * wrbmp.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in Microsoft "BMP"
+ * format (MS Windows 3.x and OS/2 1.x flavors).
+ * Either 8-bit colormapped or 24-bit full-color format can be written.
+ * No compression is supported.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * This code contributed by James Arthur Boucher.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef BMP_SUPPORTED
+
+
+/*
+ * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
+ * This is not yet implemented.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ //Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+/*
+ * Since BMP stores scanlines bottom-to-top, we have to invert the image
+ * from JPEG's top-to-bottom order. To do this, we save the outgoing data
+ * in a virtual array during put_pixel_row calls, then actually emit the
+ * BMP file during finish_output. The virtual array contains one JSAMPLE per
+ * pixel if the output is grayscale or colormapped, three if it is full color.
+ */
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ boolean is_os2; /* saves the OS2 format request flag */
+
+ jvirt_sarray_ptr whole_image; /* needed to reverse row order */
+ JDIMENSION data_width; /* JSAMPLEs per row */
+ JDIMENSION row_width; /* physical width of one row in the BMP file */
+ int pad_bytes; /* number of padding bytes needed per row */
+ JDIMENSION cur_output_row; /* next row# to write to virtual array */
+} bmp_dest_struct;
+
+typedef bmp_dest_struct * bmp_dest_ptr;
+
+
+/* Forward declarations */
+LOCAL(void) write_colormap
+ JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest,
+ int map_colors, int map_entry_size));
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* This version is for writing 24-bit pixels */
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ int pad;
+
+ /* Access next row in virtual array */
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image,
+ dest->cur_output_row, (JDIMENSION) 1, TRUE);
+ dest->cur_output_row++;
+
+ /* Transfer data. Note destination values must be in BGR order
+ * (even though Microsoft's own documents say the opposite).
+ */
+ inptr = dest->pub.buffer[0];
+ outptr = image_ptr[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
+ outptr[1] = *inptr++;
+ outptr[0] = *inptr++;
+ outptr += 3;
+ }
+
+ /* Zero out the pad bytes. */
+ pad = dest->pad_bytes;
+ while (--pad >= 0)
+ *outptr++ = 0;
+}
+
+METHODDEF(void)
+put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* This version is for grayscale OR quantized color output */
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ int pad;
+
+ /* Access next row in virtual array */
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image,
+ dest->cur_output_row, (JDIMENSION) 1, TRUE);
+ dest->cur_output_row++;
+
+ /* Transfer data. */
+ inptr = dest->pub.buffer[0];
+ outptr = image_ptr[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = *inptr++; /* can omit GETJSAMPLE() safely */
+ }
+
+ /* Zero out the pad bytes. */
+ pad = dest->pad_bytes;
+ while (--pad >= 0)
+ *outptr++ = 0;
+}
+
+
+/*
+ * Startup: normally writes the file header.
+ * In this module we may as well postpone everything until finish_output.
+ */
+
+METHODDEF(void)
+start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* no work here */
+}
+
+
+/*
+ * Finish up at the end of the file.
+ *
+ * Here is where we really output the BMP file.
+ *
+ * First, routines to write the Windows and OS/2 variants of the file header.
+ */
+
+LOCAL(void)
+write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
+/* Write a Windows-style BMP file header, including colormap if needed */
+{
+ char bmpfileheader[14];
+ char bmpinfoheader[40];
+#define PUT_2B(array,offset,value) \
+ (array[offset] = (char) ((value) & 0xFF), \
+ array[offset+1] = (char) (((value) >> 8) & 0xFF))
+#define PUT_4B(array,offset,value) \
+ (array[offset] = (char) ((value) & 0xFF), \
+ array[offset+1] = (char) (((value) >> 8) & 0xFF), \
+ array[offset+2] = (char) (((value) >> 16) & 0xFF), \
+ array[offset+3] = (char) (((value) >> 24) & 0xFF))
+ INT32 headersize, bfSize;
+ int bits_per_pixel, cmap_entries;
+
+ /* Compute colormap size and total file size */
+ if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* Colormapped RGB */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ } else {
+ /* Unquantized, full color RGB */
+ bits_per_pixel = 24;
+ cmap_entries = 0;
+ }
+ } else {
+ /* Grayscale output. We need to fake a 256-entry colormap. */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ }
+ /* File size */
+ headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */
+ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
+ MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader));
+
+ /* Fill the file header */
+ bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
+ bmpfileheader[1] = 0x4D;
+ PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
+ /* we leave bfReserved1 & bfReserved2 = 0 */
+ PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
+
+ /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */
+ PUT_2B(bmpinfoheader, 0, 40); /* biSize */
+ PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */
+ PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */
+ PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */
+ PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */
+ /* we leave biCompression = 0, for none */
+ /* we leave biSizeImage = 0; this is correct for uncompressed data */
+ if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */
+ PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */
+ PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */
+ }
+ PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */
+ /* we leave biClrImportant = 0 */
+
+ if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ if (cmap_entries > 0)
+ write_colormap(cinfo, dest, cmap_entries, 4);
+}
+
+
+LOCAL(void)
+write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
+/* Write an OS2-style BMP file header, including colormap if needed */
+{
+ char bmpfileheader[14];
+ char bmpcoreheader[12];
+ INT32 headersize, bfSize;
+ int bits_per_pixel, cmap_entries;
+
+ /* Compute colormap size and total file size */
+ if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* Colormapped RGB */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ } else {
+ /* Unquantized, full color RGB */
+ bits_per_pixel = 24;
+ cmap_entries = 0;
+ }
+ } else {
+ /* Grayscale output. We need to fake a 256-entry colormap. */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ }
+ /* File size */
+ headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */
+ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
+ MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader));
+
+ /* Fill the file header */
+ bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
+ bmpfileheader[1] = 0x4D;
+ PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
+ /* we leave bfReserved1 & bfReserved2 = 0 */
+ PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
+
+ /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */
+ PUT_2B(bmpcoreheader, 0, 12); /* bcSize */
+ PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */
+ PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */
+ PUT_2B(bmpcoreheader, 8, 1); /* bcPlanes - must be 1 */
+ PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */
+
+ if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ if (cmap_entries > 0)
+ write_colormap(cinfo, dest, cmap_entries, 3);
+}
+
+
+/*
+ * Write the colormap.
+ * Windows uses BGR0 map entries; OS/2 uses BGR entries.
+ */
+
+LOCAL(void)
+write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest,
+ int map_colors, int map_entry_size)
+{
+ JSAMPARRAY colormap = cinfo->colormap;
+ int num_colors = cinfo->actual_number_of_colors;
+ FILE * outfile = dest->pub.output_file;
+ int i;
+
+ if (colormap != NULL) {
+ if (cinfo->out_color_components == 3) {
+ /* Normal case with RGB colormap */
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(colormap[2][i]), outfile);
+ putc(GETJSAMPLE(colormap[1][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ } else {
+ /* Grayscale colormap (only happens with grayscale quantization) */
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ }
+ } else {
+ /* If no colormap, must be grayscale data. Generate a linear "map". */
+ for (i = 0; i < 256; i++) {
+ putc(i, outfile);
+ putc(i, outfile);
+ putc(i, outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ }
+ /* Pad colormap with zeros to ensure specified number of colormap entries */
+ if (i > map_colors)
+ ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i);
+ for (; i < map_colors; i++) {
+ putc(0, outfile);
+ putc(0, outfile);
+ putc(0, outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+}
+
+
+METHODDEF(void)
+finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ register FILE * outfile = dest->pub.output_file;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW data_ptr;
+ JDIMENSION row;
+ register JDIMENSION col;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Write the header and colormap */
+ if (dest->is_os2)
+ write_os2_header(cinfo, dest);
+ else
+ write_bmp_header(cinfo, dest);
+
+ /* Write the file body from our virtual array */
+ for (row = cinfo->output_height; row > 0; row--) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) (cinfo->output_height - row);
+ progress->pub.pass_limit = (long) cinfo->output_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE);
+ data_ptr = image_ptr[0];
+ for (col = dest->row_width; col > 0; col--) {
+ putc(GETJSAMPLE(*data_ptr), outfile);
+ data_ptr++;
+ }
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Make sure we wrote the output file OK */
+ fflush(outfile);
+ if (ferror(outfile))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for BMP format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
+{
+ bmp_dest_ptr dest;
+ JDIMENSION row_width;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (bmp_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(bmp_dest_struct));
+ dest->pub.start_output = start_output_bmp;
+ dest->pub.finish_output = finish_output_bmp;
+ dest->is_os2 = is_os2;
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = put_gray_rows;
+ else
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ } else {
+ ERREXIT(cinfo, JERR_BMP_COLORSPACE);
+ }
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Determine width of rows in the BMP file (padded to 4-byte boundary). */
+ row_width = cinfo->output_width * cinfo->output_components;
+ dest->data_width = row_width;
+ while ((row_width & 3) != 0) row_width++;
+ dest->row_width = row_width;
+ dest->pad_bytes = (int) (row_width - dest->data_width);
+
+ /* Allocate space for inversion array, prepare for write pass */
+ dest->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ row_width, cinfo->output_height, (JDIMENSION) 1);
+ dest->cur_output_row = 0;
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* BMP_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/wrgif.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrgif.cpp
new file mode 100644
index 00000000..6a631fc0
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrgif.cpp
@@ -0,0 +1,400 @@
+/*
+ * wrgif.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in GIF format.
+ *
+ **************************************************************************
+ * NOTE: to avoid entanglements with Unisys' patent on LZW compression, *
+ * this code has been modified to output "uncompressed GIF" files. *
+ * There is no trace of the LZW algorithm in this file. *
+ **************************************************************************
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ */
+
+/*
+ * This code is loosely based on ppmtogif from the PBMPLUS distribution
+ * of Feb. 1991. That file contains the following copyright notice:
+ * Based on GIFENCODE by David Rowley <[email protected]>.
+ * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
+ * Copyright (C) 1989 by Jef Poskanzer.
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "as is" without express or
+ * implied warranty.
+ *
+ * We are also required to state that
+ * "The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated."
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef GIF_SUPPORTED
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ j_decompress_ptr cinfo; /* back link saves passing separate parm */
+
+ /* State for packing variable-width codes into a bitstream */
+ int n_bits; /* current number of bits/code */
+ int maxcode; /* maximum code, given n_bits */
+ INT32 cur_accum; /* holds bits not yet output */
+ int cur_bits; /* # of bits in cur_accum */
+
+ /* State for GIF code assignment */
+ int ClearCode; /* clear code (doesn't change) */
+ int EOFCode; /* EOF code (ditto) */
+ int code_counter; /* counts output symbols */
+
+ /* GIF data packet construction buffer */
+ int bytesinpkt; /* # of bytes in current packet */
+ char packetbuf[256]; /* workspace for accumulating packet */
+
+} gif_dest_struct;
+
+typedef gif_dest_struct * gif_dest_ptr;
+
+/* Largest value that will fit in N bits */
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+
+/*
+ * Routines to package finished data bytes into GIF data blocks.
+ * A data block consists of a count byte (1..255) and that many data bytes.
+ */
+
+LOCAL(void)
+flush_packet (gif_dest_ptr dinfo)
+/* flush any accumulated data */
+{
+ if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */
+ dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++;
+ if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt)
+ != (size_t) dinfo->bytesinpkt)
+ ERREXIT(dinfo->cinfo, JERR_FILE_WRITE);
+ dinfo->bytesinpkt = 0;
+ }
+}
+
+
+/* Add a character to current packet; flush to disk if necessary */
+#define CHAR_OUT(dinfo,c) \
+ { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c); \
+ if ((dinfo)->bytesinpkt >= 255) \
+ flush_packet(dinfo); \
+ }
+
+
+/* Routine to convert variable-width codes into a byte stream */
+
+LOCAL(void)
+output (gif_dest_ptr dinfo, int code)
+/* Emit a code of n_bits bits */
+/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
+{
+ dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits;
+ dinfo->cur_bits += dinfo->n_bits;
+
+ while (dinfo->cur_bits >= 8) {
+ CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
+ dinfo->cur_accum >>= 8;
+ dinfo->cur_bits -= 8;
+ }
+}
+
+
+/* The pseudo-compression algorithm.
+ *
+ * In this module we simply output each pixel value as a separate symbol;
+ * thus, no compression occurs. In fact, there is expansion of one bit per
+ * pixel, because we use a symbol width one bit wider than the pixel width.
+ *
+ * GIF ordinarily uses variable-width symbols, and the decoder will expect
+ * to ratchet up the symbol width after a fixed number of symbols.
+ * To simplify the logic and keep the expansion penalty down, we emit a
+ * GIF Clear code to reset the decoder just before the width would ratchet up.
+ * Thus, all the symbols in the output file will have the same bit width.
+ * Note that emitting the Clear codes at the right times is a mere matter of
+ * counting output symbols and is in no way dependent on the LZW patent.
+ *
+ * With a small basic pixel width (low color count), Clear codes will be
+ * needed very frequently, causing the file to expand even more. So this
+ * simplistic approach wouldn't work too well on bilevel images, for example.
+ * But for output of JPEG conversions the pixel width will usually be 8 bits
+ * (129 to 256 colors), so the overhead added by Clear symbols is only about
+ * one symbol in every 256.
+ */
+
+LOCAL(void)
+compress_init (gif_dest_ptr dinfo, int i_bits)
+/* Initialize pseudo-compressor */
+{
+ /* init all the state variables */
+ dinfo->n_bits = i_bits;
+ dinfo->maxcode = MAXCODE(dinfo->n_bits);
+ dinfo->ClearCode = (1 << (i_bits - 1));
+ dinfo->EOFCode = dinfo->ClearCode + 1;
+ dinfo->code_counter = dinfo->ClearCode + 2;
+ /* init output buffering vars */
+ dinfo->bytesinpkt = 0;
+ dinfo->cur_accum = 0;
+ dinfo->cur_bits = 0;
+ /* GIF specifies an initial Clear code */
+ output(dinfo, dinfo->ClearCode);
+}
+
+
+LOCAL(void)
+compress_pixel (gif_dest_ptr dinfo, int c)
+/* Accept and "compress" one pixel value.
+ * The given value must be less than n_bits wide.
+ */
+{
+ /* Output the given pixel value as a symbol. */
+ output(dinfo, c);
+ /* Issue Clear codes often enough to keep the reader from ratcheting up
+ * its symbol size.
+ */
+ if (dinfo->code_counter < dinfo->maxcode) {
+ dinfo->code_counter++;
+ } else {
+ output(dinfo, dinfo->ClearCode);
+ dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */
+ }
+}
+
+
+LOCAL(void)
+compress_term (gif_dest_ptr dinfo)
+/* Clean up at end */
+{
+ /* Send an EOF code */
+ output(dinfo, dinfo->EOFCode);
+ /* Flush the bit-packing buffer */
+ if (dinfo->cur_bits > 0) {
+ CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
+ }
+ /* Flush the packet buffer */
+ flush_packet(dinfo);
+}
+
+
+/* GIF header construction */
+
+
+LOCAL(void)
+put_word (gif_dest_ptr dinfo, unsigned int w)
+/* Emit a 16-bit word, LSB first */
+{
+ putc(w & 0xFF, dinfo->pub.output_file);
+ putc((w >> 8) & 0xFF, dinfo->pub.output_file);
+}
+
+
+LOCAL(void)
+put_3bytes (gif_dest_ptr dinfo, int val)
+/* Emit 3 copies of same byte value --- handy subr for colormap construction */
+{
+ putc(val, dinfo->pub.output_file);
+ putc(val, dinfo->pub.output_file);
+ putc(val, dinfo->pub.output_file);
+}
+
+
+LOCAL(void)
+emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap)
+/* Output the GIF file header, including color map */
+/* If colormap==NULL, synthesize a gray-scale colormap */
+{
+ int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
+ int cshift = dinfo->cinfo->data_precision - 8;
+ int i;
+
+ if (num_colors > 256)
+ ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors);
+ /* Compute bits/pixel and related values */
+ BitsPerPixel = 1;
+ while (num_colors > (1 << BitsPerPixel))
+ BitsPerPixel++;
+ ColorMapSize = 1 << BitsPerPixel;
+ if (BitsPerPixel <= 1)
+ InitCodeSize = 2;
+ else
+ InitCodeSize = BitsPerPixel;
+ /*
+ * Write the GIF header.
+ * Note that we generate a plain GIF87 header for maximum compatibility.
+ */
+ putc('G', dinfo->pub.output_file);
+ putc('I', dinfo->pub.output_file);
+ putc('F', dinfo->pub.output_file);
+ putc('8', dinfo->pub.output_file);
+ putc('7', dinfo->pub.output_file);
+ putc('a', dinfo->pub.output_file);
+ /* Write the Logical Screen Descriptor */
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_width);
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
+ FlagByte = 0x80; /* Yes, there is a global color table */
+ FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
+ FlagByte |= (BitsPerPixel-1); /* size of global color table */
+ putc(FlagByte, dinfo->pub.output_file);
+ putc(0, dinfo->pub.output_file); /* Background color index */
+ putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */
+ /* Write the Global Color Map */
+ /* If the color map is more than 8 bits precision, */
+ /* we reduce it to 8 bits by shifting */
+ for (i=0; i < ColorMapSize; i++) {
+ if (i < num_colors) {
+ if (colormap != NULL) {
+ if (dinfo->cinfo->out_color_space == JCS_RGB) {
+ /* Normal case: RGB color map */
+ putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file);
+ putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file);
+ putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file);
+ } else {
+ /* Grayscale "color map": possible if quantizing grayscale image */
+ put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift);
+ }
+ } else {
+ /* Create a gray-scale map of num_colors values, range 0..255 */
+ put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1));
+ }
+ } else {
+ /* fill out the map to a power of 2 */
+ put_3bytes(dinfo, 0);
+ }
+ }
+ /* Write image separator and Image Descriptor */
+ putc(',', dinfo->pub.output_file); /* separator */
+ put_word(dinfo, 0); /* left/top offset */
+ put_word(dinfo, 0);
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
+ /* flag byte: not interlaced, no local color map */
+ putc(0x00, dinfo->pub.output_file);
+ /* Write Initial Code Size byte */
+ putc(InitCodeSize, dinfo->pub.output_file);
+
+ /* Initialize for "compression" of image data */
+ compress_init(dinfo, InitCodeSize+1);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+
+ if (cinfo->quantize_colors)
+ emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap);
+ else
+ emit_header(dest, 256, (JSAMPARRAY) NULL);
+}
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ compress_pixel(dest, GETJSAMPLE(*ptr++));
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+
+ /* Flush "compression" mechanism */
+ compress_term(dest);
+ /* Write a zero-length data block to end the series */
+ putc(0, dest->pub.output_file);
+ /* Write the GIF terminator mark */
+ putc(';', dest->pub.output_file);
+ /* Make sure we wrote the output file OK */
+ fflush(dest->pub.output_file);
+ if (ferror(dest->pub.output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for GIF format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_gif (j_decompress_ptr cinfo)
+{
+ gif_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (gif_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(gif_dest_struct));
+ dest->cinfo = cinfo; /* make back link for subroutines */
+ dest->pub.start_output = start_output_gif;
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ dest->pub.finish_output = finish_output_gif;
+
+ if (cinfo->out_color_space != JCS_GRAYSCALE &&
+ cinfo->out_color_space != JCS_RGB)
+ ERREXIT(cinfo, JERR_GIF_COLORSPACE);
+
+ /* Force quantization if color or if > 8 bits input */
+ if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) {
+ /* Force quantization to at most 256 colors */
+ cinfo->quantize_colors = TRUE;
+ if (cinfo->desired_number_of_colors > 256)
+ cinfo->desired_number_of_colors = 256;
+ }
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ if (cinfo->output_components != 1) /* safety check: just one component? */
+ ERREXIT(cinfo, JERR_GIF_BUG);
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/wrppm.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrppm.cpp
new file mode 100644
index 00000000..b52a1d7b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrppm.cpp
@@ -0,0 +1,269 @@
+/*
+ * wrppm.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in PPM/PGM format.
+ * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
+ * The PBMPLUS library is NOT required to compile this software
+ * (but it is highly useful as a set of PPM image manipulation programs).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef PPM_SUPPORTED
+
+
+/*
+ * For 12-bit JPEG data, we either downscale the values to 8 bits
+ * (to write standard byte-per-sample PPM/PGM files), or output
+ * nonstandard word-per-sample PPM/PGM files. Downscaling is done
+ * if PPM_NORAWWORD is defined (this can be done in the Makefile
+ * or in jconfig.h).
+ * (When the core library supports data precision reduction, a cleaner
+ * implementation will be to ask for that instead.)
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) (v)
+#define BYTESPERSAMPLE 1
+#define PPM_MAXVAL 255
+#else
+#ifdef PPM_NORAWWORD
+#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8))
+#define BYTESPERSAMPLE 1
+#define PPM_MAXVAL 255
+#else
+/* The word-per-sample format always puts the LSB first. */
+#define PUTPPMSAMPLE(ptr,v) \
+ { register int val_ = v; \
+ *ptr++ = (char) (val_ & 0xFF); \
+ *ptr++ = (char) ((val_ >> 8) & 0xFF); \
+ }
+#define BYTESPERSAMPLE 2
+#define PPM_MAXVAL ((1<<BITS_IN_JSAMPLE)-1)
+#endif
+#endif
+
+
+/*
+ * When JSAMPLE is the same size as char, we can just fwrite() the
+ * decompressed data to the PPM or PGM file. On PCs, in order to make this
+ * work the output buffer must be allocated in near data space, because we are
+ * assuming small-data memory model wherein fwrite() can't reach far memory.
+ * If you need to process very wide images on a PC, you might have to compile
+ * in large-memory model, or else replace fwrite() with a putc() loop ---
+ * which will be much slower.
+ */
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ /* Usually these two pointers point to the same place: */
+ char *iobuffer; /* fwrite's I/O buffer */
+ JSAMPROW pixrow; /* decompressor output buffer */
+ size_t buffer_width; /* width of I/O buffer */
+ JDIMENSION samples_per_row; /* JSAMPLEs per output row */
+} ppm_dest_struct;
+
+typedef ppm_dest_struct * ppm_dest_ptr;
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ *
+ * put_pixel_rows handles the "normal" 8-bit case where the decompressor
+ * output buffer is physically the same as the fwrite buffer.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * This code is used when we have to copy the data and apply a pixel
+ * format translation. Typically this only happens in 12-bit mode.
+ */
+
+METHODDEF(void)
+copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = dest->samples_per_row; col > 0; col--) {
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Write some pixel data when color quantization is in effect.
+ * We have to demap the color index values to straight data.
+ */
+
+METHODDEF(void)
+put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register int pixval;
+ register JSAMPROW ptr;
+ register JSAMPROW color_map0 = cinfo->colormap[0];
+ register JSAMPROW color_map1 = cinfo->colormap[1];
+ register JSAMPROW color_map2 = cinfo->colormap[2];
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ pixval = GETJSAMPLE(*ptr++);
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval]));
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval]));
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval]));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+METHODDEF(void)
+put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register JSAMPROW ptr;
+ register JSAMPROW color_map = cinfo->colormap[0];
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+
+ /* Emit file header */
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ /* emit header for raw PGM format */
+ fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n",
+ (long) cinfo->output_width, (long) cinfo->output_height,
+ PPM_MAXVAL);
+ break;
+ case JCS_RGB:
+ /* emit header for raw PPM format */
+ fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n",
+ (long) cinfo->output_width, (long) cinfo->output_height,
+ PPM_MAXVAL);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_PPM_COLORSPACE);
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* Make sure we wrote the output file OK */
+ fflush(dinfo->output_file);
+ if (ferror(dinfo->output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for PPM format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_ppm (j_decompress_ptr cinfo)
+{
+ ppm_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (ppm_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ppm_dest_struct));
+ dest->pub.start_output = start_output_ppm;
+ dest->pub.finish_output = finish_output_ppm;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Create physical I/O buffer. Note we make this near on a PC. */
+ dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
+ dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char));
+ dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);
+
+ if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 ||
+ SIZEOF(JSAMPLE) != SIZEOF(char)) {
+ /* When quantizing, we need an output buffer for colormap indexes
+ * that's separate from the physical I/O buffer. We also need a
+ * separate buffer if pixel format translation must take place.
+ */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width * cinfo->output_components, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+ if (! cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = copy_pixel_rows;
+ else if (cinfo->out_color_space == JCS_GRAYSCALE)
+ dest->pub.put_pixel_rows = put_demapped_gray;
+ else
+ dest->pub.put_pixel_rows = put_demapped_rgb;
+ } else {
+ /* We will fwrite() directly from decompressor output buffer. */
+ /* Synthesize a JSAMPARRAY pointer structure */
+ /* Cast here implies near->far pointer conversion on PCs */
+ dest->pixrow = (JSAMPROW) dest->iobuffer;
+ dest->pub.buffer = & dest->pixrow;
+ dest->pub.buffer_height = 1;
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ }
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/wrrle.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrrle.cpp
new file mode 100644
index 00000000..87e81739
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrrle.cpp
@@ -0,0 +1,306 @@
+/*
+ * wrrle.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in RLE format.
+ * The Utah Raster Toolkit library is required (version 3.1 or later).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * Based on code contributed by Mike Lijewski,
+ * with updates from Robert Hutchinson.
+ */
+#include "stdafx.h"
+
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef RLE_SUPPORTED
+
+/* rle.h is provided by the Utah Raster Toolkit. */
+
+#include <rle.h>
+
+/*
+ * We assume that JSAMPLE has the same representation as rle_pixel,
+ * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Since RLE stores scanlines bottom-to-top, we have to invert the image
+ * from JPEG's top-to-bottom order. To do this, we save the outgoing data
+ * in a virtual array during put_pixel_row calls, then actually emit the
+ * RLE file during finish_output.
+ */
+
+
+/*
+ * For now, if we emit an RLE color map then it is always 256 entries long,
+ * though not all of the entries need be used.
+ */
+
+#define CMAPBITS 8
+#define CMAPLENGTH (1<<(CMAPBITS))
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ jvirt_sarray_ptr image; /* virtual array to store the output image */
+ rle_map *colormap; /* RLE-style color map, or NULL if none */
+ rle_pixel **rle_row; /* To pass rows to rle_putrow() */
+
+} rle_dest_struct;
+
+typedef rle_dest_struct * rle_dest_ptr;
+
+/* Forward declarations */
+METHODDEF(void) rle_put_pixel_rows
+ JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied));
+
+
+/*
+ * Write the file header.
+ *
+ * In this module it's easier to wait till finish_output to write anything.
+ */
+
+METHODDEF(void)
+start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+ size_t cmapsize;
+ int i, ci;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /*
+ * Make sure the image can be stored in RLE format.
+ *
+ * - RLE stores image dimensions as *signed* 16 bit integers. JPEG
+ * uses unsigned, so we have to check the width.
+ *
+ * - Colorspace is expected to be grayscale or RGB.
+ *
+ * - The number of channels (components) is expected to be 1 (grayscale/
+ * pseudocolor) or 3 (truecolor/directcolor).
+ * (could be 2 or 4 if using an alpha channel, but we aren't)
+ */
+
+ if (cinfo->output_width > 32767 || cinfo->output_height > 32767)
+ ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width,
+ cinfo->output_height);
+
+ if (cinfo->out_color_space != JCS_GRAYSCALE &&
+ cinfo->out_color_space != JCS_RGB)
+ ERREXIT(cinfo, JERR_RLE_COLORSPACE);
+
+ if (cinfo->output_components != 1 && cinfo->output_components != 3)
+ ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components);
+
+ /* Convert colormap, if any, to RLE format. */
+
+ dest->colormap = NULL;
+
+ if (cinfo->quantize_colors) {
+ /* Allocate storage for RLE-style cmap, zero any extra entries */
+ cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map);
+ dest->colormap = (rle_map *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize);
+ MEMZERO(dest->colormap, cmapsize);
+
+ /* Save away data in RLE format --- note 8-bit left shift! */
+ /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
+ for (ci = 0; ci < cinfo->out_color_components; ci++) {
+ for (i = 0; i < cinfo->actual_number_of_colors; i++) {
+ dest->colormap[ci * CMAPLENGTH + i] =
+ GETJSAMPLE(cinfo->colormap[ci][i]) << 8;
+ }
+ }
+ }
+
+ /* Set the output buffer to the first row */
+ dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE);
+ dest->pub.buffer_height = 1;
+
+ dest->pub.put_pixel_rows = rle_put_pixel_rows;
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->total_extra_passes++; /* count file writing as separate pass */
+ }
+#endif
+}
+
+
+/*
+ * Write some pixel data.
+ *
+ * This routine just saves the data away in a virtual array.
+ */
+
+METHODDEF(void)
+rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+
+ if (cinfo->output_scanline < cinfo->output_height) {
+ dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ cinfo->output_scanline, (JDIMENSION) 1, TRUE);
+ }
+}
+
+/*
+ * Finish up at the end of the file.
+ *
+ * Here is where we really output the RLE file.
+ */
+
+METHODDEF(void)
+finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+ rle_hdr header; /* Output file information */
+ rle_pixel **rle_row, *red, *green, *blue;
+ JSAMPROW output_row;
+ char cmapcomment[80];
+ int row, col;
+ int ci;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /* Initialize the header info */
+ header = *rle_hdr_init(NULL);
+ header.rle_file = dest->pub.output_file;
+ header.xmin = 0;
+ header.xmax = cinfo->output_width - 1;
+ header.ymin = 0;
+ header.ymax = cinfo->output_height - 1;
+ header.alpha = 0;
+ header.ncolors = cinfo->output_components;
+ for (ci = 0; ci < cinfo->output_components; ci++) {
+ RLE_SET_BIT(header, ci);
+ }
+ if (cinfo->quantize_colors) {
+ header.ncmap = cinfo->out_color_components;
+ header.cmaplen = CMAPBITS;
+ header.cmap = dest->colormap;
+ /* Add a comment to the output image with the true colormap length. */
+ sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors);
+ rle_putcom(cmapcomment, &header);
+ }
+
+ /* Emit the RLE header and color map (if any) */
+ rle_put_setup(&header);
+
+ /* Now output the RLE data from our virtual array.
+ * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
+ * and (b) we are not on a machine where FAR pointers differ from regular.
+ */
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_limit = cinfo->output_height;
+ progress->pub.pass_counter = 0;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+
+ if (cinfo->output_components == 1) {
+ for (row = cinfo->output_height-1; row >= 0; row--) {
+ rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ (JDIMENSION) row, (JDIMENSION) 1, FALSE);
+ rle_putrow(rle_row, (int) cinfo->output_width, &header);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ } else {
+ for (row = cinfo->output_height-1; row >= 0; row--) {
+ rle_row = (rle_pixel **) dest->rle_row;
+ output_row = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ (JDIMENSION) row, (JDIMENSION) 1, FALSE);
+ red = rle_row[0];
+ green = rle_row[1];
+ blue = rle_row[2];
+ for (col = cinfo->output_width; col > 0; col--) {
+ *red++ = GETJSAMPLE(*output_row++);
+ *green++ = GETJSAMPLE(*output_row++);
+ *blue++ = GETJSAMPLE(*output_row++);
+ }
+ rle_putrow(rle_row, (int) cinfo->output_width, &header);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+#endif
+
+ /* Emit file trailer */
+ rle_puteof(&header);
+ fflush(dest->pub.output_file);
+ if (ferror(dest->pub.output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for RLE format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_rle (j_decompress_ptr cinfo)
+{
+ rle_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (rle_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(rle_dest_struct));
+ dest->pub.start_output = start_output_rle;
+ dest->pub.finish_output = finish_output_rle;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Allocate a work array for output to the RLE library. */
+ dest->rle_row = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width, (JDIMENSION) cinfo->output_components);
+
+ /* Allocate a virtual array to hold the image. */
+ dest->image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) (cinfo->output_width * cinfo->output_components),
+ cinfo->output_height, (JDIMENSION) 1);
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* RLE_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/IJGWin32/wrtarga.cpp b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrtarga.cpp
new file mode 100644
index 00000000..1227789d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/IJGWin32/wrtarga.cpp
@@ -0,0 +1,253 @@
+/*
+ * wrtarga.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in Targa format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * Based on code contributed by Lee Daniel Crocker.
+ */
+#include "stdafx.h"
+//#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef TARGA_SUPPORTED
+
+
+/*
+ * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
+ * This is not yet implemented.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+
+#endif
+
+/*
+ * The output buffer needs to be writable by fwrite(). On PCs, we must
+ * allocate the buffer in near data space, because we are assuming small-data
+ * memory model, wherein fwrite() can't reach far memory. If you need to
+ * process very wide images on a PC, you might have to compile in large-memory
+ * model, or else replace fwrite() with a putc() loop --- which will be much
+ * slower.
+ */
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ char *iobuffer; /* physical I/O buffer */
+ JDIMENSION buffer_width; /* width of one row */
+} tga_dest_struct;
+
+typedef tga_dest_struct * tga_dest_ptr;
+
+
+LOCAL(void)
+write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
+/* Create and write a Targa header */
+{
+ char targaheader[18];
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(targaheader, SIZEOF(targaheader));
+
+ if (num_colors > 0) {
+ targaheader[1] = 1; /* color map type 1 */
+ targaheader[5] = (char) (num_colors & 0xFF);
+ targaheader[6] = (char) (num_colors >> 8);
+ targaheader[7] = 24; /* 24 bits per cmap entry */
+ }
+
+ targaheader[12] = (char) (cinfo->output_width & 0xFF);
+ targaheader[13] = (char) (cinfo->output_width >> 8);
+ targaheader[14] = (char) (cinfo->output_height & 0xFF);
+ targaheader[15] = (char) (cinfo->output_height >> 8);
+ targaheader[17] = 0x20; /* Top-down, non-interlaced */
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ targaheader[2] = 3; /* image type = uncompressed gray-scale */
+ targaheader[16] = 8; /* bits per pixel */
+ } else { /* must be RGB */
+ if (num_colors > 0) {
+ targaheader[2] = 1; /* image type = colormapped RGB */
+ targaheader[16] = 8;
+ } else {
+ targaheader[2] = 2; /* image type = uncompressed RGB */
+ targaheader[16] = 24;
+ }
+ }
+
+ if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* used for unquantized full-color output */
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
+ outptr[1] = (char) GETJSAMPLE(inptr[1]);
+ outptr[2] = (char) GETJSAMPLE(inptr[0]);
+ inptr += 3, outptr += 3;
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+METHODDEF(void)
+put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* used for grayscale OR quantized color output */
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = (char) GETJSAMPLE(*inptr++);
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Write some demapped pixel data when color quantization is in effect.
+ * For Targa, this is only applied to grayscale data.
+ */
+
+METHODDEF(void)
+put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JSAMPROW color_map0 = cinfo->colormap[0];
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ int num_colors, i;
+ FILE *outfile;
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ /* Targa doesn't have a mapped grayscale format, so we will */
+ /* demap quantized gray output. Never emit a colormap. */
+ write_header(cinfo, dinfo, 0);
+ if (cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = put_demapped_gray;
+ else
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* We only support 8-bit colormap indexes, so only 256 colors */
+ num_colors = cinfo->actual_number_of_colors;
+ if (num_colors > 256)
+ ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
+ write_header(cinfo, dinfo, num_colors);
+ /* Write the colormap. Note Targa uses BGR byte order */
+ outfile = dest->pub.output_file;
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
+ putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
+ putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
+ }
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else {
+ write_header(cinfo, dinfo, 0);
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ }
+ } else {
+ ERREXIT(cinfo, JERR_TGA_COLORSPACE);
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* Make sure we wrote the output file OK */
+ fflush(dinfo->output_file);
+ if (ferror(dinfo->output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for Targa format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_targa (j_decompress_ptr cinfo)
+{
+ tga_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (tga_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(tga_dest_struct));
+ dest->pub.start_output = start_output_tga;
+ dest->pub.finish_output = finish_output_tga;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Create I/O buffer. Note we make this near on a PC. */
+ dest->buffer_width = cinfo->output_width * cinfo->output_components;
+ dest->iobuffer = (char *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (dest->buffer_width * SIZEOF(char)));
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* TARGA_SUPPORTED */
diff --git a/KaplaDemo/samples/sampleViewer3/MathUtils.cpp b/KaplaDemo/samples/sampleViewer3/MathUtils.cpp
new file mode 100644
index 00000000..e6a0ba1c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/MathUtils.cpp
@@ -0,0 +1,365 @@
+#include "MathUtils.h"
+#include "foundation/PxMat33.h"
+#include "PhysXMacros.h"
+
+//---------------------------------------------------------------------
+
+void jacobiRotate(PxMat33 &A, PxMat33 &R, int p, int q)
+{
+ // rotates A through phi in pq-plane to set A(p,q) = 0
+ // rotation stored in R whose columns are eigenvectors of A
+ if (A(p,q) == 0.0f)
+ return;
+
+ float d = (A(p,p) - A(q,q))/(2.0f*A(p,q));
+ float t = 1.0f / (PxAbs(d) + PxSqrt(d*d + 1.0f));
+ if (d < 0.0f) t = -t;
+ float c = 1.0f/PxSqrt(t*t + 1);
+ float s = t*c;
+ A(p,p) += t*A(p,q);
+ A(q,q) -= t*A(p,q);
+ A(p,q) = A(q,p) = 0.0f;
+ // transform A
+ int k;
+ for (k = 0; k < 3; k++) {
+ if (k != p && k != q) {
+ float Akp = c*A(k,p) + s*A(k,q);
+ float Akq =-s*A(k,p) + c*A(k,q);
+ A(k,p) = A(p,k) = Akp;
+ A(k,q) = A(q,k) = Akq;
+ }
+ }
+ // store rotation in R
+ for (k = 0; k < 3; k++) {
+ float Rkp = c*R(k,p) + s*R(k,q);
+ float Rkq =-s*R(k,p) + c*R(k,q);
+ R(k,p) = Rkp;
+ R(k,q) = Rkq;
+ }
+}
+
+//---------------------------------------------------------------------
+
+void eigenDecomposition(PxMat33 &A, PxMat33 &R)
+{
+ const int numJacobiIterations = 10;
+ const float epsilon = 1e-15f;
+
+ // only for symmetric matrices!
+ R = PX_MAT33_ID; // unit matrix
+ int iter = 0;
+ while (iter < numJacobiIterations) { // 3 off diagonal elements
+ // find off diagonal element with maximum modulus
+ int p,q;
+ float a,max;
+ max = PxAbs(A(0,1));
+ p = 0; q = 1;
+ a = PxAbs(A(0,2));
+ if (a > max) { p = 0; q = 2; max = a; }
+ a = PxAbs(A(1,2));
+ if (a > max) { p = 1; q = 2; max = a; }
+ // all small enough -> done
+ if (max < epsilon) break;
+ // rotate matrix with respect to that element
+ jacobiRotate(A, R, p,q);
+ iter++;
+ }
+}
+
+//---------------------------------------------------------------------
+void polarDecomposition(const PxMat33 &A, PxMat33 &R)
+{
+ // A = SR, where S is symmetric and R is orthonormal
+ // -> S = (A A^T)^(1/2)
+
+ PxMat33 AAT;
+ AAT(0,0) = A(0,0)*A(0,0) + A(0,1)*A(0,1) + A(0,2)*A(0,2);
+ AAT(1,1) = A(1,0)*A(1,0) + A(1,1)*A(1,1) + A(1,2)*A(1,2);
+ AAT(2,2) = A(2,0)*A(2,0) + A(2,1)*A(2,1) + A(2,2)*A(2,2);
+
+ AAT(0,1) = A(0,0)*A(1,0) + A(0,1)*A(1,1) + A(0,2)*A(1,2);
+ AAT(0,2) = A(0,0)*A(2,0) + A(0,1)*A(2,1) + A(0,2)*A(2,2);
+ AAT(1,2) = A(1,0)*A(2,0) + A(1,1)*A(2,1) + A(1,2)*A(2,2);
+
+ AAT(1,0) = AAT(0,1);
+ AAT(2,0) = AAT(0,2);
+ AAT(2,1) = AAT(1,2);
+
+ PxMat33 U;
+ R = PX_MAT33_ID;
+ eigenDecomposition(AAT, U);
+
+ const float eps = 1e-15f;
+
+ float l0 = AAT(0,0); if (l0 <= eps) l0 = 0.0f; else l0 = 1.0f / sqrt(l0);
+ float l1 = AAT(1,1); if (l1 <= eps) l1 = 0.0f; else l1 = 1.0f / sqrt(l1);
+ float l2 = AAT(2,2); if (l2 <= eps) l2 = 0.0f; else l2 = 1.0f / sqrt(l2);
+
+ PxMat33 S1;
+ S1(0,0) = l0*U(0,0)*U(0,0) + l1*U(0,1)*U(0,1) + l2*U(0,2)*U(0,2);
+ S1(1,1) = l0*U(1,0)*U(1,0) + l1*U(1,1)*U(1,1) + l2*U(1,2)*U(1,2);
+ S1(2,2) = l0*U(2,0)*U(2,0) + l1*U(2,1)*U(2,1) + l2*U(2,2)*U(2,2);
+
+ S1(0,1) = l0*U(0,0)*U(1,0) + l1*U(0,1)*U(1,1) + l2*U(0,2)*U(1,2);
+ S1(0,2) = l0*U(0,0)*U(2,0) + l1*U(0,1)*U(2,1) + l2*U(0,2)*U(2,2);
+ S1(1,2) = l0*U(1,0)*U(2,0) + l1*U(1,1)*U(2,1) + l2*U(1,2)*U(2,2);
+
+ S1(1,0) = S1(0,1);
+ S1(2,0) = S1(0,2);
+ S1(2,1) = S1(1,2);
+
+ R = S1 * A;
+
+ // stabilize
+ PxVec3 c0 = R.column0;
+ PxVec3 c1 = R.column1;
+ PxVec3 c2 = R.column2;
+
+ if (c0.magnitudeSquared() < eps)
+ c0 = c1.cross(c2);
+ else if (c1.magnitudeSquared() < eps)
+ c1 = c2.cross(c0);
+ else
+ c2 = c0.cross(c1);
+ R.column0 = c0;
+ R.column1 = c1;
+ R.column2 = c2;
+}
+
+//---------------------------------------------------------------------
+PxVec3 perpVec3(const PxVec3 &v)
+{
+ PxVec3 n;
+ if (fabs(v.x) < fabs(v.y) && fabs(v.x) < fabs(v.z))
+ n = PxVec3(1.0f, 0.0f, 0.0f);
+ else if (fabs(v.y) < fabs(v.z))
+ n = PxVec3(0.0f, 1.0f, 0.0f);
+ else
+ n = PxVec3(0.0f, 0.0f, 1.0f);
+ n = v.cross(n);
+ n.normalize();
+ return n;
+}
+
+//---------------------------------------------------------------------
+void polarDecompositionStabilized(const PxMat33 &A, PxMat33 &R)
+{
+ PxMat33 ATA;
+ ATA = A.getTranspose() * A;
+
+ PxMat33 Q;
+ eigenDecomposition(ATA, Q);
+
+ int degenerated = 0;
+
+ float l0 = ATA(0,0);
+ if (fabs(l0) <= FLT_EPSILON) {
+ l0 = 0;
+ degenerated += 1;
+ }
+ else l0 = 1.0f / PxSqrt(l0);
+
+ float l1 = ATA(1,1);
+ if (fabs(l1) <= FLT_EPSILON) {
+ l1 = 0;
+ degenerated += 2;
+ }
+ else l1 = 1.0f / PxSqrt(l1);
+
+ float l2 = ATA(2,2);
+ if (fabs(l2) <= FLT_EPSILON) {
+ l2 = 0;
+ degenerated += 4;
+ }
+ else l2 = 1.0f / PxSqrt(l2);
+
+
+ if (A.getDeterminant() < 0) //Invertierung nach Irving,Fedkiw
+ {
+ float *max = &l0;
+ if (l1 > *max) {max = &l1;}
+ if (l2 > *max) {max = &l2;}
+ *max *= -1;
+ }
+
+ PxMat33 D = PX_MAT33_ZERO;
+ D(0,0) = l0;
+ D(1,1) = l1;
+ D(2,2) = l2;
+ R = A * Q * D;
+
+ Q = Q.getTranspose();
+
+ //handle singular cases
+
+ PxVec3 r0 = R.column0;
+ PxVec3 r1 = R.column1;
+ PxVec3 r2 = R.column2;
+
+ if (degenerated == 0) { // 000
+ }
+ else if (degenerated == 1) { // 100
+ r0 = r1.cross(r2);
+ R.column0 = r0;
+ }
+ else if (degenerated == 2) { // 010
+ r1 = r2.cross(r0);
+ R.column1 = r1;
+ }
+ else if (degenerated == 4) { // 001
+ r2 = r0.cross(r1);
+ R.column2 = r2;
+ }
+ else if (degenerated == 6) { // 011
+ r1 = perpVec3(r0);
+ r2 = r0.cross(r1);
+ R.column1 = r1;
+ R.column2 = r2;
+ }
+ else if (degenerated == 5) { // 101
+ r2 = perpVec3(r1);
+ r0 = r1.cross(r2);
+ R.column2 = r2;
+ R.column0 = r0;
+ }
+ else if (degenerated == 3) { // 110
+ r0 = perpVec3(r2);
+ r1 = r2.cross(r0);
+ R.column0 = r0;
+ R.column1 = r1;
+ }
+ else // 111
+ R = PX_MAT33_ID;
+
+ R = R*Q;
+}
+
+//---------------------------------------------------------------------
+void eigenDecomposition22(const PxMat33 &A, PxMat33 &R, PxMat33 &D)
+{
+ // only for symmetric matrices
+
+ // decompose A such that
+ // A = R D R^T, where D is diagonal and R orthonormal (a rotation)
+
+ R = PX_MAT33_ID;
+ D = PX_MAT33_ID;
+ D(0,0) = A(0,0); D(0,1) = A(0,1);
+ D(1,0) = A(1,0); D(1,1) = A(1,1);
+
+ if (D(0,1) == 0.0f)
+ return;
+
+ float d = (D(0,0) - D(1,1))/(2.0f*D(0,1));
+ float t = 1.0f / (PxAbs(d) + PxSqrt(d*d + 1.0f));
+ if (d < 0.0f) t = -t;
+ float c = 1.0f/sqrt(t*t + 1);
+ float s = t*c;
+ D(0,0) += t*D(0,1);
+ D(1,1) -= t*D(0,1);
+ D(0,1) = D(1,0) = 0.0f;
+ // store rotation in R
+ for (int k = 0; k < 2; k++) {
+ float Rkp = c*R(k,0) + s*R(k,1);
+ float Rkq =-s*R(k,0) + c*R(k,1);
+ R(k,0) = Rkp;
+ R(k,1) = Rkq;
+ }
+}
+
+//---------------------------------------------------------------------
+PxMat33 outerProduct(const PxVec3 &v0, const PxVec3 &v1)
+{
+ PxMat33 M;
+ M.column0 = v0 * v1.x;
+ M.column1 = v0 * v1.y;
+ M.column2 = v0 * v1.z;
+ return M;
+}
+
+// From geometrictools.com
+PxQuat align (const PxVec3& v1, const PxVec3& v2) {
+ // vector U = Cross(V1,V2)/Length(Cross(V1,V2)). The angle of rotation,
+ // A, is the angle between V1 and V2. The quaternion for the rotation is
+ // q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz).
+ //
+ // (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then
+ // compute sin(A/2) and cos(A/2), we reduce the computational costs by
+ // computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) =
+ // Dot(V1,B).
+ //
+ // (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but
+ // Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in
+ // which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where
+ // C = Cross(V1,B).
+ //
+ // If V1 = V2, then B = V1, cos(A/2) = 1, and U = (0,0,0). If V1 = -V2,
+ // then B = 0. This can happen even if V1 is approximately -V2 using
+ // floating point arithmetic, since Vector3::Normalize checks for
+ // closeness to zero and returns the zero vector accordingly. The test
+ // for exactly zero is usually not recommend for floating point
+ // arithmetic, but the implementation of Vector3::Normalize guarantees
+ // the comparison is robust. In this case, the A = pi and any axis
+ // perpendicular to V1 may be used as the rotation axis.
+
+ PxVec3 bisector = v1 + v2;
+ bisector.normalize();
+
+ float cosHalfAngle = v1.dot(bisector);
+ PxVec3 cross;
+
+ float mTuple[4];
+ mTuple[0] = cosHalfAngle;
+
+ if (cosHalfAngle != (float)0)
+ {
+ cross = v1.cross(bisector);
+ mTuple[1] = cross.x;
+ mTuple[2] = cross.y;
+ mTuple[3] = cross.z;
+ }
+ else
+ {
+ float invLength;
+ if (fabs(v1[0]) >= fabs(v1[1]))
+ {
+ // V1.x or V1.z is the largest magnitude component.
+ invLength = fastInvSqrt(v1[0]*v1[0] + v1[2]*v1[2]);
+ mTuple[1] = -v1[2]*invLength;
+ mTuple[2] = (float)0;
+ mTuple[3] = +v1[0]*invLength;
+ }
+ else
+ {
+ // V1.y or V1.z is the largest magnitude component.
+ invLength = fastInvSqrt(v1[1]*v1[1] + v1[2]*v1[2]);
+ mTuple[1] = (float)0;
+ mTuple[2] = +v1[2]*invLength;
+ mTuple[3] = -v1[1]*invLength;
+ }
+ }
+
+ PxQuat q(mTuple[1],mTuple[2],mTuple[3], mTuple[0]);
+ return q;
+}
+
+void decomposeTwistTimesSwing (const PxQuat& q, const PxVec3& v1,
+ PxQuat& twist, PxQuat& swing)
+{
+
+ PxVec3 v2 = v1;
+ q.rotate(v2);
+
+ swing = align(v1, v2);
+ twist = q*swing.getConjugate();
+}
+
+void decomposeSwingTimesTwist (const PxQuat& q, const PxVec3& v1,
+ PxQuat& swing, PxQuat& twist)
+{
+ PxVec3 v2 = v1;
+ q.rotate(v2);
+
+ swing = align(v1, v2);
+ twist = swing.getConjugate()*q;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/MathUtils.h b/KaplaDemo/samples/sampleViewer3/MathUtils.h
new file mode 100644
index 00000000..0051ff1e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/MathUtils.h
@@ -0,0 +1,102 @@
+#ifndef MATH_UTILS
+#define MATH_UTILS
+
+#include "foundation/PxVec3.h"
+#include "foundation/PxQuat.h"
+#include "foundation/PxMath.h"
+
+using namespace physx;
+
+// ------------------------------------------------------------------------
+PX_FORCE_INLINE PxF32 randRange(const PxF32 a, const PxF32 b)
+{
+ return a + (b-a)*::rand()/RAND_MAX;
+}
+
+// ------------------------------------------------------------------------
+inline static float fastInvSqrt(float input)
+{
+ const float halfInput = 0.5f * input;
+ int i = *(int*)&input;
+
+ i = 0x5f375a86 - ( i >> 1 );
+ input = *(float*) & i;
+ input = input * ( 1.5f - halfInput * input * input);
+ return input;
+}
+
+// ------------------------------------------------------------------------
+inline static void fastNormalize(PxVec3 &v) {
+ v *= fastInvSqrt(v.magnitudeSquared());
+}
+
+// ------------------------------------------------------------------------
+inline static float fastLen(PxVec3 &v) {
+ return 1.0f / fastInvSqrt(v.magnitudeSquared());
+}
+
+// ------------------------------------------------------------------------
+inline static float fastNormalizeLen(PxVec3 &v) {
+ float inv = fastInvSqrt(v.magnitudeSquared());
+ v *= inv;
+ return 1.0f / inv;
+}
+
+// ------------------------------------------------------------------------
+inline static float fastAcos(float x) {
+ // MacLaurin series
+ if (x < -1.0f) x = -1.0f;
+ if (x > 1.0f) x = 1.0f;
+ float x2 = x*x;
+ float angle = (35.0f/1152.0f)*x2;
+ angle = (5.0f/112.0f) + angle*x2;
+ angle = (3.0f/40.0f) + angle*x2;
+ angle = (1.0f/6.0f) + angle*x2;
+ angle = 1 + angle*x2;
+ angle = 1.5707963267948966f - angle * x;
+ return angle;
+}
+
+// ------------------------------------------------------------------------
+inline static void quatFromVectors(const PxVec3 &n0, const PxVec3 &n1, PxQuat &q)
+{
+ // fast approximation
+ PxVec3 axis = n0.cross(n1) * 0.5f;
+ q = PxQuat(axis.x, axis.y, axis.z, PxSqrt(1.0f - axis.magnitudeSquared()));
+
+ // correct
+ //PxVec3 axis = n0 ^ n1;
+ //axis.normalize();
+ //float s = PxMath::sqrt(0.5f * (1.0f - n0.dot(n1)));
+ //q.x = axis.x * s;
+ //q.y = axis.y * s;
+ //q.z = axis.z * s;
+ //q.w = PxMath::sqrt(1.0f - s*s);
+}
+
+// ------------------------------------------------------------------------
+void polarDecomposition(const PxMat33 &A, PxMat33 &R);
+void polarDecompositionStabilized(const PxMat33 &A, PxMat33 &R);
+
+// ------------------------------------------------------------------------
+void eigenDecomposition(PxMat33 &A, PxMat33 &R);
+
+// ------------------------------------------------------------------------
+void eigenDecomposition22(const PxMat33 &A, PxMat33 &R, PxMat33 &D);
+
+// ------------------------------------------------------------------------
+PxMat33 outerProduct(const PxVec3 &v0, const PxVec3 &v1);
+
+// ------------------------------------------------------------------------
+PxQuat align(const PxVec3& v1, const PxVec3& v2);
+
+// ------------------------------------------------------------------------
+void decomposeTwistTimesSwing(const PxQuat& q, const PxVec3& v1,
+ PxQuat& twist, PxQuat& swing);
+
+// ------------------------------------------------------------------------
+void decomposeSwingTimesTwist(const PxQuat& q, const PxVec3& v1,
+ PxQuat& swing, PxQuat& twist);
+
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/MediaPath.cpp b/KaplaDemo/samples/sampleViewer3/MediaPath.cpp
new file mode 100644
index 00000000..0b40e075
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/MediaPath.cpp
@@ -0,0 +1,285 @@
+
+
+#if defined(WIN32) || defined(WIN64)
+#define NOMINMAX
+#include <windows.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "MediaPath.h"
+
+#if defined(_XBOX)
+
+#include <xtl.h>
+#include <Xbdm.h>
+
+static bool MediaFileExists(const char *fname)
+{
+ FILE *fp=fopen(fname,"rb");
+ if(fp == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ fclose(fp);
+ return true;
+ }
+}
+
+char* FindMediaFile(const char *fname,char *buff)
+{
+ strcpy(buff,"d:\\");
+ strcat(buff,fname);
+
+ if(MediaFileExists(buff))
+ return buff;
+
+ DmMapDevkitDrive();
+
+ strcpy(buff,"DEVKIT:\\");
+ strcat(buff,fname);
+
+ if(MediaFileExists(buff))
+ return buff;
+
+ char msg[1024];
+ sprintf(msg, "Can't find media file: %s\n", fname);
+ OutputDebugString(msg);
+
+ return buff;
+}
+
+char* GetTempFilePath(char *buff)
+{
+ strcpy(buff,"d:\\");
+ return buff;
+}
+
+#elif defined(__CELLOS_LV2__)
+
+#include <sys/paths.h>
+
+char* FindMediaFile(const char *fname,char *buff)
+{
+ strcpy(buff,SYS_APP_HOME "/");
+ strcat(buff,fname);
+ return buff;
+}
+
+char* GetTempFilePath(char *buff)
+{
+ strcpy(buff,SYS_APP_HOME "/");
+ return buff;
+}
+
+#elif defined(WIN32) || defined(WIN64)
+
+static bool MediaFileExists(const char *fname)
+{
+ FILE *fp=fopen(fname,"rb");
+ if(fp == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ fclose(fp);
+ return true;
+ }
+}
+
+char* FindMediaFile(const char* fname, const char* path)
+{
+ static char fullPath[512];
+ strcpy(fullPath, path);
+ strcat(fullPath, "/");
+ strcat(fullPath, fname);
+ return fullPath;
+}
+
+char* FindMediaFile(const char *fname,char *buff)
+{
+ char curPath[MAX_PATH];
+ GetCurrentDirectory(MAX_PATH, curPath);
+ strcat(curPath, "\\");
+ strcpy(buff, curPath);
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ char basePath[MAX_PATH];
+ GetModuleFileName(NULL, basePath, MAX_PATH);
+ char* pTmp = strrchr(basePath, '\\');
+ if(pTmp != NULL){
+ *pTmp = 0;
+ SetCurrentDirectory(basePath);
+ pTmp = strrchr(basePath, '\\');
+ if(pTmp != NULL){
+ *pTmp = 0;
+ }
+ pTmp = strrchr(basePath, '\\');
+ if(pTmp != NULL){
+ *(pTmp + 1) = 0;
+ }
+ }
+
+ strcpy(buff, basePath);
+ strcat(buff,"..\\..\\..\\externals\\GRB\\1.0\\");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ // printf("base path is: %s\n", basePath);
+ strcpy(buff, basePath);
+ strcat(buff,"Samples\\Media\\");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff, basePath);
+ strcat(buff,"Samples\\compiler\\vc8win32\\");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff, basePath);
+ strcat(buff,"Bin\\win32\\");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ printf("Can't find media file: %s\n", fname);
+
+ strcpy(buff,fname);
+ return buff;
+}
+
+char* GetTempFilePath(char *buff)
+{
+ strcpy(buff,"");
+ return buff;
+}
+
+#elif defined(LINUX)
+
+static bool MediaFileExists(const char *fname)
+{
+ FILE *fp=fopen(fname,"rb");
+ if(fp == NULL)
+ {
+ return false;
+ }
+ else
+ {
+ fclose(fp);
+ return true;
+ }
+}
+
+char* FindMediaFile(const char *fname,char *buff)
+{
+ strcpy(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../Samples/Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../../Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"Samples/Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ printf("Can't find media file: %s\n", fname);
+
+ strcpy(buff,fname);
+ return buff;
+}
+
+char* GetTempFilePath(char *buff)
+{
+ strcpy(buff,"");
+ return buff;
+}
+#elif defined(__PPCGEKKO__)
+
+#include <revolution/dvd.h>
+
+static bool MediaFileExists(const char *fname)
+{
+ DVDFileInfo fileInfo;
+
+ if(DVDOpen(fname,&fileInfo))
+ {
+ DVDClose(&fileInfo);
+ return true;
+ }
+
+ return false;
+
+}
+
+char* FindMediaFile(const char *fname,char *buff)
+{
+ strcpy(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"/Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../Samples/Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../../Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"../../Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ strcpy(buff,"Samples/Media/");
+ strcat(buff,fname);
+ if(MediaFileExists(buff))
+ return buff;
+
+ printf("Can't find media file: %s\n", fname);
+
+ strcpy(buff,fname);
+ return buff;
+}
+
+char* GetTempFilePath(char *buff)
+{
+ strcpy(buff,"");
+ return buff;
+}
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/MediaPath.h b/KaplaDemo/samples/sampleViewer3/MediaPath.h
new file mode 100644
index 00000000..ef1e0d0d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/MediaPath.h
@@ -0,0 +1,24 @@
+#ifndef __MEDIA_PATH__
+#define __MEDIA_PATH__
+
+/*
+This function locates the media associated with the sample in a non platform specific way.
+
+For example it searches the Samples\Media directory on the PC (assuming the exe is in the bin directory or
+or project directory after a compile). This helps prevent duplicate resources for samples.
+
+On the XBox360 the game specific drive alias is added to the path(ie d:\).
+
+On PS3 no change is made.
+
+ fname - File name of media file
+ buff - buffer to put media path in
+ return - buff.
+*/
+char* FindMediaFile(const char *fname,char *buff);
+
+char* FindMediaFile(const char *fname, const char* path);
+
+char* GetTempFilePath(char *buff);
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/PhysXMacros.h b/KaplaDemo/samples/sampleViewer3/PhysXMacros.h
new file mode 100644
index 00000000..73f6d812
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/PhysXMacros.h
@@ -0,0 +1,13 @@
+#ifndef PHYSX_MACROS_H
+#define PHYSX_MACROS_H
+
+#include "PxPhysicsVersion.h"
+
+#define PX_TRANSFORM_ID PxTransform(PxIdentity)
+#define PX_MAT33_ID PxMat33(PxIdentity)
+#define PX_MAT33_ZERO PxMat33(PxZero)
+#define PX_MAT44_ID PxMat44(PxIdentity)
+#define PX_MAT44_ZERO PxMat44(PxZero)
+
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/RawLoader.cpp b/KaplaDemo/samples/sampleViewer3/RawLoader.cpp
new file mode 100644
index 00000000..f374a6a9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/RawLoader.cpp
@@ -0,0 +1,439 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+// PT: this file is a loader for "raw" binary files. It should NOT create SDK objects directly.
+
+#include <stdio.h>
+#include "foundation/PxPreprocessor.h"
+#include "RawLoader.h"
+#include "PxTkFile.h"
+
+typedef ::FILE File;
+
+using namespace physx;
+
+RAWObject::RAWObject() : mName(NULL)
+{
+ mTransform = PxTransform(PxIdentity);
+}
+
+RAWTexture::RAWTexture() :
+mID(0xffffffff),
+mWidth(0),
+mHeight(0),
+mHasAlpha(false)
+//mPixels(NULL)
+{
+}
+
+RAWMesh::RAWMesh() :
+mNbVerts(0),
+mNbFaces(0),
+mMaterialID(0xffffffff),
+mVerts(NULL),
+mVertexNormals(NULL),
+mVertexColors(NULL),
+mUVs(NULL),
+mIndices(NULL)
+{
+}
+
+RAWShape::RAWShape() :
+mNbVerts(0),
+mVerts(NULL)
+{
+}
+
+RAWHelper::RAWHelper()
+{
+}
+
+RAWMaterial::RAWMaterial() :
+mID(0xffffffff),
+mDiffuseID(0xffffffff),
+mOpacity(1.0f),
+mDoubleSided(false)
+{
+ mAmbientColor = PxVec3(0);
+ mDiffuseColor = PxVec3(0);
+ mSpecularColor = PxVec3(0);
+}
+
+#if PX_INTEL_FAMILY
+static const bool gFlip = false;
+#elif PX_PPC
+static const bool gFlip = true;
+#elif PX_ARM_FAMILY
+static const bool gFlip = false;
+#else
+#error Unknown platform!
+#endif
+
+PX_INLINE void Flip(PxU32& v)
+{
+ PxU8* b = (PxU8*)&v;
+
+ PxU8 temp = b[0];
+ b[0] = b[3];
+ b[3] = temp;
+ temp = b[1];
+ b[1] = b[2];
+ b[2] = temp;
+}
+
+PX_INLINE void Flip(PxI32& v)
+{
+ Flip((PxU32&)v);
+}
+
+PX_INLINE void Flip(PxF32& v)
+{
+ Flip((PxU32&)v);
+}
+
+static PxU8 read8(File* fp)
+{
+ PxU8 data;
+ size_t numRead = fread(&data, 1, 1, fp);
+ if (numRead != 1) { return 0; }
+ return data;
+}
+
+static PxU32 read32(File* fp)
+{
+ PxU32 data;
+ size_t numRead = fread(&data, 1, 4, fp);
+ if (numRead != 4) { return 0; }
+ if (gFlip)
+ Flip(data);
+ return data;
+}
+
+static PxF32 readFloat(File* fp)
+{
+ PxF32 data;
+ size_t numRead = fread(&data, 1, 4, fp);
+ if (numRead != 4) { return 0; }
+ if (gFlip)
+ Flip(data);
+ return data;
+}
+
+static PxTransform readTransform(File* fp, PxReal scale)
+{
+ PxTransform tr;
+ tr.p.x = scale * readFloat(fp);
+ tr.p.y = scale * readFloat(fp);
+ tr.p.z = scale * readFloat(fp);
+
+ tr.q.x = readFloat(fp);
+ tr.q.y = readFloat(fp);
+ tr.q.z = readFloat(fp);
+ tr.q.w = readFloat(fp);
+
+ PX_ASSERT(tr.isValid());
+
+ return tr;
+}
+
+static void readVertexArray(File* fp, PxVec3* verts, PxU32 nbVerts)
+{
+ const size_t size = 4 * 3 * nbVerts;
+ size_t numRead = fread(verts, 1, size, fp);
+ if (numRead != size) { return; }
+
+ if (gFlip)
+ {
+ for (PxU32 j = 0; j<nbVerts; j++)
+ {
+ Flip(verts[j].x);
+ Flip(verts[j].y);
+ Flip(verts[j].z);
+ }
+ }
+}
+
+static void readUVs(File* fp, PxReal* uvs, PxU32 nbVerts)
+{
+ const size_t size = 4 * 2 * nbVerts;
+ size_t numRead = fread(uvs, 1, size, fp);
+ if (numRead != size) { return; }
+
+ if (gFlip)
+ {
+ for (PxU32 j = 0; j<nbVerts * 2; j++)
+ Flip(uvs[j]);
+ }
+}
+
+static void readVertices(File* fp, PxVec3* verts, PxU32 nbVerts, PxReal scale)
+{
+ readVertexArray(fp, verts, nbVerts);
+
+ for (PxU32 j = 0; j<nbVerts; j++)
+ verts[j] *= scale;
+}
+
+static void readNormals(File* fp, PxVec3* verts, PxU32 nbVerts)
+{
+ readVertexArray(fp, verts, nbVerts);
+}
+
+static void readVertexColors(File* fp, PxVec3* colors, PxU32 nbVerts)
+{
+ readVertexArray(fp, colors, nbVerts);
+}
+
+static void readName(File* fp, char* objectName)
+{
+ PxU32 offset = 0;
+ char c;
+ do
+ {
+ size_t numRead = fread(&c, 1, 1, fp);
+ if (numRead != 1) { c = '\0'; }
+ objectName[offset++] = c;
+ } while (c);
+ objectName[offset] = 0;
+}
+
+
+bool loadRAWfile(const char* filename, RAWImportCallback& cb, PxReal scale)
+{
+ File* fp = NULL;
+ fopen_s(&fp, filename, "rb");
+ if (!fp)
+ return false;
+
+ // General info
+ const PxU32 tag = read32(fp);
+ const PxU32 generalVersion = read32(fp);
+ const PxU32 nbMaterials = read32(fp);
+ const PxU32 nbTextures = read32(fp);
+ const PxU32 nbMeshes = read32(fp);
+ const PxU32 nbShapes = read32(fp);
+ const PxU32 nbHelpers = read32(fp);
+
+ (void)tag;
+ (void)generalVersion;
+ char objectName[512];
+
+ // Textures
+ for (PxU32 i = 0; i<nbTextures; i++)
+ {
+ RAWTexture data;
+
+ readName(fp, objectName);
+ data.mName = objectName;
+ data.mTransform = PxTransform(PxIdentity); // PT: texture transform not supported yet
+ data.mID = read32(fp);
+
+ PxU32* pixels = NULL;
+ PxU8 r, g, b, a;
+ if (read8(fp))
+ {
+ data.mWidth = read32(fp);
+ data.mHeight = read32(fp);
+ data.mHasAlpha = read8(fp) != 0;
+ const PxU32 nbPixels = data.mWidth*data.mHeight;
+ pixels = new PxU32[nbPixels];
+ data.mPixels = pixels;
+ for (PxU32 i = 0; i<nbPixels; i++)
+ {
+ r = read8(fp);
+ g = read8(fp);
+ b = read8(fp);
+
+ if (data.mHasAlpha)
+ a = read8(fp);
+ else
+ a = 0xff;
+
+ //b, g, r, a
+ pixels[i] = b << 24 | g << 16 | r << 8 | a;
+ /*pixels[i].r = read8(fp);
+ pixels[i].g = read8(fp);
+ pixels[i].b = read8(fp);
+ if (data.mHasAlpha)
+ pixels[i].a = read8(fp);
+ else
+ pixels[i].a = 0xff;*/
+ }
+ }
+ else
+ {
+ data.mWidth = 0;
+ data.mHeight = 0;
+ data.mHasAlpha = false;
+ data.mPixels = NULL;
+ }
+
+ cb.newTexture(data);
+ delete[] pixels;
+ }
+
+ // Materials
+ for (PxU32 i = 0; i<nbMaterials; i++)
+ {
+ RAWMaterial data;
+ data.mID = read32(fp);
+ data.mDiffuseID = read32(fp);
+ data.mOpacity = readFloat(fp);
+ data.mDoubleSided = read32(fp) != 0;
+
+ data.mAmbientColor.x = readFloat(fp);
+ data.mAmbientColor.y = readFloat(fp);
+ data.mAmbientColor.z = readFloat(fp);
+
+ data.mDiffuseColor.x = readFloat(fp);
+ data.mDiffuseColor.y = readFloat(fp);
+ data.mDiffuseColor.z = readFloat(fp);
+
+ data.mSpecularColor.x = readFloat(fp);
+ data.mSpecularColor.y = readFloat(fp);
+ data.mSpecularColor.z = readFloat(fp);
+
+ cb.newMaterial(data);
+ }
+
+ // Meshes
+ for (PxU32 i = 0; i<nbMeshes; i++)
+ {
+ RAWMesh data;
+
+ readName(fp, objectName);
+ data.mName = objectName;
+ data.mTransform = readTransform(fp, scale);
+ //
+ data.mNbVerts = read32(fp);
+ data.mNbFaces = read32(fp);
+ const PxU32 hasVertexColors = read32(fp);
+ const PxU32 hasUVs = read32(fp);
+ data.mMaterialID = read32(fp);
+
+ PxVec3* tmpVerts = new PxVec3[data.mNbVerts];
+ PxVec3* tmpNormals = new PxVec3[data.mNbVerts];
+ PxVec3* tmpColors = NULL;
+ PxReal* tmpUVs = NULL;
+
+ data.mVerts = tmpVerts;
+ data.mVertexNormals = tmpNormals;
+ data.mVertexColors = NULL;
+ data.mUVs = NULL;
+
+ readVertices(fp, tmpVerts, data.mNbVerts, scale);
+ readNormals(fp, tmpNormals, data.mNbVerts);
+
+ if (hasVertexColors)
+ {
+ tmpColors = new PxVec3[data.mNbVerts];
+ data.mVertexColors = tmpColors;
+ readVertexColors(fp, tmpColors, data.mNbVerts);
+ }
+
+ if (hasUVs)
+ {
+ tmpUVs = new PxReal[(sizeof(PxReal)*data.mNbVerts * 2)];
+ data.mUVs = tmpUVs;
+ readUVs(fp, tmpUVs, data.mNbVerts);
+ }
+
+ PxU32* tmpIndices = new PxU32[sizeof(PxU32)*data.mNbFaces * 3];
+ data.mIndices = tmpIndices;
+ const size_t size = 4 * 3 * data.mNbFaces;
+ size_t numRead = fread(tmpIndices, 1, size, fp);
+ if (numRead != size)
+ {
+ delete[] tmpIndices;
+ delete[] tmpUVs;
+ delete[] tmpColors;
+ delete[] tmpNormals;
+ delete[] tmpVerts;
+ /*SAMPLE_FREE(tmpIndices);
+ SAMPLE_FREE(tmpUVs);
+
+ DELETEARRAY(tmpColors);
+ DELETEARRAY(tmpNormals);
+ DELETEARRAY(tmpVerts);*/
+ return false;
+ }
+ if (gFlip)
+ {
+ for (PxU32 j = 0; j<data.mNbFaces * 3; j++)
+ {
+ Flip(tmpIndices[j]);
+ }
+ }
+
+ cb.newMesh(data);
+
+ delete[] tmpIndices;
+ delete[] tmpUVs;
+ delete[] tmpColors;
+ delete[] tmpNormals;
+ delete[] tmpVerts;
+
+ /* SAMPLE_FREE(tmpIndices);
+ SAMPLE_FREE(tmpUVs);
+ DELETEARRAY(tmpColors);
+ DELETEARRAY(tmpNormals);
+ DELETEARRAY(tmpVerts);*/
+ }
+
+ // Shapes
+ for (PxU32 i = 0; i<nbShapes; i++)
+ {
+ RAWShape data;
+
+ readName(fp, objectName);
+ data.mName = objectName;
+ data.mTransform = readTransform(fp, scale);
+ //
+ data.mNbVerts = read32(fp);
+ PxVec3* tmp = new PxVec3[data.mNbVerts];
+ data.mVerts = tmp;
+ readVertices(fp, tmp, data.mNbVerts, scale);
+
+ cb.newShape(data);
+
+ delete[] tmp;
+ }
+
+ // Helpers
+ for (PxU32 i = 0; i<nbHelpers; i++)
+ {
+ RAWHelper data;
+
+ readName(fp, objectName);
+ data.mName = objectName;
+ data.mTransform = readTransform(fp, scale);
+ }
+ return true;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/RawLoader.h b/KaplaDemo/samples/sampleViewer3/RawLoader.h
new file mode 100644
index 00000000..4f5d1e33
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/RawLoader.h
@@ -0,0 +1,114 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef RAW_LOADER_H
+#define RAW_LOADER_H
+
+#include "foundation/PxTransform.h"
+
+class RAWObject
+{
+public:
+ RAWObject();
+
+ const char* mName;
+ physx::PxTransform mTransform;
+};
+
+class RAWTexture : public RAWObject
+{
+public:
+ RAWTexture();
+
+ physx::PxU32 mID;
+ physx::PxU32 mWidth;
+ physx::PxU32 mHeight;
+ bool mHasAlpha;
+ physx::PxU32* mPixels; //b, g, r, a(blue, green, red, alpha)
+};
+
+class RAWMesh : public RAWObject
+{
+public:
+ RAWMesh();
+
+ physx::PxU32 mNbVerts;
+ physx::PxU32 mNbFaces;
+ physx::PxU32 mMaterialID;
+ const physx::PxVec3* mVerts;
+ const physx::PxVec3* mVertexNormals;
+ const physx::PxVec3* mVertexColors;
+ const physx::PxReal* mUVs;
+ const physx::PxU32* mIndices;
+};
+
+class RAWShape : public RAWObject
+{
+public:
+ RAWShape();
+
+ physx::PxU32 mNbVerts;
+ const physx::PxVec3* mVerts;
+};
+
+class RAWHelper : public RAWObject
+{
+public:
+ RAWHelper();
+};
+
+class RAWMaterial
+{
+public:
+ RAWMaterial();
+
+ physx::PxU32 mID;
+ physx::PxU32 mDiffuseID;
+ physx::PxReal mOpacity;
+ physx::PxVec3 mAmbientColor;
+ physx::PxVec3 mDiffuseColor;
+ physx::PxVec3 mSpecularColor;
+ bool mDoubleSided;
+};
+
+class RAWImportCallback
+{
+public:
+ virtual ~RAWImportCallback() {}
+ virtual void newMaterial(const RAWMaterial&) = 0;
+ virtual void newMesh(const RAWMesh&) = 0;
+ virtual void newShape(const RAWShape&) = 0;
+ virtual void newHelper(const RAWHelper&) = 0;
+ virtual void newTexture(const RAWTexture&) = 0;
+};
+
+bool loadRAWfile(const char* filename, RAWImportCallback& cb, physx::PxReal scale);
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp
new file mode 100644
index 00000000..f79a657a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp
@@ -0,0 +1,342 @@
+
+/**********************************************************************\
+* AUTHOR : HILLAIRE S�bastien
+*
+* SITE : sebastien.hillaire.free.fr
+*
+* You are free to totally or partially use this file/code.
+* If you do, please credit me in your software or demo and leave this
+* note.
+* Share your work and your ideas as much as possible!
+\*********************************************************************/
+
+#include "FrameBufferObjectMRT.h"
+
+
+//#include "ImageBMP.h"
+
+bool CheckFramebufferStatus(const GLuint fbo)
+{
+ GLenum status;
+ bool ret = false;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+
+ status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ switch(status) {
+ case GL_FRAMEBUFFER_COMPLETE_EXT:
+ //printf("Frame Buffer Created\n");
+ ret = true;
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ printf("Unsupported framebuffer format\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ printf("Framebuffer incomplete, missing attachment\n");
+ break;
+ //case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
+ // printf("Framebuffer incomplete, duplicate attachment\n");
+ // break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ printf("Framebuffer incomplete, attached images must have same dimensions\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ printf("Framebuffer incomplete, attached images must have same format\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing draw buffer\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing read buffer\n");
+ break;
+ default:
+ printf("Framebuffer incomplete, UNKNOW ERROR\n");
+ assert(0);
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+FrameBufferObjectMRT::FrameBufferObjectMRT(unsigned int width, unsigned int height,
+ unsigned int nbColorBuffer,
+ const unsigned int* colorBufferInternalFormat,
+ const unsigned int* colorBufferSWRAP,
+ const unsigned int* colorBufferTWRAP,
+ const unsigned int* colorBufferMinFiltering,
+ const unsigned int* colorBufferMagFiltering,
+ FBO_DepthBufferType depthBufferType,
+ const unsigned int depthBufferMinFiltering,
+ const unsigned int depthBufferMagFiltering,
+ const unsigned int depthBufferSWRAP,
+ const unsigned int depthBufferTWRAP)
+{
+ this->width = width;
+ this->height= height;
+ this->nbColorAttachement = nbColorBuffer;
+ if(this->nbColorAttachement>this->getMaxColorAttachments())
+ this->nbColorAttachement = this->getMaxColorAttachments();
+
+
+ /////////////////INITIALIZATION/////////////////
+
+ //color render buffer
+ if(this->nbColorAttachement>0)
+ {
+ this->colorTextures = new GLuint[this->nbColorAttachement];
+ this->colorMinificationFiltering = new GLuint[this->nbColorAttachement];
+ for(int i=0; i<this->nbColorAttachement; i++)
+ {
+ glGenTextures(1, &this->colorTextures[i]);
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, colorBufferMinFiltering[i]);
+ this->colorMinificationFiltering[i] = colorBufferMinFiltering[i];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, colorBufferMagFiltering[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, colorBufferSWRAP[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, colorBufferTWRAP[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, colorBufferInternalFormat[i], width, height, 0, GL_RGB, GL_FLOAT, NULL);
+
+ if(this->colorMinificationFiltering[i]==GL_NEAREST_MIPMAP_NEAREST
+ || this->colorMinificationFiltering[i]==GL_LINEAR_MIPMAP_NEAREST
+ ||this->colorMinificationFiltering[i]==GL_NEAREST_MIPMAP_LINEAR
+ || this->colorMinificationFiltering[i]==GL_LINEAR_MIPMAP_LINEAR)
+ {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ }
+ }
+
+ //depth render buffer
+ this->depthType = depthBufferType;
+ if(this->depthType!=FBO_DepthBufferType_NONE)
+ {
+ switch(this->depthType)
+ {
+ case FBO_DepthBufferType_TEXTURE:
+ glGenTextures(1, &this->depthID);
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ this->depthMinificationFiltering = depthBufferMinFiltering;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, depthBufferMinFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, depthBufferMagFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, depthBufferSWRAP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, depthBufferTWRAP);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+ if(this->depthMinificationFiltering==GL_NEAREST_MIPMAP_NEAREST
+ || this->depthMinificationFiltering==GL_LINEAR_MIPMAP_NEAREST
+ ||this->depthMinificationFiltering==GL_NEAREST_MIPMAP_LINEAR
+ || this->depthMinificationFiltering==GL_LINEAR_MIPMAP_LINEAR)
+ {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ break;
+
+ case FBO_DepthBufferType_RENDERTARGET:
+ default:
+ glGenRenderbuffersEXT(1, &this->depthID);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->depthID);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, width, height);
+ break;
+ }
+ }
+
+ /////////////////ATTACHEMENT/////////////////
+ glGenFramebuffersEXT(1, &this->fbo);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,this->fbo);
+
+ //color render buffer attachement
+ if(nbColorBuffer>0)
+ {
+ for(int i=0; i<this->nbColorAttachement; i++)
+ {
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, this->colorTextures[i], 0 );
+ }
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ }
+ else
+ {
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ }
+
+ //depth render buffer attachement
+ if(this->depthType!=FBO_DepthBufferType_NONE)
+ {
+ switch(this->depthType)
+ {
+ case FBO_DepthBufferType_TEXTURE:
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->depthID, 0);
+ break;
+
+ case FBO_DepthBufferType_RENDERTARGET:
+ default:
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->depthID);
+ break;
+ }
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ CheckFramebufferStatus(this->fbo);
+}
+
+FrameBufferObjectMRT::~FrameBufferObjectMRT()
+{
+ if(this->nbColorAttachement>0)
+ {
+ delete [] this->colorTextures;
+ delete [] this->colorMinificationFiltering;
+ }
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+
+const GLint FrameBufferObjectMRT::getMaxColorAttachments()
+{
+ GLint maxAttach = 0;
+ glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach );
+ return maxAttach;
+}
+const GLint FrameBufferObjectMRT::getMaxBufferSize()
+{
+ GLint maxSize = 0;
+ glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize );
+ return maxSize;
+}
+
+
+
+void FrameBufferObjectMRT::enableRenderToColorAndDepth(const unsigned int colorBufferNum) const
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fbo);
+
+ if(this->nbColorAttachement>0)
+ {
+ unsigned int colorBuffer = GL_COLOR_ATTACHMENT0_EXT + colorBufferNum;
+ if((int)colorBufferNum>this->nbColorAttachement)
+ colorBuffer = GL_COLOR_ATTACHMENT0_EXT;
+ glDrawBuffer(colorBuffer);
+ }
+ else
+ {
+ glDrawBuffer(GL_NONE); //for example, in the case of rendering in a depth buffer
+ }
+}
+
+void FrameBufferObjectMRT::enableRenderToColorAndDepth_MRT(const GLuint numBuffers, const GLenum* drawbuffers) const
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fbo);
+
+ //HERE, THERE SHOULD HAVE A TEST OF THE DRAW BUFFERS ID AND NUMBER
+ /*for(GLuint i=0; i<numBuffers; i++)
+ {
+ }*/
+ glDrawBuffers(numBuffers, drawbuffers);
+
+}
+
+void FrameBufferObjectMRT::disableRenderToColorDepth()
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+}
+
+
+
+void FrameBufferObjectMRT::saveAndSetViewPort() const
+{
+ glPushAttrib(GL_VIEWPORT_BIT);
+ glViewport(0, 0, this->width, this->height);
+}
+
+void FrameBufferObjectMRT::restoreViewPort() const
+{
+ glPopAttrib();
+}
+
+
+
+void FrameBufferObjectMRT::bindColorTexture(const unsigned int colorBufferNum) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[colorBufferNum]);
+ }
+ else
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FrameBufferObjectMRT::bindDepthTexture() const
+{
+ if(this->depthType==FBO_DepthBufferType_TEXTURE)
+ {
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ }
+ else
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FrameBufferObjectMRT::generateColorBufferMipMap(const unsigned int colorBufferNum) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ if(this->colorMinificationFiltering[colorBufferNum]==GL_NEAREST
+ || this->colorMinificationFiltering[colorBufferNum]==GL_LINEAR)
+ return; //don't allow to generate mipmap chain for texture that don't support it at the creation
+
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[colorBufferNum]);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+}
+
+void FrameBufferObjectMRT::generateDepthBufferMipMap() const
+{
+ if(this->depthType==FBO_DepthBufferType_TEXTURE)
+ {
+ if(this->depthMinificationFiltering==GL_NEAREST
+ || this->depthMinificationFiltering==GL_LINEAR)
+ return; //don't allow to generate mipmap chain for texture that don't support it at the creation
+
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+}
+
+
+
+unsigned int FrameBufferObjectMRT::getNumberOfColorAttachement() const
+{
+ return this->nbColorAttachement;
+}
+
+FBO_DepthBufferType FrameBufferObjectMRT::getDepthBufferType() const
+{
+ return this->depthType;
+}
+
+unsigned int FrameBufferObjectMRT::getWidth() const
+{
+ return this->width;
+}
+
+unsigned int FrameBufferObjectMRT::getHeight() const
+{
+ return this->height;
+}
+
+/*
+void FrameBufferObjectMRT::saveToDisk(const unsigned int colorBufferNum, const char* filepath) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ ImageBMP::TextureToDisk(filepath,GL_TEXTURE_2D,this->colorTextures[colorBufferNum]);
+ }
+}*/ \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h
new file mode 100644
index 00000000..d899cda0
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h
@@ -0,0 +1,220 @@
+
+/**********************************************************************\
+* AUTHOR : HILLAIRE S�bastien
+*
+* SITE : sebastien.hillaire.free.fr
+*
+* You are free to totally or partially use this file/code.
+* If you do, please credit me in your software or demo and leave this
+* note.
+* Share your work and your ideas as much as possible!
+\*********************************************************************/
+
+
+#ifndef _FRAME_BUFFER_OBJECT_OPENGL_
+#define _FRAME_BUFFER_OBJECT_OPENGL_
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "stdlib.h"
+#include "assert.h"
+#include "stdio.h"
+#include "GL/glew.h"
+
+typedef enum{
+ FBO_DepthBufferType_NONE=0,
+ FBO_DepthBufferType_TEXTURE=1,
+ FBO_DepthBufferType_RENDERTARGET=2
+} FBO_DepthBufferType;
+
+/**
+ * The FrameBufferObject class allowing to use render to texture
+ */
+class FrameBufferObjectMRT
+{
+private:
+ /**
+ * The OpenGL FBO ID
+ */
+ GLuint fbo;
+
+ /**
+ * the table containing all texture id of each render target
+ */
+ GLuint* colorTextures;
+ /**
+ * the number of color attachement
+ */
+ GLint nbColorAttachement;
+ /**
+ * The minification filtering for the color buffer textures
+ */
+ GLuint *colorMinificationFiltering;
+
+ /**
+ * the depth texture/buffer id
+ */
+ GLuint depthID;
+ /**
+ * the depth type
+ */
+ FBO_DepthBufferType depthType;
+ /**
+ * The minification filtering for the depth buffer texture
+ */
+ GLuint depthMinificationFiltering;
+
+ /**
+ * the width in pixel
+ */
+ unsigned int width;
+ /**
+ * the height in pixel
+ */
+ unsigned int height;
+
+ /**
+ * default constructeur not allowed
+ */
+ FrameBufferObjectMRT();
+ /**
+ * copy constructeur not allowed
+ */
+ FrameBufferObjectMRT(FrameBufferObjectMRT&);
+ /**
+ * copy assignement operator not allowed
+ */
+ FrameBufferObjectMRT& operator=(const FrameBufferObjectMRT&);
+
+public:
+
+ /**
+ * The only available constructor
+ */
+ FrameBufferObjectMRT(unsigned int width, unsigned int height,
+ unsigned int nbColorBuffer,
+ const unsigned int* colorBufferInternalFormat,
+ const unsigned int* colorBufferSWRAP,
+ const unsigned int* colorBufferTWRAP,
+ const unsigned int* colorBufferMinFiltering,
+ const unsigned int* colorBufferMagFiltering,
+ FBO_DepthBufferType depthBufferType=FBO_DepthBufferType_NONE,
+ const unsigned int depthBufferMinFiltering=GL_LINEAR,
+ const unsigned int depthBufferMagFiltering=GL_LINEAR,
+ const unsigned int depthBufferSWRAP=GL_CLAMP,
+ const unsigned int depthBufferTWRAP=GL_CLAMP);
+
+ /**
+ * The destructor
+ */
+ ~FrameBufferObjectMRT();
+
+ /**
+ * @return the number of color attachment of this FBO
+ */
+ unsigned int getNumberOfColorAttachement() const;
+ /**
+ * @return the type of depth buffer of this FBO
+ */
+ FBO_DepthBufferType getDepthBufferType() const;
+
+ /**
+ * @return the width in pixel of this FBO
+ */
+ unsigned int getWidth() const;
+ /**
+ * @return the height in pixel of this FBO
+ */
+ unsigned int getHeight() const;
+
+ /**
+ * @return the maximum number of color texture attachement
+ */
+ static const GLint getMaxColorAttachments();
+ /**
+ * @return the maximum width and height allowed
+ */
+ static const GLint getMaxBufferSize();
+
+ /**
+ * Enable this FBO to render in ONE texture using the depth buffer if it exist.
+ * To disable rendering in the depth buffer and/or depth testing, use glDepthMask and glDisable(GL_DEPTH_TEST).
+ *
+ * @param colorBufferNum : the number of the render texture (0 for GL_COLOR_ATTACHMENT0_EXT, etc)
+ */
+ void enableRenderToColorAndDepth(const unsigned int colorBufferNum) const;
+ /**
+ * Enable this FBO to render in MULTIPLE texture using the depth buffer if it exist.
+ * To disable rendering in the depth buffer and/or depth testing, use glDepthMask and glDisable(GL_DEPTH_TEST).
+ * Using this method, you must not use gl_fragColor in the fragment program but gl_fragData[i].
+ *
+ * @param numBuffers : the number of renger target we want
+ * @param drawbuffers : an array containing the color texture ID binded to the fragment program output gl_fragData[i]
+ */
+ void enableRenderToColorAndDepth_MRT(const GLuint numBuffers, const GLenum* drawbuffers) const;
+ /**
+ * Disable render to texture. This method os static because it works the same way for all fbo instance.
+ * Thus, if you want to render to two render texture sequentially, you don't need to disable fbo rendering
+ * and it will improves performances.
+ */
+ static void disableRenderToColorDepth();
+
+ /**
+ * Save the current viewport and set up the viewport for this fbo. If the FBO is has same resolution as the current
+ * viewport, you don't need to call this method.
+ */
+ void saveAndSetViewPort() const;
+ /**
+ * Restore previous viewport.
+ * @see saveAndSetViewPort
+ */
+ void restoreViewPort() const;
+
+
+ GLuint getColorBuffer(int colorBufferNum) {
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ return this->colorTextures[colorBufferNum];
+ }
+ return NULL;
+ }
+ /**
+ * Bind a color buffer in the current texture unit as a GL_TEXTURE_2D.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, texture 0 is binded
+ */
+ void bindColorTexture(const unsigned int colorBufferNum) const;
+ /**
+ * Bind the depth buffer in the current texture unit as a GL_TEXTURE_2D.
+ */
+ void bindDepthTexture() const;
+
+ /**
+ * Generate the mipmap chain for a given color buffer.
+ * The mipmap generation will not work for texture-buffer you have specified with GL_NEAREST or GL_LINEAR at the creation.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, we return.
+ */
+ void generateColorBufferMipMap(const unsigned int colorBufferNum) const;
+ /**
+ * Generate the mipmap chain for the depth buffer. Some driver don't support it.
+ */
+ void generateDepthBufferMipMap() const;
+
+ /**
+ * Save a given color bufferin a bitmap file.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, we return.
+ * @param filepath : the path of the bitmap file.
+ */
+ //void saveToDisk(const unsigned int colorBufferNum, const char* filepath) const;
+
+};
+
+
+
+#endif
+
diff --git a/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp
new file mode 100644
index 00000000..7a2cec9c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp
@@ -0,0 +1,2878 @@
+// GLSL shaders
+#include "Compound.h"
+#define STRINGIFY(A) #A
+
+// particle vertex shader
+const char *particleVS = STRINGIFY(
+uniform float pointRadius; // point size in world space
+uniform float pointScale; // scale to calculate size in pixels
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.2;
+void main()
+{
+ // scale down point size based on density
+ float density = gl_MultiTexCoord1.x;
+ float scaledPointRadius = pointRadius * (pointShrink + smoothstep(densityThreshold, densityThreshold*2.0, density)*(1.0-pointShrink));
+// float scaledPointRadius = pointRadius;
+
+ // calculate window-space point size
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ float dist = length(eyeSpacePos.xyz);
+ gl_PointSize = scaledPointRadius * (pointScale / dist);
+
+ gl_TexCoord[0] = gl_MultiTexCoord0; // sprite texcoord
+ gl_TexCoord[1] = vec4(eyeSpacePos.xyz, scaledPointRadius); // eye space pos
+ gl_TexCoord[2] = vec4(gl_MultiTexCoord2.xyz, density); // velocity and density
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ if (density < densityThreshold) gl_Position.w = -1.0; // cull particles with small density
+
+ gl_FrontColor = gl_Color;
+}
+);
+const char *particleVSNoKill = STRINGIFY(
+uniform float pointRadius; // point size in world space
+uniform float pointScale; // scale to calculate size in pixels
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.2;
+void main()
+{
+ // scale down point size based on density
+ float density = gl_MultiTexCoord1.x;
+// float scaledPointRadius = pointRadius * (pointShrink + smoothstep(densityThreshold, densityThreshold*2.0, density)*(1.0-pointShrink))*max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10.0f;;
+ float scaledPointRadius = pointRadius;
+
+ // calculate window-space point size
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ float dist = length(eyeSpacePos.xyz);
+ gl_PointSize = scaledPointRadius * (pointScale / dist);
+ //gl_PointSize = 10.0f;
+ gl_TexCoord[0] = gl_MultiTexCoord0; // sprite texcoord
+ gl_TexCoord[1] = vec4(eyeSpacePos.xyz, scaledPointRadius); // eye space pos
+ gl_TexCoord[2] = vec4(gl_MultiTexCoord2.xyz, density); // velocity and density
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ gl_FrontColor = gl_Color;
+}
+);
+// render particle as constant shaded disc
+const char *particleDebugPS = STRINGIFY(
+uniform float pointRadius;
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+
+// gl_FragColor = gl_Color;
+ gl_FragColor = gl_TexCoord[2].w * 0.001; // show density
+// gl_FragColor = gl_TexCoord[2]; // show vel
+}
+);
+
+// render particle as lit sphere
+const char *particleSpherePS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ gl_FragColor = diffuse*gl_Color;
+}
+);
+
+// visualize density
+const char *particleDensityPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform float densityScale;
+uniform float densityOffset;
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ // calculate color based on density
+ float x = 1.0 - saturate((gl_TexCoord[2].w - densityOffset) * densityScale);
+ vec3 color = lerp(gl_Color.xyz, vec3(1.0, 1.0, 1.0), x);
+
+ gl_FragColor = vec4(diffuse*color, 1.0);
+}
+);
+
+// renders eye-space depth
+const char *particleSurfacePS = STRINGIFY(
+uniform float pointRadius;
+uniform float faceScale = 1.0;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2)*faceScale;
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*gl_TexCoord[1].w, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ gl_FragColor = eyeSpacePos.z; // output eye-space depth
+// gl_FragColor = -eyeSpacePos.z/10.0;
+}
+);
+
+// render particle thickness
+const char *particleThicknessPS = STRINGIFY(
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform float pointRadius;
+uniform float faceScale = 1.0;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2) * faceScale;
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*gl_TexCoord[1].w, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float alpha = exp(-r2*2.0);
+
+// gl_FragColor = eyeSpacePos.z; // output distance
+ gl_FragColor = N.z*pointRadius*2.0*alpha; // output thickness
+}
+);
+
+// motion blur shaders
+const char *mblurVS = STRINGIFY(
+uniform float timestep = 0.02;
+uniform vec3 eyeVel;
+uniform float iStartFade = 1.0;
+void main()
+{
+ vec3 pos = gl_Vertex.xyz;
+ vec3 vel = gl_MultiTexCoord2.xyz;
+ //vel = vec3(10.0f,0.0f,0.0f);
+ vec3 pos2 = (pos - (vel+eyeVel)*timestep); // previous position
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos, 1.0); // eye space
+ gl_TexCoord[0] = gl_ModelViewMatrix * vec4(pos2, 1.0);
+ gl_TexCoord[1].x = gl_MultiTexCoord1.x;
+ gl_TexCoord[1].y = max(0.0f, min(gl_MultiTexCoord3.x*iStartFade, 1.0f));
+ gl_TexCoord[2].xyz = pos;
+ gl_TexCoord[3] = gl_MultiTexCoord4;
+
+ gl_FrontColor = gl_Color;
+}
+
+);
+
+const char *mblurGS = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 50.0;
+uniform float idensityThreshold = 1.0 / 50.0;
+uniform float pointShrink = 0.25;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ float density = gl_TexCoordIn[0][1].x;
+ float life = gl_TexCoordIn[0][1].y;
+
+ // scale down point size based on density
+ float pointSize = pointRadius;
+
+ pointSize *= gl_TexCoordIn[0][3].x;
+
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 pos2 = gl_TexCoordIn[0][0].xyz;
+ vec3 motion = pos - pos2;
+ vec3 dir = normalize(motion);
+ float len = length(motion);
+
+ vec3 x = dir * pointSize;
+ vec3 view = normalize(-pos);
+ vec3 y = normalize(cross(dir, view)) * pointSize;
+ float facing = dot(view, dir);
+
+ // check for very small motion to avoid jitter
+ float threshold = 0.01;
+// if (len < threshold) {
+ if ((len < threshold) || (facing > 0.95) || (facing < -0.95)) {
+ pos2 = pos;
+ x = vec3(pointSize, 0.0, 0.0);
+ y = vec3(0.0, -pointSize, 0.0);
+ }
+
+
+
+ //if (density < densityThreshold) {
+
+ gl_TexCoord[0] = vec4(0, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+
+ //}
+}
+);
+const char *mblurGSNoKill = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 50.0;
+uniform float idensityThreshold = 1.0 / 30.0;
+uniform float pointShrink = 0.25;
+uniform sampler2D meteorTex;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ float density = gl_TexCoordIn[0][1].x;
+ float life = gl_TexCoordIn[0][1].y;
+
+
+ gl_TexCoord[1].xy = 0.25f*vec2(gl_PrimitiveIDIn / 4, gl_PrimitiveIDIn % 4);
+ // scale down point size based on density
+ float factor = 1.0f;//density * idensityThreshold;
+ //smoothstep(0.0f, densityThreshold, density);
+ //density * idensityThreshold;
+ //clamp(density / 50.0f, 0, 1);
+ float pointSize = pointRadius*factor;//*(pointShrink + smoothstep(0.0, densityThreshold, density)*(1.0-pointShrink));
+
+ pointSize *= gl_TexCoordIn[0][3].x;
+ float tmp = gl_TexCoordIn[0][3].y;
+
+ float bb = 1.0f;
+ if (tmp > 0.5f) {
+ //gl_FrontColor = vec4(3*life,0,0,1);
+ // TODO: Meteor trail color here...
+ //vec2 fetchPos = vec2( min(max((3-lifeTime)/3,0),1), 0);
+ float val = 1-min(max((life-0.3)/0.2,0.01),0.99);
+ vec2 fetchPos = vec2(val, 0);
+ gl_FrontColor = texture2D(meteorTex, fetchPos);
+ if (gl_FrontColor.r > 0.5) bb += (gl_FrontColor.r-0.5)*(gl_FrontColor.r-0.5)*10;
+
+ }
+// float pointSize = pointRadius;
+
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 pos2 = gl_TexCoordIn[0][0].xyz;
+ vec3 motion = pos - pos2;
+ vec3 dir = normalize(motion);
+ float len = length(motion);
+
+ vec3 x = dir * pointSize;
+ vec3 view = normalize(-pos);
+ vec3 y = normalize(cross(dir, view)) * pointSize;
+ float facing = dot(view, dir);
+
+ // check for very small motion to avoid jitter
+ float threshold = 0.01;
+// if (len < threshold) {
+ if ((len < threshold) || (facing > 0.95) || (facing < -0.95)) {
+ pos2 = pos;
+ x = vec3(pointSize, 0.0, 0.0);
+ y = vec3(0.0, -pointSize, 0.0);
+ }
+
+ float angle = density;
+ float cv = cos(angle);
+ float sv = sin(angle);
+
+ vec3 xt = cv*x + sv*y;
+ vec3 yt = -sv*x + cv*y;
+ x = xt;
+ y = yt;
+
+ {
+
+ gl_TexCoord[0] = vec4(0, 0, bb, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, bb, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, bb, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, bb, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+/*
+ gl_TexCoord[0] = vec4(0, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+ */
+ }
+}
+);
+
+const char *particleSprayPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.5;
+uniform vec3 lightDir;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+void main()
+{
+ //gl_FragColor = vec4(1.0f,1.0f,1.0f,1.0f);
+ //return;
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = exp(-mag*4.0);
+ float shadowC = shadowCoef();
+
+ gl_FragColor = gl_Color*(shadowAmbient + (1.0f -shadowAmbient)*shadowC)*(abs(dot(lightDir, N))*0.3f+0.7f );//*falloff;
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.w *= falloff * gl_TexCoord[0].w;
+
+}
+);
+const char *particleSprayGenFOMPS= STRINGIFY(
+const float PI = 3.1415926535897932384626433832795;
+const vec4 factor_a = vec4(2.0*PI)*vec4(0.0,1.0,2.0,3.0);
+const vec4 factor_b = vec4(2.0*PI)*vec4(1.0,2.0,3.0,0.0);
+const vec4 factor_m2 = vec4(-2.0);
+uniform float ispotMaxDist;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ // float falloff = exp(-mag*4.0);
+ //float falloff = pow(1.0-mag,1.5);//exp(-mag);
+ float falloff = 1.0;
+ float opacity = gl_Color.a * falloff * min(gl_TexCoord[0].w,1.0f);
+
+ float distance = sqrt(dot(gl_TexCoord[2].xyz, gl_TexCoord[2].xyz))*ispotMaxDist;
+
+
+ //compute value for projection into Fourier basis
+ vec4 cos_a0123 = cos(factor_a*vec4(distance));
+ vec4 sin_b123 = sin(factor_b*vec4(distance));
+ vec4 lnOpacitR = factor_m2*vec4(log(1.0-opacity));
+
+ gl_FragData[0] = lnOpacitR*cos_a0123;
+ gl_FragData[1] = lnOpacitR*sin_b123;
+}
+);
+
+const char *particleSprayUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.5;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = 1.0f;//shadowCoef();
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC = (1.0f-att);
+
+ //....
+
+ gl_FragColor.xyz = gl_Color.xyz*(shadowAmbient + (1.0f -shadowAmbient)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w;
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+}
+);
+
+// motion blur shaders
+const char *particleDumbFoamVS = STRINGIFY(
+uniform float timestep = 0.02;
+// GPU Water
+uniform sampler2D waterHFTex;
+uniform float minEta;
+uniform float fracEta;
+uniform vec2 hfScale; // 1/(sx*dx), 1/(sz*dx)
+uniform vec2 hfOffset; // 0.5/sx, 0.5/sz
+uniform vec2 hfCellOffset; // 1.0/sx, 1.0/sz
+uniform vec2 origin;
+uniform float dx;
+uniform float waterHOffset;
+uniform vec4 foamFactor = vec4(1.0/4, 1.0/4,0,0);
+void main()
+{
+ vec2 hfTexCoord = (gl_Vertex.xz - origin)*hfScale + hfOffset;
+ vec4 etaH = texture2D(waterHFTex, hfTexCoord);
+ vec4 etaHxp1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(1,0));
+ vec4 etaHxm1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(-1,0));
+ vec4 etaHzp1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(0,1));
+ vec4 etaHzm1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(0,-1));
+ float h = etaH.x+etaH.y;
+ float hxp1 = etaHxp1.x+etaHxp1.y;
+ float hxm1 = etaHxm1.x+etaHxm1.y;
+ float hzp1 = etaHzp1.x+etaHzp1.y;
+ float hzm1 = etaHzm1.x+etaHzm1.y;
+
+ vec3 pos = gl_Vertex.xyz;
+ vec3 vel = gl_MultiTexCoord2.xyz;
+
+ vec3 normal = vec3(-normalize(cross(vec3(2*dx, hxp1-hxm1, 0), vec3(0, hzp1-hzm1, 2*dx))));//vec3(0,1,0);
+ vec3 bitangent = normalize(cross(vec3(1,0,0), normal));
+ vec3 tangent = normalize(cross(bitangent, normal));
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos, 1.0); // eye space
+ gl_TexCoord[0] = gl_MultiTexCoord2 * foamFactor;
+ gl_TexCoord[1] = gl_ModelViewMatrix * vec4(tangent, 0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(normal, 0.0);
+ gl_TexCoord[3] = gl_ModelViewMatrix * vec4(bitangent, 0.0);
+
+ gl_TexCoord[0].w = max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10;// Fade with life time
+ gl_FrontColor = gl_Color;
+}
+);
+const char *particleFoamVS = STRINGIFY(
+uniform float timestep = 0.02;
+// GPU Water
+uniform float minEta;
+uniform float fracEta;
+
+uniform float dx;
+uniform vec4 foamFactor = vec4(1.0/4, 1.0/4,0,0);
+uniform float foamOffset;
+uniform float foamOffset2;
+uniform float foamOffset3;
+void main()
+{
+
+
+ vec3 pos = gl_Vertex.xyz;
+
+ vec3 normal = normalize(gl_MultiTexCoord2.xyz);
+ vec3 bitangent = normalize(cross(vec3(1,0,0), normal));
+ vec3 tangent = normalize(cross(bitangent, normal));
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos + normal*foamOffset + vec3(0.0f, foamOffset3, 0.0f), 1.0); // eye space
+ vec3 eyeVec = normalize(gl_Position.xyz);
+ gl_Position.xyz -= eyeVec*foamOffset2;
+ gl_TexCoord[0] = gl_MultiTexCoord2 * foamFactor;
+ gl_TexCoord[1] = gl_ModelViewMatrix * vec4(tangent, 0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(normal, 0.0);
+ gl_TexCoord[3] = gl_ModelViewMatrix * vec4(bitangent, 0.0);
+
+ gl_TexCoord[0].w = max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10;// Fade with life time
+ gl_FrontColor = gl_Color;
+}
+);
+
+const char *particleDumbFoamGS = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.25;
+uniform float foamTexSize = 0.249;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 x = pointRadius*gl_TexCoordIn[0][1].xyz;
+ vec3 normal = gl_TexCoordIn[0][2].xyz;
+ vec3 y = -pointRadius*gl_TexCoordIn[0][3].xyz;
+
+
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(0, 0, 0, 0);
+ gl_TexCoord[1] = vec4(normal, gl_TexCoordIn[0][0].w);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_TexCoord[3] = vec4(1, 1, 0, 0);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(0, foamTexSize, 0, 0);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(1, -1, 0, 0);
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(foamTexSize, 0, 0, 0);
+ gl_TexCoord[2] = vec4(pos - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(-1, 1, 0, 0);
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(foamTexSize, foamTexSize, 0, 0);
+ gl_TexCoord[2] = vec4(pos - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(-1, -1, 0, 0);
+ EmitVertex();
+
+}
+);
+
+const char *particleDumbFoamPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir;
+uniform sampler2D foamTex;
+uniform sampler2DArrayShadow stex;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float foamAmbient = 0.8f;
+uniform float foamDiffuse = 0.2f;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ float mag = clamp(1.1-dot(gl_TexCoord[3].xy,gl_TexCoord[3].xy),0,1);
+
+
+ gl_FragColor.xyz = mix(gl_Fog.color, gl_Color*(foamAmbient + (foamDiffuse*max(dot(gl_TexCoord[1].xyz, lightDir),0.0f) )*shadowCoef()), fog);//*falloff;
+ gl_FragColor.w = /*texture2D(foamTex, gl_TexCoord[0]).r**/gl_Color.w*mag*gl_TexCoord[1].w;
+//
+
+}
+);
+
+const char *particleFoamPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir;
+uniform sampler2D foamTex;
+uniform sampler2DArrayShadow stex;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float foamAmbient = 0.5f;
+uniform float foamDiffuse = 0.5f;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ float mag = clamp(1.1-dot(gl_TexCoord[3].xy,gl_TexCoord[3].xy),0,1);
+
+
+ gl_FragColor.xyz = gl_Color*(
+ foamAmbient + (foamDiffuse*abs(dot(gl_TexCoord[1].xyz, lightDir)))*shadowCoef()
+ );//*falloff;
+ gl_FragColor.w = /*texture2D(foamTex, gl_TexCoord[0]).r**/gl_Color.w*mag*gl_TexCoord[1].w;
+//
+
+}
+);
+
+// screen-space shaders
+const char *passThruVS = STRINGIFY(
+void main()
+{
+ gl_Position = gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_TexCoord[1] = gl_Vertex;
+ gl_FrontColor = gl_Color;
+}
+);
+
+// blur depth map
+// separable version
+const char *depthBlurPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0 / r;
+uniform float blurDepthFalloff = 2.0;
+uniform float depthThreshold = 0.5;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float sum = 0;
+ float wsum = 0;
+ for(float x=-r; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + x*scale).x;
+
+ // bilateral filter
+ // spatial domain
+ float r = x * blurScale;
+ float w = exp(-r*r);
+ //float w = 1.0;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * blurDepthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+ //float g = abs(sample - center) < depthThreshold;
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// 2D non-separable version
+const char *depthBlur2DPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0 / r;
+uniform float blurDepthFalloff = 1.0;
+uniform float depthThreshold = 0.1;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center < -9999.0) {
+ discard;
+ return;
+ }
+
+ float sum = 0;
+ float wsum = 0;
+ for(float y=-r; y<=r; y+=1.0) {
+ for(float x=-r; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + vec2(x, y)).x;
+
+ // bilateral filter
+ // spatial domain
+ //float r = length(vec2(x, y)) * blurScale;
+ // float w = exp(-r*r);
+ float rsq = (x*x + y*y) * blurScale * blurScale;
+ float w = exp(-rsq);
+ //float w = 1.0;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * blurDepthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+// float g = abs(sample - center) < depthThreshold;
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// symmetrical filter (see "Screen Space Meshes" paper)
+const char *depthBlurSymPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0;
+uniform float blurDepthFalloff = 2.0;
+uniform float depthThreshold = 0.25;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center == 0.0) {
+ discard; return;
+ }
+
+ float sum = center;
+ float wsum = 1.0;
+
+ for(float x=1.0; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + x*scale).x;
+ float sample2 = texture2DRect(colorTex, gl_TexCoord[0].xy - x*scale).x;
+
+ bool valid = abs(sample - center) < depthThreshold;
+ bool valid2 = abs(sample2 - center) < depthThreshold;
+
+ if (valid && valid2) {
+ float r = (x / r) * blurScale;
+ float w = exp(-r*r);
+
+ sum += sample * w;
+ wsum += w;
+
+ sum += sample2 * w;
+ wsum += w;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// display final shaded surface
+const char *displaySurfacePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(1.0, 1.0, 1.0, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.3;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+// float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+// vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ float refraction = thickness*thicknessRefraction.x;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+/*
+ // dispersive refraction
+ vec3 refraction = thickness*thicknessRefraction;
+ vec4 sceneCol;
+ sceneCol.r = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.x)).r;
+ sceneCol.g = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.y)).g;
+ sceneCol.b = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.z)).b;
+ sceneCol.a = 1.0;
+*/
+
+ vec4 finalCol = vec4(attenuatedColor.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+ float alpha = saturate(attenuatedColor.w);
+
+// gl_FragColor = -c.z;
+// gl_FragColor = vec4(n*0.5+0.5, 1.0);
+// gl_FragColor = vec4(diffuse.xxx, 1.0);
+// gl_FragColor = vec4(specular.xxx, 1.0);
+// gl_FragColor = vec4(fresnel.xxx, 1.0);
+// gl_FragColor = diffuse*fluidColor + specular;
+// gl_FragColor = vec4(eyePos*0.5+0.5, 1.0);
+// gl_FragColor = thickness;
+// gl_FragColor = vec4(attenuatedColor.xyz, 1.0);
+// gl_FragColor = attenuatedColor.w;
+// gl_FragColor = alpha;
+
+ gl_FragColor = lerp(finalCol, sceneCol, alpha);
+
+// gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+// gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+ //gl_FragColor.w = 1.0;
+}
+);
+
+// new version (handles transparency differently)
+const char *displaySurfaceNewPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.5, 0.5, 0.5, 1.0);
+
+uniform float falloffScale = 0.01;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.1, 2.2);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+// float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+// float refraction = thickness*thicknessRefraction.x;
+// vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ // dispersive refraction
+ vec3 refraction = thickness*thicknessRefraction;
+ vec4 sceneCol;
+ sceneCol.r = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.x)).r;
+ sceneCol.g = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.y)).g;
+ sceneCol.b = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.z)).b;
+ sceneCol.a = 1.0;
+
+ gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+// non-transparent version for oil etc.
+const char *displaySurfaceSolidPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 diffuseColor = vec4(0.0, 0.0, 0.0, 0.0);
+uniform vec4 specularColor = vec4(0.75, 0.75, 0.75, 1.0);
+
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+ float diffuse = max(0.0, dot(n, lightDir));
+// float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ gl_FragColor = diffuseColor*diffuse + reflectColor*fresnel + specularColor*specular;
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+// chrome surface using cubemap
+const char *displaySurfaceChromePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform float subSample = 1;
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = ddx2;
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+// if (abs(ddy2.z) < abs(ddy.z)) {
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = ddy2;
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+ float diffuse = max(0.0, dot(n, lightDir));
+// float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+// vec3 v = vec3(0, 0, 1);
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+// float fresnel = pow(1.0 - max(0.0, dot(n, v)), 5.0);
+ float fresnel = 0.2 + 0.8*pow(1.0 - max(0.0, dot(n, v)), 2.0);
+ //float fresnel = 1.0 - max(0.0, dot(n, v));
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+// r = (mat3) gl_ModelViewMatrixInverse * r;
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+// gl_FragColor = reflectColor * fresnel;
+ gl_FragColor = reflectColor * (0.5 + 0.5*diffuse);
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+
+const char *textureRectPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect tex;
+
+void main()
+{
+ gl_FragColor = texture2DRect(tex, gl_TexCoord[0].xy);
+}
+);
+
+// dilate depth image by taking maximum value of neighbourhood
+const char *dilatePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect tex;
+
+void main()
+{
+ float c = texture2DRect(tex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 0)).x);
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 1)).x);
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, 1)).x);
+
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(-1, 0)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 0)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, -1)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, 1)).x);
+ }
+
+ gl_FragColor = c;
+}
+);
+
+// NUTT
+// Water heightfield thickness vertex shader
+const char *hfThicknessVS = STRINGIFY(
+uniform float zMax;
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * vec4(gl_Vertex.xyz,1);
+
+
+ vec4 eyeNormal = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0);
+ //gl_TexCoord[0] = vec4(eyeSpacePos.xyz,0); // sprite texcoord
+
+ //float tc = 0.1*(zFar + eyeSpacePos.z);
+ float dis = sqrt(dot(eyeSpacePos,eyeSpacePos));
+ float tc = (zMax-dis);
+ //gl_FrontColor = vec4(tc,tc,-tc,1);
+ //gl_BackColor = vec4(-tc,-tc,-tc,1);
+ //float tc = 0.1;
+
+ if (dot(eyeNormal.xyz,eyeSpacePos.xyz) > 0) {
+ gl_TexCoord[0] = vec4(tc,tc,tc,1);
+ } else
+ {
+ gl_TexCoord[0]= vec4(-tc,-tc,-tc,1);
+
+ }
+ gl_Position = gl_ProjectionMatrix * eyeSpacePos;
+ //gl_BackColor = vec4(1,1,1,1);//vec4(-1000,-1000,-1000,1);//vec4(-2*tc,-2*tc,-2*tc,1);
+}
+);
+
+
+// Water heightfield thickness PS
+const char *hfThicknessPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+void main()
+{
+
+ gl_FragColor = gl_TexCoord[0];
+ //gl_FragColor = gl_Color;
+ //gl_FragColor = (
+}
+);
+
+// Water heightfield thickness PS
+const char *hfThicknessAddPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect thicknessTex;
+void main()
+{
+ // Add contribution of heightfield fluid thickness to particle thickness
+ vec4 col = texture2DRect(thicknessTex, gl_TexCoord[0].xy);
+ col.x = max(col.x, 0.0);
+ //col.x*=-1;
+ /*
+ if (col.x > 10) {
+ gl_FragColor = vec4(0,0,0,1);
+ } else { */
+ gl_FragColor = vec4(col.x,col.x,col.x,1);
+ //}
+}
+);
+// Water heightfield depth vertex shader
+const char *hfDepthVS = STRINGIFY(
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = vec4(eyeSpacePos.xyz,0); // sprite texcoord
+
+}
+);
+// Water heightfield depth PS
+const char *hfDepthPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+ void main()
+{
+ gl_FragColor = vec4(gl_TexCoord[0].z,gl_TexCoord[0].z,gl_TexCoord[0].z,1);
+}
+);
+
+// Turn depth map to distance from eye and subtract
+const char *depthToInitThicknessPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect depthTex;
+uniform float zNear;
+uniform float zFar;
+uniform float mulX;
+uniform float mulY;
+uniform float zMax;
+
+void main()
+{
+ float glDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float eyeDepth = zNear*zFar / (zFar - glDepth*(zFar-zNear));
+ gl_FragDepth = glDepth;
+ //gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ //gl_FragColor = vec4(gl_FragDepth,gl_FragDepth,gl_FragDepth,1);
+ //float val = 0.001*(-(zFar - eyeDepth));
+ //float val = -(zFar-eyeDepth)*0.1;
+ vec3 eyePos = vec3(gl_TexCoord[1].x*eyeDepth*mulX, gl_TexCoord[1].y*eyeDepth*mulY, eyeDepth);
+
+ float val = -(zMax-sqrt(dot(eyePos,eyePos)));
+ gl_FragColor = vec4( val,val,val, 1);
+
+
+}
+);
+
+// Debug PS
+const char *debugPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect thicknessTex;
+
+void main()
+{
+ vec4 col = texture2DRect(thicknessTex, gl_TexCoord[0].xy);
+
+ col.x*=-0.01;
+// if (col.x > 1) {
+// gl_FragColor = vec4(1,0,0,1);
+// } else {
+ gl_FragColor = vec4(col.x,col.x,col.x,1);
+// }
+ //gl_FragColor = vec4(1,0,1,1);
+}
+);
+
+
+// Debug Triangle VS
+const char *debugTriVS = STRINGIFY(
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ vec4 eyeSpaceNormal = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,1);
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vec3 eyeVec = normalize(eyeSpacePos.xyz);
+ float dp = dot(eyeSpaceNormal.xyz,eyeVec.xyz);
+
+ if (dp > 0) {
+ gl_FrontColor = vec4(dp,0,0,1);
+ } else {
+ gl_FrontColor = vec4(0,-dp,0,1);
+ }
+}
+);
+const char *copyPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect depthTex;
+uniform sampler2DRect sceneTex;
+void main()
+{
+ gl_FragColor = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+}
+);
+
+
+// Debug Triangle PS
+const char *debugTriPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+void main()
+{
+ gl_FragColor = gl_Color;
+}
+);
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.03;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+uniform float shadowAmbient = 0.9;
+uniform float splashZShadowBias = 0.001f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess*10);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel /*+ specularColor.xyz*specular*/, 1.0);
+ float shadow = shadowCoef(eyePos);
+ float sc = (1.0f - shadowAmbient)*shadow + shadowAmbient;
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular*shadow*0.9, 1.0);
+
+ gl_FragColor = vec4(finalCol.xyz*(sc), max(0.0f, min(1.0, thicknessAlphaMul*thickness/*2.0f*(gl_TexCoord[1].w+waterHOffset)*/)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ /*
+ vec4 sceneSeethroughCol = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+
+
+ //----------------
+ float thickPar = 0.0000001;
+ float blendBackground = max(0.0, min(1.0f, -thickness / thickPar));
+
+
+ gl_FragColor = (blendBackground)*finalCol + (1.0-blendBackground)*sceneSeethroughCol;
+ if (thickness < 0) gl_FragColor = vec4(1.0f,0.0f,0.0f,1.0f); else */
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+ //gl_FragColor = vec4(n.z, n.z, n.z, 1);
+}
+);
+
+
+
+// render particle as lit sphere
+const char *particleBubblePS = STRINGIFY(
+ uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform samplerCube cubemapTex;
+uniform sampler2DRect sceneTex;
+
+uniform vec2 viewportd2 = vec2(300,300);
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.5, 0.5, 0.5, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.3;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ //gl_FragColor = diffuse*gl_Color;
+ gl_FragColor = gl_Color;
+ gl_FragColor.w = (1.0-r2)*(1.0-r2)*0.4;
+
+
+ vec3 v = normalize(-eyeSpacePos.xyz);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(N, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(N, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, N);
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = 0;
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ vec2 tx = viewportd2 + viewportd2*vec2(clipSpacePos.x/clipSpacePos.w, clipSpacePos.y/clipSpacePos.w);
+ vec4 sceneCol = texture2DRect(sceneTex, tx);
+ //vec4 sceneCol = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+ //sceneCol = vec4(1,1,1,1);''
+
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+ //vec4 finalCol = vec4((1-fresnel)*specularColor.xyz*specular, 1.0);
+
+ float vn = (1-dot(N,v));
+ finalCol = vn*vn*gl_Color+specularColor*specular;
+
+ finalCol.w = finalCol.x;
+ finalCol.xyz = gl_Color;
+
+ //----------------
+ gl_FragColor = finalCol*0.8;
+
+ //gl_FragColor.w = 0.4;
+ //gl_FragColor = vec4(clipSpacePos.x/clipSpacePos.w, clipSpacePos.y/clipSpacePos.w, 0, 1);
+
+ //gl_FragColor *= gl_FragColor.w;
+}
+);
+
+const char *depthBlurViewIDPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform float world2texScale;
+uniform float tex2worldScale;
+uniform float maxBlurRadius = 50;
+uniform float blurRadiusImagePlane = 10; // in world space
+uniform vec2 blurDir; // direction of blur
+uniform float XYFalloff = 0.02;
+uniform float depthFalloff = 1.00;
+
+void main()
+{
+ float center = -texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+
+
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float myWorld2Tex = world2texScale / center;
+ float rawRad = blurRadiusImagePlane / center;
+ float sampleRadius = round(rawRad);
+ sampleRadius = min(sampleRadius, maxBlurRadius);
+ sampleRadius = max(0.0, sampleRadius);
+
+ float myTex2World = tex2worldScale * center;
+
+ //sampleRadius = max(0.0f, sampleRadius);
+ //sampleRadius = 0;
+ float sum = 0;
+ float wsum = 0;
+
+
+ for(float i=-sampleRadius; i<=sampleRadius; i+=1) { // step of 1 pixel
+ float sample = -texture2DRect(colorTex, gl_TexCoord[0].xy + i*blurDir).x;
+
+
+ float x = i * myTex2World;
+
+ // bilateral filter
+ // spatial domain
+ float r = x * XYFalloff;
+ float cut = (rawRad - abs(i)) / (rawRad);
+ float w = exp(-r*r) * max(0.0f, pow(cut, 0.4)) ;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * depthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = -sum;
+
+}
+);
+const char *depthBlurViewIDNonSepPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform float world2texScale;
+uniform float tex2worldScale;
+uniform float maxBlurRadius = 2;
+uniform float blurRadiusImagePlane = 10; // in world space
+uniform float XYFalloff = 0.02;
+uniform float depthFalloff = 1.00;
+
+void main()
+{
+ float center = -texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+
+
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float myWorld2Tex = world2texScale / center;
+ float rawRad = blurRadiusImagePlane / center;
+ float sampleRadius = round(rawRad);
+ sampleRadius = min(sampleRadius, maxBlurRadius);
+ sampleRadius = max(0.0, sampleRadius);
+
+ float myTex2World = tex2worldScale * center;
+
+ //sampleRadius = max(0.0f, sampleRadius);
+ //sampleRadius = 0;
+ float sum = 0;
+ float wsum = 0;
+
+
+ for(float i=-sampleRadius; i<=sampleRadius; i+=1) { // step of 1 pixel
+ float y = i * myTex2World;
+ for(float j=-sampleRadius; j<=sampleRadius; j+=1) { // step of 1 pixel
+ float sample = -texture2DRect(colorTex, gl_TexCoord[0].xy + vec2(j, i)).x;
+
+ float x = j * myTex2World;
+ float dis = sqrt(x*x+y*y);
+
+ // bilateral filter
+ // spatial domain
+ float r = dis * XYFalloff;
+ float cut = (rawRad - abs(i)) / (rawRad);
+ float w = exp(-r*r) * max(0.0f, pow(cut, 0.4)) ;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * depthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = -sum;
+
+}
+);
+
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutEscapePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 1.0f;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+uniform float shadowAmbient = 0.9;
+uniform float splashZShadowBias = 0.0f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+uniform float thicknessScale = 1.0f;
+uniform float thicknessClamp = 1000.0f;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = min(thicknessClamp, texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x* thicknessScale);
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir); // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);//textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+
+
+
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec2 refractedCoord = gl_TexCoord[0].xy + (n.xy * refraction);
+
+ // don't refract objects in front of surface
+// float bgDepth = texture2DRect(sceneDepthTex, refractedCoord).x;
+
+ // if (bgDepth < surfaceDepth) refractedCoord = gl_TexCoord[0].xy;
+ //refractedCoord = lerp(refractedCoord, gl_TexCoord[0].xy, smoothstep(0.01, 0.0, bgDepth - surfaceDepth));
+
+ vec4 sceneCol = texture2DRect(sceneTex, refractedCoord);
+
+
+
+
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + (reflectColor.xyz )*fresnel + specularColor.xyz*specular, 1.0);
+
+ gl_FragColor = vec4(diffuse, diffuse, diffuse, 1.0f);//finalCol;
+ gl_FragColor = finalCol;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ /*
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel , 1.0);
+
+ float shadow = shadowCoef(eyePos);
+ gl_FragColor = vec4(finalCol.xyz*((1.0f - shadowAmbient)*shadow + shadowAmbient), max(0.0f, min(1.0, thicknessAlphaMul*thickness)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ */
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+
+}
+);
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutEscapeDiffusePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 1.0f;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+uniform float splashZShadowBias = -0.001f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+uniform float thicknessScale = 1.0f;
+uniform float thicknessClamp = 1000.0f;
+
+uniform vec3 spotLightPos;
+uniform vec3 spotLightPos2;
+uniform vec3 spotLightPos3;
+uniform float shadowAmbient = 0.5f;
+
+//#define BLUISH 1
+const int BLUISH = 0;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = min(thicknessClamp, texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x* thicknessScale);
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+ if (dot(n, eyePos.xyz) > 0) {
+ n.xyz *= -1;
+ }
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ //float diffuse = dot(n, lightDir); // wrap lighting
+ vec3 lvec = normalize(spotLightPos - eyePos);
+ vec3 lvec2 = normalize(spotLightPos2 - eyePos);
+ vec3 lvec3 = normalize(spotLightPos3 - eyePos);
+
+ float shadowC = shadowCoef(eyePos);
+ float shadowFactor = ((1.0f - shadowAmbient)*shadowC + shadowAmbient);
+ float diffuse = (0.33333f*0.7f*(max(dot(n, lvec),0.0f)+max(dot(n, lvec2),0.0f)+max(dot(n, lvec3),0.0f)))*shadowFactor+0.3f; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);//textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+
+
+
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec2 refractedCoord = gl_TexCoord[0].xy + (n.xy * refraction);
+
+ // don't refract objects in front of surface
+// float bgDepth = texture2DRect(sceneDepthTex, refractedCoord).x;
+
+ // if (bgDepth < surfaceDepth) refractedCoord = gl_TexCoord[0].xy;
+ //refractedCoord = lerp(refractedCoord, gl_TexCoord[0].xy, smoothstep(0.01, 0.0, bgDepth - surfaceDepth));
+
+
+
+
+
+
+
+
+ vec3 sceneCol = texture2DRect(sceneTex, gl_TexCoord[0].xy).xyz;
+ vec3 bb = vec3(diffuse,diffuse,diffuse);
+ if (BLUISH) {
+ vec4 col1 = 1.5*vec4(116,147,179,255) / 200.0;
+ bb = col1.xyz*diffuse;
+ }
+//#endif
+ float alpha = clamp(thickness, 0.0f, 1.0f);
+
+
+ gl_FragColor.xyz = (1.0f-alpha)*sceneCol + alpha*bb;
+ gl_FragColor.w = 1.0f;
+ //gl_FragColor = finalCol;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ /*
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel , 1.0);
+
+ float shadow = shadowCoef(eyePos);
+ gl_FragColor = vec4(finalCol.xyz*((1.0f - shadowAmbient)*shadow + shadowAmbient), max(0.0f, min(1.0, thicknessAlphaMul*thickness)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ */
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+
+}
+);
+
+const char *texture2DPS = STRINGIFY(
+ uniform sampler2D tex; \n
+ void main() \n
+{ \n
+gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); \n
+} \n
+);
+
+#if TECHNICAL_MODE
+
+const char *particleSmokeUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.3;
+
+float shadowCoef()
+{
+ const int index = 0;
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+uniform sampler2D smokeTex;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ //gl_FragColor = gl_Color;
+ //return;
+
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = shadowCoef();
+
+ vec3 shadowColor = vec3(0.4, 0.4, 0.4)*0.8;
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC *= (1.0f-att);
+ float inS = shadowC;
+ shadowC = (shadowAmbient + (1.0f -shadowAmbient)*shadowC);
+ //....
+ if (gl_TexCoord[0].z > 1) shadowC = 1;
+ vec4 texColor = texture2D(smokeTex, gl_TexCoord[0].xy*0.25+gl_TexCoord[1].xy);
+
+ gl_FragColor.xyz = (texColor.x)*gl_Color.xyz*(shadowColor + (vec3(1.0f,1,1) -shadowColor)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w*texColor.r;
+
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.xyz *= 1.6f;
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+ //gl_FragColor.w = 1;
+ //gl_FragColor.xyz = vec3(shadowC, shadowC, shadowC);
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ gl_FragColor.xyz *= ((gl_TexCoord[0].z)+inS*0.3)*0.7;
+ //gl_FragDepth = gl_FragCoord.z - (1-mag)*0.00002;
+
+}
+);
+
+#else
+const char *particleSmokeUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.3;
+
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+uniform sampler2D smokeTex;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ //gl_FragColor = gl_Color;
+ //return;
+/*
+ gl_FragColor = texture2D(smokeTex, gl_TexCoord[0].xy);
+ gl_FragColor.w = gl_FragColor.r;
+ gl_FragColor.xyz = vec3(1,1,1);
+ return;
+*/
+// gl_FragColor = vec4(1,0,0,1);
+// return;
+
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = shadowCoef();
+
+ vec3 shadowColor = vec3(0.4, 0.4, 0.9)*0.8;
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC *= (1.0f-att);
+ float inS = shadowC;
+ shadowC = (shadowAmbient + (1.0f -shadowAmbient)*shadowC);
+ //....
+ if (gl_TexCoord[0].z > 1) shadowC = 1;
+ vec4 texColor = texture2D(smokeTex, gl_TexCoord[0].xy*0.25+gl_TexCoord[1].xy);
+
+ gl_FragColor.xyz = (texColor.x)*gl_Color.xyz*(shadowColor + (vec3(1.0f,1,1) -shadowColor)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w*texColor.r;
+
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.xyz *= 1.6f;
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+ //gl_FragColor.w = 1;
+ //gl_FragColor.xyz = vec3(shadowC, shadowC, shadowC);
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ gl_FragColor.xyz *= ((gl_TexCoord[0].z)+inS*0.3)*0.7;
+ //gl_FragDepth = gl_FragCoord.z - (1-mag)*0.00002;
+
+}
+);
+
+#endif
+// sky box
+const char *skyboxVS = STRINGIFY(
+ uniform vec3 projectionCenter = vec3(0,0,0);
+
+void main()
+{
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ // gl_Position = gl_Vertex;
+ // gl_Position = gl_ProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0].xyz = (gl_Vertex.xyz + projectionCenter);
+ // gl_TexCoord[0].xyz = (mat3) gl_ModelViewMatrix * gl_Vertex.xyz;
+ gl_FrontColor = gl_Color;
+}
+);
+
+const char *skyboxPS = STRINGIFY(
+ uniform samplerCube cubemap;
+
+void main()
+{
+ gl_FragColor = textureCube(cubemap, gl_TexCoord[0].xyz * vec3(1, 1, 1));
+
+ gl_FragColor.x = 1.5 * pow(gl_FragColor.x, 2.2);
+ gl_FragColor.y = 1.5 * pow(gl_FragColor.y, 2.2);
+ gl_FragColor.z = 1.5 * pow(gl_FragColor.z, 2.2);
+ gl_FragColor.w = 1.5 * pow(gl_FragColor.w, 2.2);
+}
+);
diff --git a/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h
new file mode 100644
index 00000000..55ad55c2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h
@@ -0,0 +1,21 @@
+extern const char *particleVS,*particleVSNoKill;
+extern const char *particleSpherePS, *particleDebugPS, *particleDensityPS, *particleFoamPS, *particleFoamVS, *particleBubblePS;
+extern const char *particleSurfacePS, *particleThicknessPS;
+extern const char *mblurVS, *mblurGS, *mblurGSNoKill, *particleSprayPS;
+extern const char *passThruVS;
+extern const char *depthBlurPS , *depthBlur2DPS, *depthBlurSymPS, *displaySurfacePS, *displaySurfaceNewPS, *displaySurfaceChromePS, *displaySurfaceSolidPS;
+extern const char *depthBlurViewIDPS, *depthBlurViewIDNonSepPS;
+extern const char *textureRectPS, *dilatePS, *copyPS;
+
+// Nutt
+extern const char *depthToInitThicknessPS;
+extern const char *hfDepthPS, *hfDepthVS, *hfThicknessVS, *hfThicknessPS;
+extern const char *debugPS, *debugTriVS, *debugTriPS;
+extern const char *hfThicknessAddPS, *displaySurfaceNutPS, *particleDumbFoamVS, *particleDumbFoamGS, *particleDumbFoamPS, *displaySurfaceNutEscapePS, *displaySurfaceNutEscapeDiffusePS, *particleSprayUseFOMPS, *particleSprayGenFOMPS ;
+
+extern const char *texture2DPS;
+
+extern const char *particleSmokeUseFOMPS;
+
+extern const char *skyboxVS;
+extern const char *skyboxPS; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp b/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp
new file mode 100644
index 00000000..c35a0af4
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp
@@ -0,0 +1,271 @@
+
+#include "glmesh.h"
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <vector>
+#include <iostream>
+using namespace std;
+GLMesh::GLMesh(GLuint elementTypei) {
+ firstTimeBO = true;
+ vbo = ibo = 0;
+ withTexture = withColor = withNormal = withTangent = false;
+ elementType = elementTypei;
+}
+GLMesh::~GLMesh() {
+ firstTimeBO = true;
+ if (vbo) {
+ glDeleteBuffersARB(1, &vbo);
+ }
+ if (ibo) {
+ glDeleteBuffersARB(1, &ibo);
+ }
+}
+void GLMesh::reset() {
+ firstTimeBO = true;
+ if (vbo) {
+ glDeleteBuffersARB(1, &vbo);
+ }
+ if (ibo) {
+ glDeleteBuffersARB(1, &ibo);
+ }
+ vbo = ibo = 0;
+ withTexture = withColor = withNormal = withTangent = false;
+
+ indices.clear();
+ vertices.clear();
+ normals.clear();
+ colors.clear();
+ texCoords.clear(); // treats as u v
+ tangents.clear();
+ bitangents.clear();
+
+ // For raw
+ rawVertices.clear();
+ rawNormals.clear();
+
+}
+void GLMesh::genVBOIBO() {
+ glGenBuffersARB(1, &vbo);
+ glGenBuffersARB(1, &ibo);
+}
+void GLMesh::updateVBOIBO(bool dynamicVB) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
+ int bytesv = 0;
+ if (firstTimeBO) {
+ //if (!((vertices.size() > 0) && (indices.size() > 0) && (normals.size() == 0) && (texCoords.size() > 0) && (colors.size() > 0))) {
+ // // Only support pos, texcoord, color, no normal for now :P
+ // exit(-129);
+ //}
+ bytesv = vertices.size()*sizeof(float)*(3); //position 3, color 3, tex coord 2
+ withColor = (colors.size() != 0);
+ withTexture = (texCoords.size() != 0);
+ withNormal = (normals.size() != 0);
+ withTangent = (tangents.size() != 0) && (bitangents.size() != 0);
+ if (withColor) bytesv += vertices.size()*sizeof(float)*(3);
+ if (withTexture) bytesv += vertices.size()*sizeof(float)*(2);
+ if (withNormal) bytesv += vertices.size()*sizeof(float)*(3);
+ if (withTangent) bytesv += vertices.size()*sizeof(float)*(6);
+
+ vector<char> dummy(bytesv, 0);
+
+
+ if (dynamicVB) {
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)&dummy[0], GL_DYNAMIC_DRAW_ARB);
+ } else {
+ //glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)&dummy[0], GL_STATIC_DRAW_ARB);
+ }
+
+ int bytesi = indices.size()*sizeof(PxU32);
+
+ dummy.resize(bytesi, 0);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bytesi, (const void*)&indices[0], GL_STATIC_DRAW_ARB); // index never change
+ firstTimeBO = 0;
+
+ }
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+
+
+ float* vb = 0;
+
+ if (dynamicVB) vb = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); else {
+ vb = new float[bytesv / sizeof(float)];
+
+ }
+
+
+ int numV = vertices.size();
+ int pos = 0;
+
+
+ memcpy(vb, &vertices[0], sizeof(PxVec3)*numV);
+ pos+=3*numV;
+
+ if (withColor) {
+ memcpy(&vb[pos], &colors[0], sizeof(PxVec3)*numV);
+ pos+=3*numV;
+ }
+
+ if (withTexture) {
+ memcpy(&vb[pos], &texCoords[0], sizeof(float)*numV*2);
+ pos+=2*numV;
+ }
+
+ if (withNormal) {
+ memcpy(&vb[pos], &normals[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ }
+
+
+ if (withTangent) {
+
+ memcpy(&vb[pos], &tangents[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ memcpy(&vb[pos], &bitangents[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ }
+ if (dynamicVB) {
+ glUnmapBuffer(GL_ARRAY_BUFFER_ARB);
+ } else {
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)vb, GL_STATIC_DRAW_ARB);
+ delete vb;
+
+ }
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+}
+void GLMesh::drawVBOIBO(bool enable, bool draw, bool disable, bool drawpoints) {
+
+ if ((vbo == 0) || (ibo == 0)) return;
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
+
+
+ // Only support pos, texcoord, color, no normal for now :P
+ int numV = vertices.size();
+ if(enable) glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), 0);
+ GLuint pos = 3*sizeof(float)*numV;
+ if (withColor) {
+ if(enable) glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+ if (withTexture) {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=2*sizeof(float)*numV;
+ }
+ if (withNormal) {
+ if(enable) glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+
+ if (withTangent) {
+
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ if(enable) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ glTexCoordPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ if(enable) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ glTexCoordPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+
+ if (draw) {
+ if (!drawpoints) {
+ glDrawElements(elementType, indices.size(), GL_UNSIGNED_INT, 0);
+ } else {
+ glDrawArrays(GL_POINTS, 0, numV);
+ }
+ }
+
+ if (disable) {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+}
+
+void GLMesh::draw() {
+ if ((vertices.size() > 0) && (indices.size() > 0)) {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &vertices[0]);
+
+ if (normals.size() > 0) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), &normals[0]);
+ }
+
+ if (texCoords.size() > 0) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, &texCoords[0]);
+ }
+
+ if (colors.size() > 0) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, &colors[0]);
+ }
+
+ //if (mTexId > 0) {
+ // glColor3f(1.0f, 1.0f, 1.0f);
+ // glEnable(GL_TEXTURE_2D);
+ // glBindTexture(GL_TEXTURE_2D, mTexId);
+ //}
+ //else {
+ // glColor3f(0.5f, 0.5f, 0.5f);
+ // glDisable(GL_TEXTURE_2D);
+ //}
+
+ glDrawElements(elementType, indices.size(), GL_UNSIGNED_INT, &indices[0]);
+ }
+ if (texCoords.size() > 0) {
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ if (colors.size() > 0) {
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+ if (rawVertices.size() > 0) {
+ // Also draw raw buffer
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &rawVertices[0]);
+ if (rawNormals.size() > 0) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), &rawNormals[0]);
+ }
+ glDrawArrays(elementType, 0, rawVertices.size());
+
+
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+
+ //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ //glDisable(GL_TEXTURE_2D);
+
+
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/Render/glmesh.h b/KaplaDemo/samples/sampleViewer3/Render/glmesh.h
new file mode 100644
index 00000000..87097ab9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/glmesh.h
@@ -0,0 +1,42 @@
+
+#ifndef __GLMESH_H__
+#define __GLMESH_H__
+#include <GL/glew.h>
+
+#include "PxPhysics.h"
+#include <vector>
+using namespace physx;
+class GLMesh{
+public:
+ GLMesh(GLuint elementTypei = GL_TRIANGLES);
+ ~GLMesh();
+ void draw();
+
+ // For indices
+ std::vector<PxU32> indices;
+ std::vector<PxVec3> vertices;
+ std::vector<PxVec3> normals;
+ std::vector<PxVec3> colors;
+ std::vector<float> texCoords; // treats as u v
+ std::vector<PxVec3> tangents;
+ std::vector<PxVec3> bitangents;
+
+ // For raw
+ std::vector<PxVec3> rawVertices;
+ std::vector<PxVec3> rawNormals;
+
+ void reset();
+ void genVBOIBO();
+ void updateVBOIBO(bool dynamicVB = true);
+ void drawVBOIBO(bool enable = true, bool draw = true, bool disable = true, bool drawpoints = false);
+
+ // For vertex buffer
+ GLuint vbo;
+ GLuint ibo;
+ bool firstTimeBO;
+ bool withTexture, withColor, withNormal, withTangent;
+ GLuint elementType;
+
+
+};
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp b/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp
new file mode 100644
index 00000000..64b712ee
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp
@@ -0,0 +1,46 @@
+float seedDustRadius = 0.02f;
+//float seedDustNumPerSite = 15;
+//float seedDustNumPerSiteCollisionEvent = 3;
+float seedDustNumPerSite = 20;
+float seedDustNumPerSiteCollisionEvent = 4.5f;
+
+float applyForcePointAreaPerSample = 0.005f;
+float applyForceFromPointsDrag = 0.1f;
+//float noise3DScale = 1.5f;
+//float noise2DScale = 0.5f;
+float noiseKIsoDecay = 0.99f;
+float noiseKAniDecay = 0.99f;
+float noise3DScale = 0.75f*0.5f;
+float noise2DScale = 0.32f*0.5f;
+float dustMaxLife = 5.0f;
+float dustMinLife = 1.0f;
+float dustParticleOpacity = 0.1f;
+float dustParticleRenderRadius = 0.1f;
+float particleStartFade = 5.0f;
+float octaveScaling = 7.0f;
+float divStrength = 5.0f;
+float curDivStrength = 0.0f;
+float divStrengthReductionRate = 8.0f/30;
+
+bool doGaussianBlur = false;
+float blurVelSigmaFDX = 1.0f;
+float blurVelCenterFactor = 30.0f;
+float curlScale = 10.0f;
+
+float areaPerDustSample = 0.005f;
+float areaPerDebris = 0.02f;
+
+float minSizeDecayRate = 1.0f;
+float explodeVel = 3.0f;
+float numParPerMeteor = 3;
+
+float minMeteorDustLife = 2.0f;
+float maxMeteorDustLife = 2.3f;
+float minMeteorDustSize = 0.5f;
+float maxMeteorDustSize = 1.5f;
+float minMeteorSizeDecayRate = 1.0f;
+
+int maxNumDebrisPerType = 500; // Maximum number of debris per each type of debris
+float sleepingThresholdRB = 0.1f;
+float sleepingThresholdParticles = 0.1f;
+int maxNumDebrisToAdd = 100; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/newParameters.h b/KaplaDemo/samples/sampleViewer3/Render/newParameters.h
new file mode 100644
index 00000000..b1d26722
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/newParameters.h
@@ -0,0 +1,42 @@
+#pragma once
+extern float seedDustRadius;
+extern float seedDustNumPerSite;
+extern float seedDustNumPerSiteCollisionEvent;
+extern float applyForcePointAreaPerSample;
+extern float applyForceFromPointsDrag;
+extern float noiseKIsoDecay;
+extern float noiseKAniDecay;
+extern float noise3DScale;
+extern float noise2DScale;
+extern float dustMaxLife;
+extern float dustMinLife;
+extern float dustParticleOpacity;
+extern float dustParticleRenderRadius;
+extern float particleStartFade;
+extern float octaveScaling;
+extern float divStrength;
+extern float curDivStrength;
+extern float divStrengthReductionRate;
+
+
+extern bool doGaussianBlur;
+extern float blurVelSigmaFDX;
+extern float blurVelCenterFactor;
+extern float curlScale;
+extern float areaPerDustSample;
+extern float areaPerDebris;
+extern float minSizeDecayRate;
+
+extern float explodeVel; // Velocity of debris
+extern float numParPerMeteor;
+
+extern float minMeteorDustLife;
+extern float maxMeteorDustLife;
+extern float minMeteorDustSize;
+extern float maxMeteorDustSize;
+
+extern int maxNumDebrisPerType;
+extern float sleepingThresholdRB;
+extern float sleepingThresholdParticles;
+extern int maxNumDebrisToAdd;
+extern float minMeteorSizeDecayRate; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/RenderTarget.cpp b/KaplaDemo/samples/sampleViewer3/RenderTarget.cpp
new file mode 100644
index 00000000..9b0c7d26
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/RenderTarget.cpp
@@ -0,0 +1,80 @@
+#include "RenderTarget.h"
+
+
+// -------------------------------------------------------------------------------------------
+RenderTarget::RenderTarget(int width, int height)
+{
+ mColorTexId = 0;
+ mDepthTexId = 0;
+ mFBO = NULL;
+
+ resize(width, height);
+}
+
+// -------------------------------------------------------------------------------------------
+void RenderTarget::clear()
+{
+ if (mColorTexId > 0) {
+ glDeleteTextures(1, &mColorTexId);
+ mColorTexId = 0;
+ }
+ if (mDepthTexId > 0) {
+ glDeleteTextures(1, &mDepthTexId);
+ mDepthTexId = 0;
+ }
+ if (mFBO)
+ delete mFBO;
+
+ mFBO = NULL;
+}
+
+// -------------------------------------------------------------------------------------------
+RenderTarget::~RenderTarget()
+{
+ clear();
+}
+
+// -------------------------------------------------------------------------------------------
+GLuint RenderTarget::createTexture(GLenum target, int width, int height, GLint internalFormat, GLenum format)
+{
+ GLuint texid;
+ glGenTextures(1, &texid);
+ glBindTexture(target, texid);
+
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(target, 0, internalFormat, width, height, 0, format, GL_FLOAT, 0);
+ return texid;
+}
+
+// -------------------------------------------------------------------------------------------
+void RenderTarget::resize(int width, int height)
+{
+ clear();
+ mFBO = new FrameBufferObject();
+ mColorTexId = createTexture(GL_TEXTURE_RECTANGLE_ARB, width, height, GL_RGBA8, GL_RGBA);
+ mDepthTexId = createTexture(GL_TEXTURE_RECTANGLE_ARB, width, height, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT);
+}
+
+// -------------------------------------------------------------------------------------------
+void RenderTarget::beginCapture()
+{
+ mFBO->Bind();
+ mFBO->AttachTexture(GL_TEXTURE_RECTANGLE_ARB, mColorTexId, GL_COLOR_ATTACHMENT0_EXT);
+ mFBO->AttachTexture(GL_TEXTURE_RECTANGLE_ARB, mDepthTexId, GL_DEPTH_ATTACHMENT_EXT);
+ mFBO->IsValid();
+}
+
+// -------------------------------------------------------------------------------------------
+void RenderTarget::endCapture()
+{
+ mFBO->AttachTexture(GL_TEXTURE_RECTANGLE_ARB, 0, GL_COLOR_ATTACHMENT0_EXT);
+ mFBO->AttachTexture(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_ATTACHMENT_EXT);
+ mFBO->Disable();
+}
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/RenderTarget.h b/KaplaDemo/samples/sampleViewer3/RenderTarget.h
new file mode 100644
index 00000000..6f77127b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/RenderTarget.h
@@ -0,0 +1,31 @@
+#ifndef RENDER_TARGET
+#define RENDER_TARGET
+
+#include "FrameBufferObject.h"
+
+// -------------------------------------------------------------------------------------------
+class RenderTarget
+{
+public:
+ RenderTarget(int width, int height);
+ ~RenderTarget();
+
+ void resize(int width, int height);
+
+ void beginCapture();
+ void endCapture();
+
+ GLuint getColorTexId() { return mColorTexId; }
+ GLuint getDepthTexId() { return mDepthTexId; }
+
+private:
+ void clear();
+ GLuint createTexture(GLenum target, int width, int height, GLint internalFormat, GLenum format);
+
+ GLuint mColorTexId;
+ GLuint mDepthTexId;
+
+ FrameBufferObject *mFBO;
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SSAOHelper.cpp b/KaplaDemo/samples/sampleViewer3/SSAOHelper.cpp
new file mode 100644
index 00000000..84de751e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SSAOHelper.cpp
@@ -0,0 +1,399 @@
+#include "SSAOHelper.h"
+#include "foundation/PxMat44.h"
+const char *ssaoFilterVS = STRINGIFY(
+ void main(void)
+ {
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex * 2.0 - 1.0;
+ }
+);
+
+const char *ssaoFilterHFS = STRINGIFY(
+ uniform sampler2D ssaoTex;
+ uniform float sx;
+
+ void main (void)
+ {
+ float SSAO = 0.0;
+
+ for(int x = -2; x <= 2; x++)
+ {
+ SSAO += texture2D(ssaoTex,vec2(x * sx + gl_TexCoord[0].s,gl_TexCoord[0].t)).r * (3.0 - abs(float(x)));
+ }
+
+ gl_FragColor = vec4(vec3(SSAO / 9.0),1.0);
+ gl_FragColor.w = gl_FragColor.x;
+ }
+);
+
+const char *ssaoFilterVFS = STRINGIFY(
+ uniform sampler2D ssaoTex;
+ uniform float sy;
+
+ void main (void)
+ {
+
+ float SSAO = 0.0;
+
+ for(int y = -2; y <= 2; y++)
+ {
+ SSAO += texture2D(ssaoTex,vec2(gl_TexCoord[0].s,y * sy + gl_TexCoord[0].t)).r * (3.0 - abs(float(y)));
+ }
+
+ gl_FragColor = vec4(vec3(pow((SSAO / 9.0),1.5)),1.0);
+ gl_FragColor.w = gl_FragColor.x;
+ //gl_FragColor = vec4(1,1,1,1);
+ }
+);
+SSAOHelper::SSAOHelper(float fov,float padding,float zNear,float zFar, const char* resourcePath, float scale) : fov(fov),padding(padding),zNear(zNear),zFar(zFar), scale(scale) {
+
+ char ssaoVSF[5000];
+ char ssaoFSF[5000];
+ sprintf(ssaoVSF, "%s\\ssao.vs", resourcePath);
+ sprintf(ssaoFSF, "%s\\ssao.fs", resourcePath);
+ SSAOFilterH.loadShaderCode(ssaoFilterVS,ssaoFilterHFS);
+ SSAOFilterV.loadShaderCode(ssaoFilterVS,ssaoFilterVFS);
+ SSAO.loadShaders(ssaoVSF,ssaoFSF);
+
+ glUseProgram(SSAO);
+ glUniform1i(glGetUniformLocation(SSAO,"depthTex"),0);
+ glUniform1i(glGetUniformLocation(SSAO,"normalTex"),1);
+ glUniform1i(glGetUniformLocation(SSAO,"unitVecTex"),2);
+ glUseProgram(0);
+// srand(GetTickCount());
+
+ glGenTextures(1,&unitVecTex);
+
+ PxVec3 *RandomUnitVectorsTextureData = new PxVec3[64 * 64];
+
+ for(int i = 0; i < 64 * 64; i++)
+ {
+ RandomUnitVectorsTextureData[i].x = (float)rand() / (float)RAND_MAX * 2.0f - 1.0f;
+ RandomUnitVectorsTextureData[i].y = (float)rand() / (float)RAND_MAX * 2.0f - 1.0f;
+ RandomUnitVectorsTextureData[i].z = (float)rand() / (float)RAND_MAX * 2.0f - 1.0f;
+
+
+ RandomUnitVectorsTextureData[i].normalize();
+
+ RandomUnitVectorsTextureData[i] = RandomUnitVectorsTextureData[i] * 0.5f + PxVec3(0.5f,0.5f,0.5f);
+ }
+
+ glBindTexture(GL_TEXTURE_2D,unitVecTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,64,64,0,GL_RGB,GL_FLOAT,RandomUnitVectorsTextureData);
+
+ delete [] RandomUnitVectorsTextureData;
+
+
+ PxVec3 *samples = new PxVec3[NUMSAMPLES];
+
+ float alfa = physx::PxPi / SAMPLEDIV,beta = physx::PxPiDivTwo / (SAMPLEDIV * 2.0f),radius = 0.5f;
+
+ for(int i = 0; i < NUMSAMPLES; i++)
+ {
+ samples[i] = PxVec3(cos(alfa),sin(alfa),sin(beta));
+ samples[i].normalize();
+ samples[i] *= ((float)NUMSAMPLES - i) / ((float)NUMSAMPLES);
+ samples[i] *= radius;
+
+ alfa += physx::PxPi / (SAMPLEDIV / 2);
+
+ if(((i + 1) % SAMPLEDIV) == 0)
+ {
+ alfa += physx::PxPi / SAMPLEDIV;
+ beta += physx::PxPiDivTwo / SAMPLEDIV;
+ }
+ }
+
+ glUseProgram(SSAO);
+ glUniform3fv(glGetUniformLocation(SSAO,"samples"),NUMSAMPLES,(GLfloat*)samples);
+ glUseProgram(0);
+
+ delete [] samples;
+
+ glGenTextures(1,&normalTex);
+ glGenTextures(1,&depthTex);
+ glGenTextures(1,&ssaoTex);
+ glGenTextures(1,&blurTex);
+
+ glGenFramebuffers(1,&FBO);
+}
+
+PxMat44 PerspectiveProjectionMatrix(float fovy,float x,float y,float n,float f)
+{
+ float PPM[16];
+
+ float coty = 1.0f / tan(fovy * physx::PxPi / 360.0f);
+ float aspect = x / (y > 0.0f ? y : 1.0f);
+
+ PPM[0] = coty / aspect;
+ PPM[1] = 0.0f;
+ PPM[2] = 0.0f;
+ PPM[3] = 0.0f;
+
+ PPM[4] = 0.0f;
+ PPM[5] = coty;
+ PPM[6] = 0.0f;
+ PPM[7] = 0.0f;
+
+ PPM[8] = 0.0f;
+ PPM[9] = 0.0f;
+ PPM[10] = (n + f) / (n - f);
+ PPM[11] = -1.0f;
+
+ PPM[12] = 0.0f;
+ PPM[13] = 0.0f;
+ PPM[14] = 2.0f * n * f / (n - f);
+ PPM[15] = 0.0f;
+
+ return PxMat44(PPM);
+}
+
+PxMat44 PerspectiveProjectionMatrixInverse(PxMat44 &PPM)
+{
+ float PPMI[16];
+
+ PPMI[0] = 1.0f / PPM.column0.x;
+ PPMI[1] = 0.0f;
+ PPMI[2] = 0.0f;
+ PPMI[3] = 0.0f;
+
+ PPMI[4] = 0.0f;
+ PPMI[5] = 1.0f / PPM.column1.y;
+ PPMI[6] = 0.0f;
+ PPMI[7] = 0.0f;
+
+ PPMI[8] = 0.0f;
+ PPMI[9] = 0.0f;
+ PPMI[10] = 0.0f;
+ PPMI[11] = 1.0f / PPM.column3.z;
+
+ PPMI[12] = 0.0f;
+ PPMI[13] = 0.0f;
+ PPMI[14] = 1.0f / PPM.column2.w;
+ PPMI[15] = - PPM.column2.z / (PPM.column2.w * PPM.column3.z);
+
+ return PxMat44(PPMI);
+}
+PxMat44 BiasMatrix()
+{
+ float BM[16];
+
+ BM[0] = 0.5f; BM[4] = 0.0f; BM[8] = 0.0f; BM[12] = 0.5f;
+ BM[1] = 0.0f; BM[5] = 0.5f; BM[9] = 0.0f; BM[13] = 0.5f;
+ BM[2] = 0.0f; BM[6] = 0.0f; BM[10] = 0.5f; BM[14] = 0.5f;
+ BM[3] = 0.0f; BM[7] = 0.0f; BM[11] = 0.0f; BM[15] = 1.0f;
+
+ return PxMat44(BM);
+}
+
+PxMat44 BiasMatrixInverse()
+{
+ float BMI[16];
+
+ BMI[0] = 2.0f; BMI[4] = 0.0f; BMI[8] = 0.0f; BMI[12] = -1.0f;
+ BMI[1] = 0.0f; BMI[5] = 2.0f; BMI[9] = 0.0f; BMI[13] = -1.0f;
+ BMI[2] = 0.0f; BMI[6] = 0.0f; BMI[10] = 2.0f; BMI[14] = -1.0f;
+ BMI[3] = 0.0f; BMI[7] = 0.0f; BMI[11] = 0.0f; BMI[15] = 1.0f;
+
+ return PxMat44(BMI);
+}
+void SSAOHelper::Resize(int w,int h) {
+ realWidth = w;
+ realHeight = h;
+ Width = w*scale;
+ Height = h*scale;
+
+ fovPad = 2.0f*atan(tan(fov*0.5f*physx::PxPi/180.0f)*(1.0f+padding))*180.0f/physx::PxPi;
+
+ SWidth = Width*(1.0f+padding);
+ SHeight = Height*(1.0f+padding);
+
+ glViewport(0,0,SWidth,SHeight);
+
+ PxMat44 mat();
+ PxMat44 Projection = PerspectiveProjectionMatrix(fovPad,SWidth,SHeight,zNear,zFar);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+ glBindTexture(GL_TEXTURE_2D,normalTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,SWidth,SHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,depthTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT32,SWidth,SHeight,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,ssaoTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,SWidth,SHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+
+ glBindTexture(GL_TEXTURE_2D,blurTex);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,SWidth,SHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
+
+ PxMat44 biasProjMat = BiasMatrix() * Projection;
+ PxMat44 biasProjMatInv = PerspectiveProjectionMatrixInverse(Projection) * BiasMatrixInverse();
+
+ glUseProgram(SSAO);
+ glUniformMatrix4fv(glGetUniformLocation(SSAO,"biasProjMat"),1,GL_FALSE,&biasProjMat.column0.x);
+ glUniformMatrix4fv(glGetUniformLocation(SSAO,"biasProjMatInv"),1,GL_FALSE,&biasProjMatInv.column0.x);
+ glUniform2f(glGetUniformLocation(SSAO,"scaleXY"),(float)SWidth / 64.0f,(float)SHeight / 64.0f);
+
+ glUseProgram(SSAOFilterH);
+ glUniform1f(glGetUniformLocation(SSAOFilterH,"sx"),1.0f / (float)SWidth);
+
+ glUseProgram(SSAOFilterV);
+ glUniform1f(glGetUniformLocation(SSAOFilterV,"sy"),1.0f / (float)SHeight);
+
+ glUseProgram(0);
+
+}
+void SSAOHelper::Destroy() {
+
+ SSAO.deleteShaders();
+ SSAOFilterH.deleteShaders();
+ SSAOFilterV.deleteShaders();
+
+ glDeleteTextures(1,&unitVecTex);
+ glDeleteTextures(1,&normalTex);
+ glDeleteTextures(1,&depthTex);
+ glDeleteTextures(1,&ssaoTex);
+ glDeleteTextures(1,&blurTex);
+ glDeleteFramebuffers(1,&FBO);
+}
+
+void SSAOHelper::DoSSAO(void (*renderScene)(), GLuint oldFBO) {
+ glBindFramebuffer(GL_FRAMEBUFFER,FBO);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,normalTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,depthTex,0);
+
+ glViewport(0,0,SWidth,SHeight);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+ PxMat44 Projection = PerspectiveProjectionMatrix(fovPad,SWidth,SHeight,zNear,zFar);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ renderScene();
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+// if(Blur)
+// {
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,ssaoTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,0,0);
+
+ glClearColor(0.0f,0.0f,0.0f,1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+// }
+// else
+// {
+// glBindFramebuffer(GL_FRAMEBUFFER,0);
+// }
+
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,depthTex);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,normalTex);
+ glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,unitVecTex);
+
+ glUseProgram(SSAO);
+
+ glBegin(GL_QUADS);
+ glVertex2f(0.0f,0.0f);
+ glVertex2f(1.0f,0.0f);
+ glVertex2f(1.0f,1.0f);
+ glVertex2f(0.0f,1.0f);
+ glEnd();
+
+ glUseProgram(0);
+
+ glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D,0);
+ glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,0);
+ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,0);
+
+// if(Blur)
+ {
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,blurTex,0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,0,0);
+
+ glBindTexture(GL_TEXTURE_2D,ssaoTex);
+
+ glUseProgram(SSAOFilterH);
+ glUniform1f(glGetUniformLocation(SSAOFilterH, "sx"), 1.0f / (float)SWidth);
+
+
+
+ glBegin(GL_QUADS);
+/*
+ glTexCoord2f(0.0f+fx,0.0f+fy); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f-fx,0.0f+fy); glVertex2f(1.0f,0.0f);
+ glTexCoord2f(1.0f-fx,1.0f-fy); glVertex2f(1.0f,1.0f);
+ glTexCoord2f(0.0f+fx,1.0f-fy); glVertex2f(0.0f,1.0f);
+*/
+ glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f,0.0f); glVertex2f(1.0f,0.0f);
+ glTexCoord2f(1.0f,1.0f); glVertex2f(1.0f,1.0f);
+ glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,1.0f);
+ glEnd();
+
+ glUseProgram(0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER,oldFBO);
+ //glClearColor(0.0f,0.0f,0.0f,1.0f);
+ //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glDisable(GL_DEPTH_TEST);
+ glDepthMask(GL_FALSE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
+
+ glViewport(0,0,realWidth,realHeight);
+
+ Projection = PerspectiveProjectionMatrix(fov,Width,Height,zNear,zFar);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(&Projection.column0.x);
+
+
+ glBindTexture(GL_TEXTURE_2D,blurTex);
+
+ glUseProgram(SSAOFilterV);
+ glUniform1f(glGetUniformLocation(SSAOFilterV, "sy"), 1.0f / (float)SHeight);
+
+ //float fx = 0.5f*(1.0f-(((float)(SWidth-Width))/((float)Width)));
+ //float fy = 0.5f*(1.0f-(((float)(SHeight-Height))/((float)Height)));
+ float fx = 0.5f*((float)(SWidth-Width)) / ((float)SWidth);
+ float fy = 0.5f*((float)(SHeight-Height)) / ((float)SHeight);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f+fx,0.0f+fy); glVertex2f(0.0f,0.0f);
+ glTexCoord2f(1.0f-fx,0.0f+fy); glVertex2f(1.0f,0.0f);
+ glTexCoord2f(1.0f-fx,1.0f-fy); glVertex2f(1.0f,1.0f);
+ glTexCoord2f(0.0f+fx,1.0f-fy); glVertex2f(0.0f,1.0f);
+ glEnd();
+
+ glUseProgram(0);
+
+ glBindTexture(GL_TEXTURE_2D,0);
+ glDisable(GL_BLEND);
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ }
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SSAOHelper.h b/KaplaDemo/samples/sampleViewer3/SSAOHelper.h
new file mode 100644
index 00000000..7fd63849
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SSAOHelper.h
@@ -0,0 +1,25 @@
+#pragma once
+#include <GL/glew.h>
+#include "Shader.h"
+#define SAMPLEDIV 4
+#define NUMSAMPLES SAMPLEDIV*SAMPLEDIV
+
+class SSAOHelper{
+public:
+ int Width, Height;
+ float padding;
+ int SWidth, SHeight;
+ float fov;
+ float fovPad;
+ float zNear, zFar;
+ float scale;
+ int realWidth, realHeight;
+
+ Shader SSAO, SSAOFilterH, SSAOFilterV;
+ SSAOHelper(float fov, float padding, float zNear, float zFar, const char* resourcePath, float scale);
+ void Resize(int w, int h);
+
+ void DoSSAO(void (*renderScene)(), GLuint oldFBO = 0);
+ void Destroy();
+ GLuint FBO, unitVecTex, normalTex, depthTex, ssaoTex, blurTex;
+};
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp b/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp
new file mode 100644
index 00000000..96b395af
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewer.cpp
@@ -0,0 +1,2527 @@
+// ===============================================================================
+// Title: Sample Viewer
+// Description: A Viewer for GRB Demo Scenes
+//
+// Written by: Matthias M�ller (23.11.11)
+// ===============================================================================
+
+#ifndef _SCL_SECURE_NO_WARNINGS
+#define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#ifdef WIN32
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+#endif
+
+
+#undef random
+
+#include <stdio.h>
+#include <assert.h>
+
+#include "ShaderShadow.h"
+#include "ShadowMap.h"
+#include "RenderTarget.h"
+
+#include <GL/glut.h>
+
+#include "SampleViewer.h"
+#include "MediaPath.h"
+
+#include <task/PxTask.h>
+#include "cudamanager/PxCudaContextManager.h"
+
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxDefaultAllocator.h"
+#include "PxDefaultErrorCallback.h"
+#include "PxDefaultCpuDispatcher.h"
+#include "PxExtensionsAPI.h"
+#include "PxPhysicsVersion.h"
+
+#include "PxScene.h"
+#include "PxGpu.h"
+
+#include "foundation/PxFoundationVersion.h"
+#include "foundation/PxProfiler.h"
+#include "pvd/PxPvd.h"
+
+//namespace PVD {
+// using namespace physx::debugger;
+// using namespace physx::debugger::comm;
+//}
+#include "Timing.h"
+#include "GLFontRenderer.h"
+#include "BmpFile.h"
+
+#include "SceneKaplaTower.h"
+#include "SceneKaplaArena.h"
+#include "SceneRagdollWashingMachine.h"
+#include "SceneVehicle.h"
+#include "SceneCrab.h"
+
+#include <string>
+#include <algorithm>
+//#include "fomHelper.h"
+#include <string>
+#include "MyShaders.h"
+#include "SimScene.h"
+#include "Texture.h"
+#include "AABox.h"
+#include "SSAOHelper.h"
+#include "HBAOHelper.h"
+#include "FXAAHelper.h"
+#include "IJGWin32/CPPJPEGWrapper.h"
+#include "HDRHelper.h"
+#include "SampleViewerGamepad.h"
+
+#include "PhysXMacros.h"
+
+#include "pvd/PxPvdTransport.h"
+#include "foundation/PxMat44.h"
+
+#define SCREEN_DUMP_PATH "C:\\Capture\\%05i.bmp"
+
+int DEFAULT_SOLVER_ITERATIONS = 8;
+
+
+#define WINDOW_WIDTH 1280
+#define WINDOW_HEIGHT 720
+
+#define ENABLE_PVD 1
+#define FULL_PVD 0
+
+// Globals -------------------------------------------------------------------------------------------
+
+int gPhysicsFrameNumber = 0; // different from gFrameNr since the latter is for graphics
+// ---------------------------------------------------------------------------------------------------
+float g_fogStart = 150.0f;
+float g_fogEnd = 350.0f;
+float shadowClipNear = 0.01f;
+float shadowClipFar = 80.0f;
+
+int gNrWorkerThreads = 4;
+
+
+extern float g_shadowAdd;
+const float zNear = 0.1f;
+const float zFar = 1000.0f;
+
+SSAOHelper* gSSAOHelper = NULL;
+HBAOHelper* gHBAOHelper = NULL;
+FXAAHelper* gFXAAHelper = NULL;
+HDRHelper* gHDRHelper = NULL;
+GLenum shadowMapType = GL_TEXTURE_2D_ARRAY_EXT;
+// PhysX
+PxPhysics* gPxPhysics = NULL;
+PxFoundation* gPxFoundation = NULL;
+PxCooking* gPxCooking = NULL;
+PxDefaultAllocator gAllocator;
+
+PxScene* gPxScene = NULL;
+PxDefaultCpuDispatcher* gPxDispatcher = NULL;
+
+PxCudaContextManager* gCudaContextManager;
+
+bool gUseGrb = true;
+bool gCurrentUsingGrb = gUseGrb;
+
+bool gForceSceneRecreate = false;
+int gCountdownToRecereate = 2;
+
+bool gShot = false;
+
+PxU32 gMaxSubSteps = 1u;
+
+// Physics param
+PxVec3 gDefaultGravity(0.0f ,-10.0f, 0.0f);
+float gTimeStepSize = 1.0f / 60.0f;
+float gSlowMotionFactor = 1.0f;
+
+// Scene
+bool gSceneRunning = false;
+float gTime = 0.0f;
+float gLastTime = 0.0f;
+bool gPause = false;
+bool gDisableRendering = false;
+bool gShowSplash = false;
+
+#ifdef USE_OPTIX
+int gNumScenes = 9;
+#else
+int gNumScenes = 5;
+#endif
+int gSceneNr = 0;
+
+float gGroundY = 0.0f;
+GLuint gGroundTexId = 0;
+
+GLuint gSplashScreenTexId = 0;
+int gSplashWidth = 0;
+int gSplashHeight = 0;
+char gResourcePath[512] = "../../../externalIP/resources";
+
+SampleViewerScene *gSampleScene = NULL;
+
+// Display
+GLFontRenderer *gFontRenderer = NULL;
+
+int gMainHandle;
+bool gHelp = false;
+bool gDisplay = true;
+char gDisplayString[512] = "";
+char gHelpString[2048] = "";
+char gDemoName[512] = "";
+float gFontSize = 0.02f;
+
+int gViewWidth = 0;
+int gViewHeight = 0;
+bool gShadows = false;
+bool gWireframeMode = false;
+bool gAdvancedRendering = true;
+bool gDebugRendering = true;
+bool gDrawGroundPlane = true;
+PxVec3 gGroupPlanePose = PxVec3(0.f);
+bool gDrawSkyBox = true;
+
+//bool gFXAAOn = true;
+//bool gDoSSAO = true;
+//bool gDoHDR = true;
+
+bool gFXAAOn = false;
+bool gDoSSAO = true;
+bool gDoHBAO = true;
+bool gDoHDR = true;
+bool gUseNormalMap = true;
+
+bool gDoDOF = false;
+
+// record movie
+int gPixelBufferSize = 0;
+GLbyte *gPixelBuffer = NULL;
+bool gRecordBMP = false;
+int gFrameNr = 0;
+int gMaxFrameNr = 0;
+
+// Shading
+int gNumShadows = 1;
+bool gShowReflections = false;
+
+static const int gNumLights = 1;
+PxVec3 gLightDirs[3];
+PxVec3 gLightPos[3];
+PxVec3 gBackLightDir;
+
+ShadowMap *gShadowMaps[4];
+ShaderShadow *gDefaultShader;
+RenderTarget *gReflectedSceneTarget = NULL;
+
+int gZval = 15;
+//FOMHelper* fom;
+Shader* gDisplayTexProg;
+Shader* gDisplayTexArrayProg;
+Shader* gDisplaySplashProg = 0;
+PxBounds3 sceneBounds;
+PxBounds3 fluidBounds;
+PxVec3 myDustColor;
+
+bool renderDust = true;
+
+#define MSAA_2x 2, 0, "MSAA_2x"
+#define CSAA_4x 2, 4, "CSAA_4x"
+#define CSAA_8x 4, 8, "CSAA_8x"
+#define CSAA_8xQ 8, 8, "CSAA_8xQ"
+#define CSAA_16x 4, 16, "CSAA_16x"
+#define CSAA_16xQ 8, 16, "CSAA_16xQ"
+
+AABox* g_pAABox = 0;
+int g_numAAModes = 5;
+//int fullW = 1900;
+//int fullH = 1200;
+
+int fullW = WINDOW_WIDTH;
+int fullH = WINDOW_HEIGHT;
+bool autoShoot = false;
+bool gForceReloadShader = false;
+bool gForceReloadDebugShader = false;
+
+using namespace std;
+
+struct SAAMode
+{
+ int ds;
+ int cs;
+ const char * name;
+};
+
+SAAMode g_aaModes[] = {
+ {MSAA_2x},
+ {CSAA_8x},
+ {CSAA_8xQ},
+ {CSAA_16x},
+ {CSAA_16xQ},
+ { CSAA_4x }
+};
+
+bool doFXAA = false;
+bool doAA = true;
+int g_curAA = 0;
+int g_curTech = 1;
+float g_curSSSize = 1.7f;
+
+bool gShowRayCast = false;
+bool fullScreen = false;
+
+// Camera
+struct Camera {
+ void init() {
+ fov = 40.0f;
+ pos = PxVec3(0.0f, 30.0f, 20.0f);
+ forward = PxVec3(0.0f,0.0f,-1.0f);
+ right = PxVec3(1.0f,0.0f,0.0f);
+
+ PxVec3 up(0, 1, 0);
+
+ PxQuat qy(3.14/4.f, right);
+ forward = qy.rotate(forward).getNormalized();
+ right = forward.cross(PxVec3(0, 1, 0)).getNormalized();
+
+
+ speed = 0.15f;
+ rotate = false;
+ translate = false;
+ zoom = false;
+
+ trackballMode = false;
+ trackballCenter = PxVec3(0.0f, 1.0f, 0.0f);
+ trackballRadius = 6.0f;
+ }
+ float fov;
+ PxVec3 pos, forward, right;
+ float speed;
+ bool rotate, translate, zoom;
+ bool trackballMode;
+ PxVec3 trackballCenter;
+ float trackballRadius;
+};
+
+Camera gCamera;
+
+// Mouse
+int gMouseX = 0;
+int gMouseY = 0;
+
+// keyboard
+#define MAX_KEYS 256
+bool gKeys[MAX_KEYS];
+
+// fps
+float curFPS = 0.0f;
+int gFrameCounter = 0;
+float gPreviousTime = getCurrentTime();
+
+volatile bool doneOneFrame = false;
+volatile bool doneInit = false;
+volatile bool doneRender = true;
+volatile bool shouldEndThread = false;
+volatile bool threadEnded = false;
+volatile int simulateDoneS = 0;
+bool renderEveryFrame = true;
+
+bool gParticlesTexOutdate = true;
+bool gConvexTexOutdate = true;
+
+
+//std::vector<Compound*> delCompoundList;
+
+SampleViewerGamepad sampleViewerGamepad;
+
+// ------------------------------------------------------------------------------------
+// This is needed to properly call cleanup routines when GLUT window is closed, as
+// there is no close callback routine, and the default way simply calls exit(0) thus
+// calling destructors w/o cleanups, leading to crash
+// (see atexit function that sets exit callback)
+// ------------------------------------------------------------------------------------
+bool gIsSampleCleanedUp = false;
+void ReleaseSDKs();
+void CleanupSample();
+// ------------------------------------------------------------------------------------
+
+physx::PxPvd* gPvd = NULL;
+physx::PxPvdTransport* gTransport = NULL;
+physx::PxPvdInstrumentationFlags gPvdFlags = physx::PxPvdInstrumentationFlag::eDEBUG;
+
+#include "PsString.h"
+#include "PsThread.h"
+
+//class SampleViewerPVDHandler : public PxPvd
+//{
+//public:
+//
+// void onPvdSendClassDescriptions(PVD::PvdConnection&) {}
+//
+// void onPvdConnected(PVD::PvdConnection& )
+// {
+// //setup joint visualization. This gets piped to pvd.
+// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_CONSTRAINTS, true);
+// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_CONTACTS, true);
+// //gPxPhysics->getVisualDebugger()->setVisualDebuggerFlag(PxVisualDebuggerFlag::eTRANSMIT_SCENEQUERIES, true);
+// }
+//
+// void onPvdDisconnected(PVD::PvdConnection& conn)
+// {
+// conn.release();
+// }
+//};
+//
+//SampleViewerPVDHandler gPVDConnectionHandler;
+
+class SampleViewerErrorCallback : public PxErrorCallback
+{
+public:
+ SampleViewerErrorCallback() {}
+ ~SampleViewerErrorCallback() {}
+
+ virtual void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line)
+ {
+ if (code == PxErrorCode::eDEBUG_INFO)
+ {
+ char buffer[1024];
+ sprintf(buffer, "%s\n", message);
+ physx::shdfnd::printString(buffer);
+ }
+ else
+ {
+ const char* errorCode = NULL;
+
+ switch (code)
+ {
+ case PxErrorCode::eINVALID_PARAMETER:
+ errorCode = "invalid parameter";
+ break;
+ case PxErrorCode::eINVALID_OPERATION:
+ errorCode = "invalid operation";
+ break;
+ case PxErrorCode::eOUT_OF_MEMORY:
+ errorCode = "out of memory";
+ break;
+ case PxErrorCode::eDEBUG_INFO:
+ errorCode = "info";
+ break;
+ case PxErrorCode::eDEBUG_WARNING:
+ errorCode = "warning";
+ break;
+ case PxErrorCode::ePERF_WARNING:
+ errorCode = "performance warning";
+ break;
+ case PxErrorCode::eABORT:
+ errorCode = "abort";
+ break;
+ default:
+ errorCode = "unknown error";
+ break;
+ }
+
+ PX_ASSERT(errorCode);
+ if (errorCode)
+ {
+ char buffer[1024];
+ sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message);
+
+ physx::shdfnd::printString(buffer);
+
+ // in debug builds halt execution for abort codes
+ PX_ASSERT(code != PxErrorCode::eABORT);
+
+ // in release builds we also want to halt execution
+ // and make sure that the error message is flushed
+ while (code == PxErrorCode::eABORT)
+ {
+ physx::shdfnd::printString(buffer);
+ physx::shdfnd::Thread::sleep(1000);
+ }
+ }
+ }
+ }
+};
+
+SampleViewerErrorCallback gErrorCallback;
+// ------------------------------------------------------------------------------------
+#include <direct.h>
+
+// ------------------------------------------------------------------------------------
+bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL)
+{
+ char path[512];
+ sprintf(path, "%s/%s", gResourcePath, filename);
+
+ // read out image data
+ int len = strlen(path);
+ unsigned char* ptr = 0, *ptrBegin;
+ int w, h;
+ BmpLoaderBuffer loader;
+ CPPJPEGWrapper jpg;
+ if (strcmp(&path[len-4], ".jpg") == 0) {
+ // jpg
+
+ if (!jpg.LoadJPEG(path, false)) {
+ printf("Error load jpg %s\n", path);
+ return false;
+ }
+ h = jpg.GetHeight();
+ w = jpg.GetWidth();
+ ptrBegin = ptr = jpg.GetData();
+ } else {
+ // bmp
+
+ if (!loader.loadFile(path)) {
+ fprintf(stderr, "Error loading bmp '%s'\n",path);
+ return false;
+ }
+ ptrBegin = ptr = loader.mRGB;
+ h = loader.mHeight;
+ w = loader.mWidth;
+
+ }
+
+ unsigned char *pColor = ptrBegin;
+
+ int lineLen = 3*w;
+ GLubyte *buffer = new GLubyte[w*h*3];
+ GLubyte *writePtr = &buffer[(h-1)*lineLen];
+
+ for (int i = 0; i < h; i++) {
+ GLubyte *writePtr = &buffer[i*lineLen];
+ GLubyte *readPtr = &pColor[i*lineLen];
+ for (int j = 0; j < w; j++) {
+ *writePtr++ = *readPtr++;
+ *writePtr++ = *readPtr++;
+ *writePtr++ = *readPtr++;
+ }
+ }
+
+ // ------ generate texture --------------------------------
+
+ glGenTextures(1, &texId);
+
+ glBindTexture(type, texId);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexParameteri(type, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(type, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(type, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+ if (createMipmaps) {
+ glTexParameteri(type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ gluBuild2DMipmaps(type, GL_RGB, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer);
+ }
+
+ delete[] buffer;
+
+ if (width)
+ *width = w;
+ if (height)
+ *height = h;
+ return true;
+}
+
+void displayTexture(GLuint tex)
+{
+ gDisplayTexProg->activate();
+ gDisplayTexProg->bindTexture("tex", tex, GL_TEXTURE_2D, 0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f, 1.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
+ glEnd();
+ gDisplayTexProg->deactivate();
+}
+void displayTextureArray(GLuint tex, int slice)
+{
+ gDisplayTexArrayProg->activate();
+ gDisplayTexArrayProg->bindTexture("tex", tex, GL_TEXTURE_2D_ARRAY_EXT, 0);
+ gDisplayTexArrayProg->setUniform1("slice", slice);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f);
+ glEnd();
+ gDisplayTexArrayProg->deactivate();
+}
+const char *textureRECTPS = STRINGIFY(
+uniform sampler2DRect tex;
+void main()
+{
+gl_FragColor = texture2DRect(tex, gl_TexCoord[0].xy); \n
+//gl_FragColor = vec4(1,0,0,1);
+}
+);
+const char *texture2DArrayPS = STRINGIFY(
+ uniform sampler2DArray tex;
+void main()
+{
+ gl_FragColor = texture2DArray(tex, vec3(gl_TexCoord[0].xy,0.0f)); \n
+ //gl_FragColor = vec4(1,0,0,1);
+}
+);
+
+void displaySplashScreen()
+{
+ float as = (float)gSplashWidth/gSplashHeight;
+
+ float xv = 0.0f, yv = 0.0f;
+ float bs = gViewWidth / ((float)gViewHeight);
+ if (bs > as) {
+ // Too wide
+ // fit height
+ yv = 1.0f;
+ xv = (as*gViewHeight) / gViewWidth;
+ } else {
+ // Too Tall
+ xv = 1.0f;
+ yv = (gViewWidth/as) / gViewHeight;
+ }
+
+
+ gDisplaySplashProg->activate();
+ gDisplaySplashProg->bindTexture("tex", gSplashScreenTexId, GL_TEXTURE_RECTANGLE_ARB, 0);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0f, gSplashHeight); glVertex2f(-xv, -yv);
+ glTexCoord2f(gSplashWidth, gSplashHeight); glVertex2f( xv, -yv);
+ glTexCoord2f(gSplashWidth, 0.0f); glVertex2f( xv, yv);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(-xv, yv);
+ glEnd();
+ gDisplaySplashProg->deactivate();
+
+}
+
+// ------------------------------------------------------------------------------------
+void SaveFrameBuffer()
+{
+ char filename[256];
+ sprintf(filename, SCREEN_DUMP_PATH, gFrameNr);
+
+ int bufferSize = gViewWidth * gViewHeight * 3;
+ if (gPixelBufferSize != bufferSize) {
+ if (gPixelBuffer != NULL)
+ free(gPixelBuffer);
+ gPixelBuffer = (GLbyte *)malloc(bufferSize);
+ gPixelBufferSize = bufferSize;
+ }
+
+ glReadBuffer(GL_BACK);
+ glReadPixels(0,0, gViewWidth, gViewHeight, GL_RGB, GL_UNSIGNED_BYTE, gPixelBuffer);
+ saveBmpRBG(filename, gViewWidth, gViewHeight, gPixelBuffer);
+}
+
+// ------------------------------------------------------------------------------------
+void WaitForSim()
+{
+ if (gSceneRunning)
+ {
+ if (gSampleScene != NULL)
+ {
+ gSampleScene->syncAsynchronousWork();
+ }
+
+ PxU32 error;
+ gPxScene->fetchResults(true, &error);
+
+ assert(error == 0);
+ gSceneRunning = false;
+ }
+}
+
+// ------------------------------------------------------------------------------------
+PxFilterFlags contactReportFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
+ PxFilterObjectAttributes attributes1, PxFilterData filterData1,
+ PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
+{
+ PX_UNUSED((attributes0, attributes1, filterData0, filterData1, constantBlockSize, constantBlock));
+
+ // all initial and persisting reports for everything, with per-point data
+ pairFlags = PxPairFlag::eSOLVE_CONTACT | PxPairFlag::eDETECT_DISCRETE_CONTACT;
+ return PxFilterFlag::eDEFAULT;
+}
+
+// ------------------------------------------------------------------------------------
+
+
+void CreateSampleViewerScene();
+void InitSampleViewerScene();
+
+void RecreateSDKScenes()
+{
+ WaitForSim();
+
+ // physX
+ if (gPxScene != NULL)
+ gPxScene->release();
+
+ PxSceneDesc sceneDesc(gPxPhysics->getTolerancesScale());
+
+ sceneDesc.gravity = PxVec3(0.0f, -10.0f * gSlowMotionFactor * gSlowMotionFactor, 0.0f); // acceleration, factor squared
+ if (!gPxDispatcher)
+ gPxDispatcher = PxDefaultCpuDispatcherCreate(gNrWorkerThreads);
+
+ if(!gCudaContextManager)
+ {
+ PxCudaContextManagerDesc cudaContextManagerDesc;
+ gCudaContextManager = PxCreateCudaContextManager(*gPxFoundation, cudaContextManagerDesc);
+ }
+
+
+
+ sceneDesc.cpuDispatcher = gPxDispatcher;
+ sceneDesc.gpuDispatcher = gCudaContextManager->getGpuDispatcher();
+ sceneDesc.filterShader = contactReportFilterShader;
+ sceneDesc.flags |= PxSceneFlag::eENABLE_PCM;
+ sceneDesc.flags |= PxSceneFlag::eENABLE_STABILIZATION;
+ if (gUseGrb)
+ {
+ sceneDesc.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
+ sceneDesc.broadPhaseType = PxBroadPhaseType::eGPU;
+ }
+ sceneDesc.flags |= PxSceneFlag::eSUPPRESS_EAGER_SCENE_QUERY_REFIT;
+ sceneDesc.gpuDynamicsConfig.contactStreamSize *= 2;
+ sceneDesc.gpuDynamicsConfig.forceStreamCapacity *= 2;
+ sceneDesc.gpuDynamicsConfig.patchStreamSize *= 2;
+ sceneDesc.gpuDynamicsConfig.tempBufferCapacity *= 2;
+
+ gSampleScene->customizeSceneDesc(sceneDesc);
+
+ gPxScene = gPxPhysics->createScene(sceneDesc);
+
+ PxPvdSceneClient* pvdClient = gPxScene->getScenePvdClient();
+ if (pvdClient)
+ {
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, false);
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, false);
+ pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, false);
+ }
+
+ if(gPxScene == NULL)
+ {
+ printf("\nError: Unable to create a PhysX scene, exiting the sample.\n\n");
+ exit(0);
+ }
+
+ gCurrentUsingGrb = gUseGrb;
+}
+
+//-----------------------------------------------------------------------------
+bool InitPhysX()
+{
+ // SDK
+ gPxFoundation = PxCreateFoundation(PX_FOUNDATION_VERSION, gAllocator, gErrorCallback);
+
+ gTransport = physx::PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10);
+
+ gPvd = NULL;
+
+#if ENABLE_PVD
+ gPvd = physx::PxCreatePvd(*gPxFoundation);
+ //gPvd->connect(*gTransport, physx::PxPvdInstrumentationFlag::eALL);
+ gPvd->connect(*gTransport, physx::PxPvdInstrumentationFlag::ePROFILE);
+#endif
+
+ gPxPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *gPxFoundation, PxTolerancesScale(), false, gPvd);
+
+
+
+ if(gPxPhysics == NULL)
+ {
+ printf("\nPhysXSDK create error.\nUnable to initialize the PhysX SDK, exiting the sample.\n\n");
+ return false;
+ }
+ PxCookingParams params(gPxPhysics->getTolerancesScale());
+ params.buildGPUData = true;
+ gPxCooking = PxCreateCooking(PX_PHYSICS_VERSION, *gPxFoundation, params);
+
+ if (gPxCooking == NULL)
+ {
+ printf("\nError: Unable to initialize the cooking library, exiting the sample.\n\n");
+ return false;
+ }
+
+ PxInitExtensions(*gPxPhysics, gPvd);
+
+ UpdateTime();
+
+ return true;
+}
+
+// ------------------------------------------------------------------------------------
+void ReleaseSDKs()
+{
+ WaitForSim();
+
+ if(gPxPhysics != NULL)
+ {
+ PxCloseExtensions();
+
+ gPxScene->release();
+ gPxDispatcher->release();
+ gPxPhysics->release();
+ gPxCooking->release();
+ if (gPvd)
+ {
+ gPvd->release();
+ gPvd = NULL;
+ }
+
+ gCudaContextManager->release();
+
+ gPxFoundation->release();
+ gPxScene = NULL;
+ gPxDispatcher = NULL;
+ gPxPhysics = NULL;
+ gPxCooking = NULL;
+ gPxFoundation = NULL;
+ gCudaContextManager = NULL;
+ }
+}
+
+// ------------------------------------------------------------------------------------
+PxReal UpdateTime()
+{
+ PxReal deltaTime;
+ gTime = timeGetTime()*0.001f; // Get current time in seconds
+ deltaTime = gTime - gLastTime;
+ gLastTime = gTime;
+
+ return deltaTime;
+}
+
+#define OVERLAP_SIM_AND_RENDER 1
+
+// ------------------------------------------------------------------------------------
+static bool g_simulationRunning = false;
+static PxReal g_simulationDT = 0.0f;
+void BeginSimulation(void)
+{
+ assert(g_simulationRunning == false);
+ assert(g_simulationDT == 0.0f);
+ if(g_simulationRunning == false)
+ {
+ static float prevTime = getCurrentTime();
+ float currTime = getCurrentTime();
+
+ float elapsedTime = currTime - prevTime;
+
+ PxReal fSubsteps = elapsedTime / gTimeStepSize;
+ PxU32 iSubsteps = PxU32(fSubsteps);
+ PxU32 nbSubsteps = PxMax(1u, PxMin(iSubsteps, gMaxSubSteps));
+
+ prevTime += PxReal(iSubsteps)*gTimeStepSize;
+
+ for (PxU32 a = 0; a < nbSubsteps; ++a)
+ {
+
+
+#if OVERLAP_SIM_AND_RENDER
+ if (gSceneRunning)
+ {
+ //fetchResult
+
+ WaitForSim();
+ if (gSampleScene != NULL)
+ {
+ gSampleScene->postSim(gTimeStepSize);
+ }
+ }
+#endif
+
+ if (gForceSceneRecreate)
+ {
+ if (--gCountdownToRecereate)
+ {
+ CreateSampleViewerScene();
+ RecreateSDKScenes();
+ InitSampleViewerScene();
+
+ gForceSceneRecreate = false;
+ }
+ }
+ else if (gUseGrb != gCurrentUsingGrb)
+ {
+ PxScene* oldScene = gPxScene;
+ gPxScene = NULL;
+
+ RecreateSDKScenes(); //Create the PxScene...
+
+ const PxU32 nbRigidStatics = oldScene->getNbActors(PxActorTypeFlag::eRIGID_STATIC);
+ const PxU32 nbRigidDynamics = oldScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
+
+ Ps::Array<PxActor*> actors(nbRigidStatics + nbRigidDynamics);
+
+ oldScene->getActors(PxActorTypeFlag::eRIGID_STATIC, actors.begin(), nbRigidStatics);
+ oldScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, actors.begin() + nbRigidStatics, nbRigidDynamics);
+
+
+ for (PxU32 a = 0; a < actors.size(); ++a)
+ {
+ oldScene->removeActor(*actors[a],false);
+ //gPxScene->addActor(*actors[a]);
+ }
+
+ for (PxU32 a = 0; a < actors.size(); ++a)
+ {
+ //oldScene->removeActor(*actors[a]);
+ gPxScene->addActor(*actors[a]);
+ }
+
+ oldScene->release();
+
+ gSampleScene->setScene(gPxScene);
+
+ gCurrentUsingGrb = gUseGrb;
+ }
+
+ {
+ if (gSampleScene != NULL)
+ gSampleScene->preSim(gTimeStepSize);
+
+ gPxScene->simulate(gTimeStepSize);
+
+ if (gSampleScene != NULL)
+ gSampleScene->duringSim(gTimeStepSize);
+
+ gSceneRunning = true;
+
+ g_simulationDT = gTimeStepSize;
+ g_simulationRunning = true;
+ }
+
+#if !OVERLAP_SIM_AND_RENDER
+ //if((a + 1) < nbSubsteps)
+ {
+ WaitForSim();
+ if (gSampleScene != NULL)
+ {
+ gSampleScene->postSim(gTimeStepSize);
+ }
+ }
+#endif
+ }
+
+
+ }
+}
+
+// ------------------------------------------------------------------------------------
+void EndSimulation(void)
+{
+ assert(g_simulationRunning == true);
+ assert(g_simulationDT != 0.0f);
+ if(g_simulationRunning == true)
+ {
+ PxReal dt = g_simulationDT;
+
+#if !OVERLAP_SIM_AND_RENDER
+ if (gSceneRunning)
+ {
+ //fetchResult
+ WaitForSim();
+ if (gSampleScene != NULL)
+ {
+ gSampleScene->postSim(gTimeStepSize);
+ }
+ }
+#endif
+
+ ++gPhysicsFrameNumber;
+
+ g_simulationDT = 0.0f;
+ g_simulationRunning = false;
+
+ gParticlesTexOutdate = true;
+ gConvexTexOutdate = true;
+ }
+}
+
+// ------------------------------------------------------------------------------------
+void RunPhysics()
+{
+ BeginSimulation();
+ EndSimulation();
+}
+
+// ------------------------------------------------------------------------------------
+
+void DisplayText()
+{
+ const char* aoString = gDoSSAO ? (gDoHBAO ? "(HBAO+)" : "(SSAO)"): "(NOAO)";
+ const char* normalString = gUseNormalMap ? "(NormalMap)" : "(NormalsFromDepth)";
+ sprintf(gDisplayString, "");
+ if (gDisplay)
+ sprintf(gDisplayString, "FPS = %0.2f\n Scene %i: %s %s%s %s %s", curFPS, gSceneNr + 1, gDemoName, gUseGrb ? "(GPU)" : "(CPU)", gHelp ? gHelpString : "", aoString, normalString);
+
+
+ float y = 0.95f;
+ int len = strlen(gDisplayString);
+ len = (len < 1024)?len:1023;
+ int start = 0;
+ char textBuffer[1024];
+ for(int i=0;i<len;i++)
+ {
+ if(gDisplayString[i] == '\n' || i == len-1)
+ {
+ int offset = i;
+ if(i == len-1) offset= i+1;
+ memcpy(textBuffer, gDisplayString+start, offset-start);
+ textBuffer[offset-start]=0;
+ gFontRenderer->print(0.01, y, gFontSize, textBuffer);
+ y -= 0.035f;
+ start = offset+1;
+ }
+ }
+}
+
+// ------------------------------------------------------------------------------------
+void SetHelpString()
+{
+ //char tempString[256];
+ sprintf(gHelpString, "\nGeneral:\n");
+ //sprintf(tempString, " 1-%d: choose scene\n", gNumScenes);
+
+ strcat(gHelpString, " F10: Reset scene\n");
+ strcat(gHelpString, " 1-5 or F10: Reset scene\n");
+ strcat(gHelpString, " F5: Toggle between CPU and GPU simulation\n");
+ strcat(gHelpString, " p: Pause\n");
+ strcat(gHelpString, " o: Single step\n");
+ if (gSceneNr == 2)
+ {
+ strcat(gHelpString, " F7: Detach/reattach camera\n");
+ strcat(gHelpString, " w,a,s,d,q,e: Drive car or move camera if camera is detached\n");
+ }
+
+ if (gSceneNr == 3)
+ {
+ strcat(gHelpString, " k: Spawn walker at mouse location\n");
+ }
+ strcat(gHelpString, " w,a,s,d,q,e: Camera\n");
+ strcat(gHelpString, " f: Toggle full screen mode\n");
+
+ strcat(gHelpString, " F1: Toggle help\n");
+
+ strcat(gHelpString, " F4: Change weapon: ");
+ if (gSampleScene != NULL)
+ strcat(gHelpString, gSampleScene->getWeaponName().c_str());
+ strcat(gHelpString, "\n");
+
+ strcat(gHelpString, " Shift-mouse: Drag objects\n");
+ strcat(gHelpString, " Space: Shoot\n");
+ if (gSceneNr == 0)
+ strcat(gHelpString, " b: Attack tower with random shapes\n");
+}
+
+// ------------------------------------------------------------------------------------
+void ProcessKeys()
+{
+ // Process keys
+ for (int i = 0; i < MAX_KEYS; i++)
+ {
+ if (!gKeys[i]) { continue; }
+
+ PxVec3 up;
+ up = PxVec3(0,1,0);
+ PxVec3 &pos = gCamera.trackballMode ? gCamera.trackballCenter : gCamera.pos;
+
+
+ if (!gSampleScene->isCameraDisable())
+ {
+ if (gCamera.trackballMode) {
+ switch (i)
+ {
+ // Camera controls
+ case 'W':
+ case 'w':{
+ gCamera.trackballRadius -= gCamera.speed;
+ if (gCamera.trackballRadius < 0.1f) gCamera.trackballRadius = 0.1f;
+ break;
+ }
+ case 'S':
+ case 's':{ gCamera.trackballRadius += gCamera.speed; break; }
+ case 'E':
+ case 'e':{ pos -= up * gCamera.speed; break; }
+ case 'Q':
+ case 'q':{ pos += up * gCamera.speed; break; }
+ }
+ }
+ else {
+ switch (i)
+ {
+ // Camera controls
+ case 'W':
+ case 'w':{ pos += gCamera.forward * gCamera.speed; break; }
+ case 'S':
+ case 's':{ pos -= gCamera.forward * gCamera.speed; break; }
+ case 'A':
+ case 'a':{ pos -= gCamera.right * gCamera.speed; break; }
+ case 'D':
+ case 'd':{ pos += gCamera.right * gCamera.speed; break; }
+ case 'E':
+ case 'e':{ pos -= up * gCamera.speed; break; }
+ case 'Q':
+ case 'q':{ pos += up * gCamera.speed; break; }
+ }
+ }
+ }
+
+ }
+}
+float XXX = 0.0f;
+ float modelMatrix[16];
+ float projMatrix[16];
+// ------------------------------------------------------------------------------------
+
+void SetupCamera(bool mirrored = false)
+{
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ float aspectRatio = ((float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT));
+ gluPerspective(gCamera.fov, aspectRatio, zNear, zFar);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (gCamera.trackballMode) {
+ gCamera.trackballCenter.x = 0.0f;
+ gCamera.trackballCenter.z = 0.0f;
+ gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius;
+ }
+
+
+ gSampleScene->getCamera(gCamera.pos, gCamera.forward);
+
+ PxVec3 pos = gCamera.pos;
+ PxVec3 dir = gCamera.forward;
+ PxVec3 apos = gCamera.pos + dir;
+
+
+ gluLookAt(pos.x, pos.y, pos.z, pos.x + dir.x, pos.y + dir.y, pos.z + dir.z, 0.0f, 1.0f, 0.0f);
+
+ if (mirrored) {
+ PxTransform trans;
+
+ PxVec3 waterN(0.0f, 1.0f, 0.0f);
+ PxVec3 waterP(0.0f,gGroundY,0.0f);
+ float QQQ = 0.00f;
+ waterP.y += QQQ;
+ float np2 = 2.0f*waterN.dot(waterP);
+
+ PxVec3 r0 = PxVec3(1.0f, 0.0f, 0.0f) - 2*waterN.x*waterN;
+ PxVec3 r1 = PxVec3(0.0f, 1.0f, 0.0f) - 2*waterN.y*waterN;
+ PxVec3 r2 = PxVec3(0.0f, 0.0f, 1.0f) - 2*waterN.z*waterN;
+ PxVec3 t = np2*waterN;
+
+ float matGL[16] = {
+ r0.x, r1.x, r2.x, 0.0f,
+ r0.y, r1.y, r2.y, 0.0f,
+ r0.z, r1.z, r2.z, 0.0f,
+ t.x, t.y, t.z, 1.0f};
+
+ glMultMatrixf(matGL);
+
+ }
+
+
+ glGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix);
+ glGetFloatv(GL_PROJECTION_MATRIX, projMatrix);
+
+ gDefaultShader->updateCamera(modelMatrix, projMatrix);
+ if (gSampleScene != NULL) {
+ for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++)
+ gSampleScene->getShaders()[i]->updateCamera(modelMatrix, projMatrix);
+ gSampleScene->setCamera(gCamera.pos, gCamera.forward, PxVec3(0,1,0), gCamera.fov);
+ }
+
+ gCamera.right = gCamera.forward.cross(PxVec3(0,1,0)).getNormalized();
+ gCamera.forward.normalize();
+
+}
+
+// ------------------------------------------------------------------------------------
+void RenderObjects(bool useShader, bool reflectedOnly)
+{
+ ShaderMaterial mat;
+ mat.init();
+
+ // ground plane
+ if (!reflectedOnly && gDrawGroundPlane)
+ {
+ if (useShader) {
+ mat.init();
+ mat.reflectionCoeff = 0.2f;
+ if (gGroundTexId > 0) {
+ mat.texId = gGroundTexId;
+ }
+ }
+ if (useShader)
+ gDefaultShader->activate(mat);
+
+ const float size = 1000.0f;
+ const float y = -0.002f;
+
+
+ PxVec3 center = gGroupPlanePose;
+ PxVec3 p0 = center + PxVec3(-size, y, -size);
+ PxVec3 p1 = center + PxVec3( size, y, -size);
+ PxVec3 p2 = center + PxVec3( size, y, size);
+ PxVec3 p3 = center + PxVec3(-size, y, size);
+
+ float texScale = 300.0f;
+ PxVec3 t0(0.0f, 0.0f, 0.0f);
+ PxVec3 t1(texScale, 0.0f, 0.0f);
+ PxVec3 t2(texScale, texScale, 0.0f);
+ PxVec3 t3(0.0f, texScale, 0.0f);
+
+ glBegin(GL_TRIANGLES);
+ glNormal3f(0.0f, 1.0f, 0.0f);
+ glTexCoord2f(t0.x, t0.y); glVertex3f(p0.x, p0.y, p0.z);
+ glTexCoord2f(t2.x, t2.y); glVertex3f(p2.x, p2.y, p2.z);
+ glTexCoord2f(t1.x, t1.y); glVertex3f(p1.x, p1.y, p1.z);
+
+ glTexCoord2f(t0.x, t0.y); glVertex3f(p0.x, p0.y, p0.z);
+ glTexCoord2f(t3.x, t3.y); glVertex3f(p3.x, p3.y, p3.z);
+ glTexCoord2f(t2.x, t2.y); glVertex3f(p2.x, p2.y, p2.z);
+ glEnd();
+ if (useShader)
+ gDefaultShader->deactivate();
+ }
+
+ if (gSampleScene != NULL)
+ gSampleScene->render(useShader);
+
+/*
+ glDisable(GL_LIGHTING);
+
+
+ glBindBuffer(GL_ARRAY_BUFFER, gFluidSim.mistPS->glVB[currentBufMultiGPU]);
+ glVertexPointer(3, GL_FLOAT, sizeof(CUGLParticleInfo), (void*)0);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glColor3f(1.0f,1.0f,1.0f);
+ glDrawArrays(GL_POINTS, 0, gFluidSim.mistPS->numGLPars[currentBufMultiGPU]);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ */
+
+//glDisable(GL_LIGHTING);
+
+ if (gShowRayCast) {
+
+ glDisable(GL_LIGHTING);
+ SimScene* simScene = ((SceneKapla*)gSampleScene)->getSimScene();
+ PxScene* scene = simScene->getScene();
+
+ PxVec3 start(-30.0f,0.0f,-30.0f);
+ PxVec3 xdir(1.0f,0.0f,0.0f);
+ PxVec3 zdir(0.0f,0.0f,1.0f);
+ PxVec3 castDir(0.0f, -1.0f, 0.0f);
+ PxVec3 castPos(0.0f, 100.0f, 0.0f);
+ float dist = 300.0f;
+ float dx = 0.3f;
+ int nx = 200;
+ int nz = 200;
+
+
+ glPointSize(10.0f);
+ glBegin(GL_POINTS);
+
+ PxHitFlags ff = PxHitFlag::ePOSITION | PxHitFlag::eNORMAL | PxHitFlag::eDISTANCE;
+ PxRaycastBuffer buf1;
+ PxRaycastHit hit;
+ for (int i = 0; i < nz; i++) {
+ for (int j = 0; j < nx; j++) {
+ PxVec3 startP = start + xdir*dx*j + zdir*dx*i + castPos;
+ scene->raycast(startP, castDir, dist, buf1, ff);
+ hit = buf1.block;
+ if (buf1.hasBlock) {
+ PxVec3 pos = startP + hit.distance * castDir;
+ glColor3f(1.0f,0.0f,0.0f);
+ glVertex3fv(&pos.x);
+ } else {
+ PxVec3 pos = startP;
+ pos.y = 0.0f;
+ glColor3f(0.0f,1.0f,0.0f);
+ glVertex3fv(&pos.x);
+
+ }
+
+ // scene->raycastSingle()
+
+ }
+ }
+
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+}
+
+// ------------------------------------------------------------------------------------
+void RenderShadowCasters()
+{
+ RenderObjects(false, true);
+}
+
+inline void RenderDepthNormalInline(bool renderNormals){
+ if(renderNormals)
+ ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH_NORMAL;
+ else
+ ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH;
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ if (gCamera.trackballMode) {
+ gCamera.trackballCenter.x = 0.0f;
+ gCamera.trackballCenter.z = 0.0f;
+ gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius;
+ }
+
+ PxVec3 pos = gCamera.pos;
+ PxVec3 dir = gCamera.forward;
+ PxVec3 apos = gCamera.pos + dir;
+ gluLookAt(pos.x, pos.y, pos.z, pos.x + dir.x, pos.y + dir.y, pos.z + dir.z, 0.0f, 1.0f, 0.0f);
+ RenderObjects(true, false);
+
+ ShaderShadow::renderMode = ShaderShadow::RENDER_COLOR;
+
+}
+
+void RenderDepthNormal()
+{
+ RenderDepthNormalInline(true);
+}
+
+void RenderDepthOnly()
+{
+ RenderDepthNormalInline(false);
+}
+
+// ------------------------------------------------------------------------------------
+void RenderScene()
+{
+ // shadows
+ SetupCamera(false);
+
+ int numShadows = gNumShadows;
+ bool showReflections = gShowReflections;
+ if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) {
+ numShadows = 0;
+ showReflections = false;
+ }
+
+ if (numShadows > 0) {
+ ShaderShadow::renderMode = ShaderShadow::RENDER_DEPTH;
+ for (int i = 0; i < gNumLights; i++) {
+ if (gShadowMaps[i] == NULL)
+ //gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i,12000);
+ //gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i, 12000);
+ gShadowMaps[i] = new ShadowMap(gViewWidth, gViewHeight, gCamera.fov, i, 6144);
+
+ gDefaultShader->setShadowMap(i, gShadowMaps[i]);
+ if (gSampleScene != NULL) {
+ for (int j = 0; j < (int)gSampleScene->getShaders().size(); j++)
+ gSampleScene->getShaders()[j]->setShadowMap(i, gShadowMaps[i]);
+ }
+ if (i > numShadows)
+ continue;
+
+
+ if (gShadowMaps[i] != NULL)
+ gShadowMaps[i]->makeShadowMap(gCamera.pos, gCamera.forward, gLightDirs[i],
+ shadowClipNear, shadowClipFar, &RenderShadowCasters);
+ }
+ ShaderShadow::renderMode = ShaderShadow::RENDER_COLOR;
+ }
+
+ for (int i = 0; i < gNumLights; i++)
+ gDefaultShader->setSpotLight(i, gLightPos[i], gLightDirs[i]);
+ gDefaultShader->setBackLightDir(gBackLightDir);
+ gDefaultShader->setNumShadows(numShadows);
+ gDefaultShader->setShowReflection(showReflections);
+
+ if (gSampleScene != NULL) {
+ for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++) {
+ ShaderShadow *s = gSampleScene->getShaders()[i];
+ for (int j = 0; j < gNumLights; j++)
+ s->setSpotLight(j, gLightPos[j], gLightDirs[j]);
+ s->setBackLightDir(gBackLightDir);
+ s->setNumShadows(numShadows);
+ s->setShowReflection(showReflections);
+ }
+ }
+
+ // reflection
+ if (showReflections) {
+
+ int reflectWidth = gViewWidth;
+ int reflectHeight = gViewHeight;
+
+ if (doAA) {
+ reflectWidth = g_pAABox->getBufW();
+ reflectHeight = g_pAABox->getBufH();
+ }
+ if (gReflectedSceneTarget == NULL) {
+
+ gReflectedSceneTarget = new RenderTarget(reflectWidth, reflectHeight);
+ gReflectedSceneTarget->beginCapture();
+ glViewport(0, 0, reflectWidth, reflectHeight);
+ gReflectedSceneTarget->endCapture();
+
+ gDefaultShader->setReflectionTexId(gReflectedSceneTarget->getColorTexId());
+ if (gSampleScene != NULL) {
+ for (int i = 0; i < (int)gSampleScene->getShaders().size(); i++)
+ gSampleScene->getShaders()[i]->setReflectionTexId(gReflectedSceneTarget->getColorTexId());
+ }
+ }
+
+ glViewport(0, 0, reflectWidth, reflectHeight);
+ gReflectedSceneTarget->beginCapture();
+
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+// glClear(GL_DEPTH_BUFFER_BIT); // todo: why is this faster?
+
+ GLdouble clipEq[4];
+ clipEq[0] = 0.0f;
+ clipEq[1] = -1.0f;
+ clipEq[2] = 0.0f;
+ clipEq[3] = gGroundY;
+ glEnable(GL_CLIP_PLANE0);
+ glClipPlane(GL_CLIP_PLANE0, clipEq);
+
+ SetupCamera(true);
+ RenderObjects(true, true);
+
+ glDisable(GL_CLIP_PLANE0);
+ gReflectedSceneTarget->endCapture();
+ }
+ glViewport(0, 0, gViewWidth, gViewHeight);
+
+ SetupCamera();
+
+ bool useFXAA = doFXAA && gFXAAOn;
+
+ if (gDoHDR)
+ gHDRHelper->beginHDR(true);
+ else
+ {
+ if (useFXAA)
+ gFXAAHelper->StartFXAA();
+ }
+
+ if (doAA) {
+ if (gDoHDR) {
+ g_pAABox->oldFbo = gHDRHelper->mHDRFbo;
+
+ }
+ g_pAABox->Activate(0,0);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+
+ RenderObjects(true, false);
+
+ //glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ if (gDoSSAO) {
+ int oldFbo = (doAA)? (g_pAABox->fbms ? g_pAABox->fbms : g_pAABox->fb) : 0;
+
+ if (useFXAA) oldFbo = gFXAAHelper->FBO;
+ if (gDoHDR) {
+ if (!doAA) {
+ oldFbo = gHDRHelper->mHDRFbo;
+ }
+ }
+
+ if (gDoHBAO)
+ gHBAOHelper->renderAO(gUseNormalMap ? RenderDepthNormal : RenderDepthOnly, oldFbo, gUseNormalMap);
+ else
+ gSSAOHelper->DoSSAO(RenderDepthNormal, oldFbo);
+ }
+
+ if (doAA) {g_pAABox->Deactivate();}
+ if (doAA) g_pAABox->Draw(g_curTech);
+
+ if (gDoHDR)
+ {
+ if (useFXAA) gFXAAHelper->StartFXAA();
+ if (useFXAA) {
+ gHDRHelper->DoHDR(gFXAAHelper->FBO, gDoDOF);
+ } else {
+ gHDRHelper->DoHDR(0, gDoDOF);
+ }
+ }
+
+ if (useFXAA)
+ gFXAAHelper->EndFXAA(0);
+}
+
+// ------------------------------------------------------------------------------------
+void RenderCallback()
+{
+ if (gForceReloadShader) {
+ SceneKapla* scene = (SceneKapla*) gSampleScene;
+ scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\scene_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\scene_fs.cpp")).c_str());
+ gForceReloadShader = false;
+ }
+ if (gForceReloadDebugShader) {
+ gDisplayTexArrayProg->loadShaders((string(gResourcePath) + string("\\shaders\\passthrough_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\shadowdebug_fs.cpp")).c_str());
+ gDefaultShader->loadShaders((string(gResourcePath) + string("\\shaders\\default_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\default_fs.cpp")).c_str());
+ gHDRHelper->mShaderDOF.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\dof_fs.cpp")).c_str());
+ gHDRHelper->mShaderBloomH.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomH_fs.cpp")).c_str());
+ gHDRHelper->mShaderBloomV.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomV_fs.cpp")).c_str());
+ gSSAOHelper->SSAOFilterH.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterh_fs.cpp")).c_str());
+ gSSAOHelper->SSAOFilterV.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterv_fs.cpp")).c_str());
+
+ SceneKapla* scene = (SceneKapla*)gSampleScene;
+ if (!scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\combine_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\combine_fs.cpp")).c_str())) {
+ printf("Can't load shader\n");
+ }
+ gForceReloadDebugShader = false;
+
+
+ }
+
+ static float first_frame_time = getCurrentTime();
+
+ ProcessKeys();
+ if (gDisableRendering)
+ {
+ if(!gPause)
+ {
+ BeginSimulation();
+ EndSimulation();
+ }
+ }
+ else
+ {
+ if (!gPause)
+ BeginSimulation();
+
+ // Clear buffers
+ // glClearColor(0.52f, 0.60f, 0.71f, 1.0f);
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (SampleViewerScene::getRenderType() == SampleViewerScene::rtOPTIX) {
+ gSampleScene->render(true);
+ SetupCamera();
+ } else {
+ RenderScene();
+ }
+
+ DisplayText();
+
+ if(gSampleScene)
+ {
+ sampleViewerGamepad.processGamepads(*gSampleScene);
+ }
+
+ glutSwapBuffers();
+ glutReportErrors();
+
+ if (!gPause)
+ EndSimulation();
+
+ if (gRecordBMP)
+ SaveFrameBuffer();
+ }
+
+ gFrameNr++; // global frame nr
+ gFrameCounter++; // FPS
+
+ if (gMaxFrameNr > 0) { // benchmark mode
+ if (gFrameNr >= gMaxFrameNr) {
+ printf("Benchmark done %d frames: %g seconds.\n",
+ gMaxFrameNr, getCurrentTime() - first_frame_time );
+ SampleViewerScene::cleanupStaticResources();
+ exit(0);
+ }
+ }
+
+ if (gShot) {
+ }
+
+
+}
+
+// ------------------------------------------------------------------------------------
+void ReshapeCallback(int width, int height)
+{
+ gViewWidth = width;
+ gViewHeight = height;
+ glViewport(0, 0, width, height);
+
+ if (gDoHDR)
+ {
+ gHDRHelper->Resize(width, height);
+ }
+
+ if (doAA) {
+ if(g_pAABox) delete g_pAABox;
+ g_pAABox = new AABox(gResourcePath);
+ g_pAABox->Initialize(width, height, g_curSSSize, g_aaModes[g_curAA].ds, g_aaModes[g_curAA].cs);
+ gSSAOHelper->Resize(g_pAABox->bufw, g_pAABox->bufh);
+ gHBAOHelper->resize(g_pAABox->bufw, g_pAABox->bufh, width, height);
+ } else {
+ gSSAOHelper->Resize(width, height);
+ gHBAOHelper->resize(width, height, width, height);
+ }
+ if (doFXAA) {
+ gFXAAHelper->Resize(width, height);
+ }
+
+}
+
+// ------------------------------------------------------------------------------------
+void IdleCallback()
+{
+ glutPostRedisplay();
+
+ float time = getCurrentTime();
+ float elapsedTime = time - gPreviousTime;
+
+ if (elapsedTime > 1.0f) {
+ char title[30];
+ curFPS = (float)gFrameCounter / elapsedTime;
+ //
+ sprintf(title, "GRB Demo");
+ glutSetWindowTitle(title);
+ gPreviousTime = time;
+ gFrameCounter = 0;
+ }
+ getElapsedTime();
+}
+
+
+void CreateSampleViewerScene()
+{
+ if (gSampleScene != NULL)
+ delete gSampleScene;
+ gSampleScene = NULL;
+
+ if (gMaxFrameNr > 0) { // benchmark mode
+ gPause = false;
+ }
+ else {
+ gPause = false;
+ }
+
+
+ float sceneSize = 20.0f;
+ sceneBounds.minimum = PxVec3(-sceneSize, 0.0f, -sceneSize);
+ sceneBounds.maximum = PxVec3(sceneSize, sceneSize, sceneSize);
+
+ float fluidSize = 5.0f;
+
+
+ //printf("Scene B is %f %f %f --- %f %f %f\n", sceneBounds.minimum.x, sceneBounds.minimum.y, sceneBounds.minimum.z,
+ // sceneBounds.maximum.x, sceneBounds.maximum.y, sceneBounds.maximum.z);
+ //gForceReloadDebugShader = true;
+ PxVec3 target(0.0f, 0.0f, 0.0f);
+ g_fogStart = 50.0f;
+ g_fogEnd = 150.0f;
+ shadowClipNear = 0.2f;
+ shadowClipFar = 100.0f;
+
+ DEFAULT_SOLVER_ITERATIONS = 8;
+
+ g_shadowAdd = -0.001f;
+
+ switch (gSceneNr) {
+ case 0:
+ {
+ gSampleScene = new SceneKaplaTower(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor);
+ gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, sceneBounds.maximum.z*2.f)*5.0f;
+ //g_shadowAdd = 0.f;// -0.004054f;
+
+ sprintf(gDemoName, "GRB Kapla Tower");
+ break;
+ }
+ case 1:
+ {
+ gSampleScene = new SceneKaplaArena(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor);
+ gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, sceneBounds.maximum.z)*5.0f;
+ //g_shadowAdd = -0.003;
+ //g_shadowAdd = 0.f;
+ sprintf(gDemoName, "GRB Kapla Arena");
+ break;
+ }
+ case 2:
+ {
+ gSampleScene = new SceneVehicle(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor);
+ gLightPos[0] = PxVec3(sceneBounds.maximum.x, sceneBounds.maximum.y*3.0f, -sceneBounds.maximum.z)*5.0f;
+ //g_shadowAdd = -0.003;
+ //g_shadowAdd = -0.001891;
+ //g_shadowAdd = 0.f;
+ sprintf(gDemoName, "GRB Vehicle Demo");
+ break;
+ }
+ case 3:
+ {
+ //DEFAULT_SOLVER_ITERATIONS = 4;
+ gSampleScene = new SceneCrab(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor);
+ gLightPos[0] = PxVec3(-sceneBounds.maximum.x, sceneBounds.maximum.y*8.0f, sceneBounds.maximum.z)*8.0f;
+ //g_shadowAdd = -0.001891;
+ //g_shadowAdd = 0.f;
+ g_fogStart = 150.0f;
+ g_fogEnd = 350.0f;
+ //shadowClipFar = 100.0f;
+ sprintf(gDemoName, "GRB Walkers Demo ");
+
+ break;
+ }
+ default:
+ {
+ //DEFAULT_SOLVER_ITERATIONS = 4;
+ //g_shadowAdd = -0.004054f;
+ //g_shadowAdd = 0.f;
+ //shadowClipFar = 130.0f;
+ gLightPos[0] = PxVec3(0.f, 25.f, 150.f);
+ gSampleScene = new SceneRagdollWashingMachine(gPxPhysics, gPxCooking, gUseGrb, gDefaultShader, gResourcePath, gSlowMotionFactor);
+ sprintf(gDemoName, "GRB Ragdoll Demo ");
+ break;
+ }
+ }
+
+ SceneKapla* scene = (SceneKapla*)gSampleScene;
+
+ if (!scene->mSimSceneShader->loadShaders((string(gResourcePath) + string("\\shaders\\combine_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\combine_fs.cpp")).c_str()))
+ {
+ printf("Can't load shader\n");
+ }
+
+ gSampleScene->getInitialCamera(gCamera.pos, gCamera.forward);
+ float fogColor[4] = { 0, 0, 0, 1 };
+ glFogf(GL_FOG_DENSITY, 0.0009f);
+ glFogf(GL_FOG_START, g_fogStart);
+ glFogf(GL_FOG_END, g_fogEnd);
+ glFogfv(GL_FOG_COLOR, fogColor);
+
+ gLightDirs[0] = gLightPos[0] - target;
+ gLightDirs[0].normalize();
+
+ if (gSceneNr == 4)
+ {
+ gLightDirs[0] = PxVec3(0.f, 0.2f, 1.f).getNormalized();
+ }
+
+ gLightPos[1] = PxVec3(sceneBounds.minimum.x, sceneBounds.maximum.y, sceneBounds.minimum.z);
+ gLightDirs[1] = gLightPos[1] - target;
+ gLightDirs[1].normalize();
+
+ gLightPos[2] = PxVec3((sceneBounds.minimum.x + sceneBounds.maximum.x) * 0.5f, sceneBounds.maximum.y, sceneBounds.minimum.z);
+ gLightDirs[2] = gLightPos[2] - target;
+ gLightDirs[2].normalize();
+
+ gBackLightDir = PxVec3(0.8f, -1.0f, -1.2f);
+ gBackLightDir.normalize();
+
+ myDustColor = ((SceneKapla*)gSampleScene)->getSimSceneShader()->getDustColor();
+ SetHelpString();
+
+}
+
+// ------------------------------------------------------------------------------------
+void InitSampleViewerScene()
+{
+ gSampleScene->onInit(gPxScene);
+}
+
+void InitGlutCallbacks(bool, int, int);
+
+//-----------------------------------------------------------------------------
+void ToggleFullscreen()
+{
+ static int window[4] = {-1, -1, -1, -1};
+
+ if ( window[0] == -1) { // We are in non-fullscreen mode
+ window[0] = glutGet(GLUT_WINDOW_WIDTH);
+ window[1] = glutGet(GLUT_WINDOW_HEIGHT);
+ window[2] = glutGet(GLUT_WINDOW_X);
+ window[3] = glutGet(GLUT_WINDOW_Y);
+ glutFullScreen();
+ }
+ else
+ { // We are in fullscreen mode
+ glutPositionWindow( window[2], window[3] );
+ glutReshapeWindow( window[0], window[1] );
+ window[0] = -1;
+ }
+
+
+
+ glutPostRedisplay();
+}
+
+
+// ------------------------------------------------------------------------------------
+void KeyboardCallback(unsigned char key, int x, int y)
+{
+ if (key != 'p' && key != 'w' && key != 'a' && key != 's' && key != 'd' && key != 'q' && key != 'e' && key != 'x' && key != 'v'
+ && key != 'u' && key != 'i' && key != 'k' && key != 'y' && key != 'b' && key != 'c' && key != 'h' && key != 'H' && key != 'n')
+ gPause = false;
+
+ if (key == ' ') {
+ gShot = true;
+ }
+
+ gKeys[key] = true;
+
+ if ('1' <= key && key <= '0' + gNumScenes)
+ {
+ gSceneNr = key - '0' - 1;
+
+ WaitForSim();
+
+ if (gSampleScene)
+ delete gSampleScene;
+ gSampleScene = NULL;
+
+ CreateSampleViewerScene();
+ RecreateSDKScenes();
+
+ InitSampleViewerScene();
+
+ }
+
+ switch (key)
+ {
+ case 'f' : ToggleFullscreen(); break;
+
+ case 27 : {
+ CleanupSample();
+ exit(0);
+ } break;
+ case 'p': { gPause = !gPause; UpdateTime(); break; }
+ case 'o': { if (!gPause) gPause = true; RunPhysics(); glutPostRedisplay(); break; }
+ case 'h': { gDoSSAO = !gDoSSAO; break; }
+ case 'H': { gDoHBAO = !gDoHBAO; break; }
+ //case 'n': { gUseNormalMap = !gUseNormalMap; break; }
+
+ default: ;
+ }
+
+ if (gSampleScene != NULL)
+ gSampleScene->handleKeyDown(key, x, y);
+}
+
+void CleanupSample()
+{
+ if (gIsSampleCleanedUp)
+ return;
+
+ WaitForSim();
+
+ if (gSampleScene != NULL) {
+ delete gSampleScene;
+ gSampleScene = 0;
+ }
+ SampleViewerScene::cleanupStaticResources();
+ ReleaseSDKs();
+
+ glutDestroyWindow(gMainHandle);
+
+ gIsSampleCleanedUp = true;
+}
+
+// ------------------------------------------------------------------------------------
+
+void KeyboardUpCallback(unsigned char key, int x, int y)
+{
+ gKeys[key] = false;
+ if (gSampleScene != NULL)
+ gSampleScene->handleKeyUp(key, x, y);
+}
+
+// ------------------------------------------------------------------------------------
+
+void SpecialCallback(int key, int x, int y)
+{
+ switch (key)
+ {
+ // Reset PhysX
+ case GLUT_KEY_F1:
+ gHelp = !gHelp;
+ break;
+ case GLUT_KEY_F2:
+ gDisplay = !gDisplay;
+ break;
+
+ case GLUT_KEY_F10:
+ {
+ WaitForSim();
+
+ if (gSampleScene)
+ delete gSampleScene;
+ gSampleScene = NULL;
+
+ CreateSampleViewerScene();
+ RecreateSDKScenes();
+
+ InitSampleViewerScene();
+ return;
+ }
+ case GLUT_KEY_F5:
+ {
+ gUseGrb = !gUseGrb;
+ }
+ }
+ if (gSampleScene != NULL)
+ gSampleScene->handleSpecialKey(key, x, y);
+
+ SetHelpString();
+}
+
+// ------------------------------------------------------------------------------------
+void MouseCallback(int button, int state, int x, int y)
+{
+ if (button != GLUT_LEFT_BUTTON || glutGetModifiers() != 0)
+ gPause = false;
+
+ gMouseX = x;
+ gMouseY = y;
+
+ if (!(glutGetModifiers() & GLUT_ACTIVE_SHIFT)) {
+
+ if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
+ {
+ gCamera.zoom = true;
+ }
+ else if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
+ {
+ gCamera.rotate = true;
+ }
+ else if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN)
+ {
+ gCamera.translate = true;
+ }
+ }
+ if (state == GLUT_UP)
+ {
+ gCamera.rotate = false;
+ gCamera.translate = false;
+ gCamera.zoom = false;
+ }
+
+ if (gSampleScene != NULL)
+ gSampleScene->handleMouseButton(button, state, x, y);
+}
+
+// ------------------------------------------------------------------------------------
+
+void MotionCallback(int x, int y)
+{
+
+ int dx = gMouseX - x;
+ int dy = gMouseY - y;
+
+ PxVec3 up;
+ up = PxVec3(0,1,0);
+
+ const float translateSpeed = 0.1f;
+
+ if (gCamera.translate)
+ {
+ PxVec3 &pos = gCamera.trackballMode ? gCamera.trackballCenter : gCamera.pos;
+ pos += gCamera.right * dx * translateSpeed;
+ pos -= up * dy * translateSpeed;
+ }
+ else if (gCamera.rotate)
+ {
+ const float rotationSpeed = 0.01f;
+ if (gCamera.trackballMode) {
+ gCamera.forward.normalize();
+ gCamera.right = gCamera.forward.cross(PxVec3(0,1,0));
+
+ PxQuat qy(dx * rotationSpeed, PxVec3(0.0f, 1.0f, 0.0f));
+ gCamera.forward = qy.rotate(gCamera.forward);
+ PxQuat qx(dy * rotationSpeed, gCamera.right);
+ gCamera.forward = qx.rotate(gCamera.forward);
+ gCamera.forward.y = PxClamp(gCamera.forward.y, 0.9f, -0.9f);
+ gCamera.forward.normalize();
+ gCamera.pos = gCamera.trackballCenter - gCamera.forward * gCamera.trackballRadius;
+ }
+ else {
+ PxQuat qx(dx * rotationSpeed, up);
+ gCamera.forward = qx.rotate(gCamera.forward);
+ PxQuat qy(dy * rotationSpeed, gCamera.right);
+ PxVec3 tempForward = gCamera.forward;
+ gCamera.forward = qy.rotate(gCamera.forward);
+ gCamera.forward.normalize();
+
+ if (PxAbs(gCamera.forward.y) > 0.98f)
+ {
+ //Clamp the axis...
+ gCamera.forward = tempForward;
+ gCamera.forward.normalize();
+ }
+ }
+ }
+ else if (gCamera.zoom) {
+ if (gCamera.trackballMode)
+ gCamera.trackballRadius *= 1.0f + 0.01f * dy;
+ else
+ gCamera.pos -= gCamera.forward * dy * translateSpeed;
+ }
+
+ gMouseX = x;
+ gMouseY = y;
+
+ if (gSampleScene != NULL)
+ gSampleScene->handleMouseMotion(x, y);
+}
+
+// ------------------------------------------------------------------------------------
+
+void InitGlutCallbacks(bool fullscreen, int width, int height)
+{
+ if (fullScreen) {
+ char modeS[500];
+ sprintf(modeS, "%dx%d:32@60", width, height);
+ glutGameModeString(modeS);
+ glutEnterGameMode();
+ }
+ else {
+ gMainHandle = glutCreateWindow("Sample Viewer");
+ glutSetWindow(gMainHandle);
+ }
+ glutDisplayFunc(RenderCallback);
+ glutReshapeFunc(ReshapeCallback);
+ glutIdleFunc(IdleCallback);
+ glutKeyboardFunc(KeyboardCallback);
+ glutKeyboardUpFunc(KeyboardUpCallback);
+ glutSpecialFunc(SpecialCallback);
+ glutMouseFunc(MouseCallback);
+ glutMotionFunc(MotionCallback);
+ glutPassiveMotionFunc(MotionCallback);
+ MotionCallback(0, 0);
+}
+
+void InitGlut(int argc, char **argv)
+{
+ //printf("glutInit\n");
+
+ glutInit(&argc, argv);
+ glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
+ glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
+
+ InitGlutCallbacks(fullScreen, WINDOW_WIDTH, WINDOW_HEIGHT);
+
+ sampleViewerGamepad.init();
+
+ // Setup default render states
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_COLOR_MATERIAL);
+ //glEnable(GL_CULL_FACE);
+ glShadeModel(GL_SMOOTH);
+#ifdef WIN32
+ glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
+ glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
+#endif
+
+ // Setup lighting
+ glEnable(GL_LIGHTING);
+// float AmbientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor);
+// float DiffuseColor[] = { 0.8f, 0.8f, 0.8f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor);
+// float SpecularColor[] = { 0.7f, 0.7f, 0.7f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor);
+
+ float AmbientColor[] = { 0.0f, 0.0f, 0.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor);
+ float DiffuseColor[] = { 0.6f, 0.6f, 0.6f, 0.0f }; glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor);
+ float SpecularColor[] = { 0.7f, 0.7f, 0.7f, 0.0f }; glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor);
+
+
+ // float Position[] = { 100.0f, 100.0f, -400.0f, 1.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position);
+ //float Position[] = { 10.0f, 200.0f, 15.0f, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position);
+
+ //float Position[] = { -400,200,300, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position);
+#if !TEST_ART_GALLERY_FLOOR
+ float Position[] = { -400,200,300, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position);
+#else
+ float Position[] = { 674,-300,200, 0.0f }; glLightfv(GL_LIGHT0, GL_POSITION, Position);
+#endif
+ glEnable(GL_LIGHT0);
+ glEnable(GL_NORMALIZE); // so that lighting on scaled objects is correct
+
+
+ PxVec3 target = PxVec3(0.0f, 8.0f, -25.0f);
+ gCamera.forward = target - gCamera.pos;
+ gCamera.forward.normalize();
+
+ for (int i = 0; i < gNumLights; i++)
+ gShadowMaps[i] = NULL;
+
+ GLenum err = glewInit();
+ if (err != GLEW_OK) {
+ printf("glewInit() failed\n");
+ exit(0);
+ }
+
+ // Setup Fog
+ glEnable (GL_FOG);
+ float fogColor[4] = {180.0f/255.0f,182.0f/255.0f,202.0f/255.0f,1.0f};
+ glFogi (GL_FOG_MODE, GL_LINEAR);
+
+ glFogf(GL_FOG_DENSITY, 0.0009f);
+ glFogf(GL_FOG_START, g_fogStart);
+ glFogf(GL_FOG_END, g_fogEnd);
+ glFogfv (GL_FOG_COLOR, fogColor);
+
+ // Load ground texture
+ gSplashScreenTexId = 0;
+
+ gDisplayTexArrayProg = new Shader();
+ gDisplayTexArrayProg->loadShaderCode(passThruVS, texture2DArrayPS);
+
+ gDisplaySplashProg = new Shader();
+ gDisplaySplashProg->loadShaderCode(passThruVS, textureRECTPS);
+
+ if (doAA) {
+ g_pAABox = new AABox(gResourcePath);
+ g_pAABox->Initialize(WINDOW_WIDTH, WINDOW_HEIGHT, g_curSSSize, g_aaModes[g_curAA].ds, g_aaModes[g_curAA].cs);
+ }
+
+ if (gDoHDR)
+ {
+ ShaderShadow::hdrScale = 2.0f;
+ }
+
+ gDefaultShader = new ShaderShadow(ShaderShadow::VS_DEFAULT, ShaderShadow::PS_SHADE);
+ gDefaultShader->init();
+
+ /*
+ TCHAR pwd[500];
+ GetCurrentDirectory(500,pwd);
+ MessageBox(NULL,pwd,pwd,0);
+*/
+ gFXAAHelper = new FXAAHelper(gResourcePath);
+ gSSAOHelper = new SSAOHelper(gCamera.fov, 0.1f, zNear, zFar, gResourcePath, doAA ? (1.0f/g_curSSSize) : 1.0f);
+ gHBAOHelper = new HBAOHelper(gCamera.fov, zNear, zFar);
+ gHDRHelper = new HDRHelper(gCamera.fov, 0.1f, zNear, zFar, gResourcePath, doAA ? (1.0f/g_curSSSize) : 1.0f);
+
+ gDisplayTexArrayProg->loadShaders((string(gResourcePath) + string("\\shaders\\passthrough_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\shadowdebug_fs.cpp")).c_str());
+ gDefaultShader->loadShaders((string(gResourcePath) + string("\\shaders\\default_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\default_fs.cpp")).c_str());
+ gHDRHelper->mShaderDOF.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\dof_fs.cpp")).c_str());
+ gHDRHelper->mShaderBloomH.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomH_fs.cpp")).c_str());
+ gHDRHelper->mShaderBloomV.loadShaders((string(gResourcePath) + string("\\shaders\\dof_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\bloomV_fs.cpp")).c_str());
+ gSSAOHelper->SSAOFilterH.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterh_fs.cpp")).c_str());
+ gSSAOHelper->SSAOFilterV.loadShaders((string(gResourcePath) + string("\\shaders\\filterv_vs.cpp")).c_str(), (string(gResourcePath) + string("\\shaders\\filterv_fs.cpp")).c_str());
+ gForceReloadDebugShader = false;
+
+
+ if (gSceneNr == 7) {
+ gCamera.pos = PxVec3(0.0319193f,3.24621f, 3.47924f);
+ }
+}
+
+extern int numCylinderSeg ;
+// ------------------------------------------------------------------------------------
+static bool parse_value_arg( std::string const& arg, std::string const& name, int& value )
+{
+ if (arg.substr(0, name.length() + 1) == (name + "=")) {
+ value = atoi( arg.substr(name.length() + 1).c_str());
+ return true;
+ }
+ return false;
+}
+
+static bool starts_with( std::string const& arg, std::string const& text )
+{
+ return arg.find( text ) == 0;
+}
+
+#define SQR(x) ((x)*(x)) // x^2
+
+// Constants
+#define M_SQRT3 1.73205080756887729352744634151 // sqrt(3)
+ // x^2
+
+
+// ----------------------------------------------------------------------------
+int dsyevc3(float A[3][3], float w[3])
+// ----------------------------------------------------------------------------
+// Calculates the eigenvalues of a symmetric 3x3 matrix A using Cardano's
+// analytical algorithm.
+// Only the diagonal and upper triangular parts of A are accessed. The access
+// is read-only.
+// ----------------------------------------------------------------------------
+// Parameters:
+// A: The symmetric input matrix
+// w: Storage buffer for eigenvalues
+// ----------------------------------------------------------------------------
+// Return value:
+// 0: Success
+// -1: Error
+// ----------------------------------------------------------------------------
+{
+ float m, c1, c0;
+
+ // Determine coefficients of characteristic poynomial. We write
+ // | a d f |
+ // A = | d* b e |
+ // | f* e* c |
+ float de = A[0][1] * A[1][2]; // d * e
+ float dd = SQR(A[0][1]); // d^2
+ float ee = SQR(A[1][2]); // e^2
+ float ff = SQR(A[0][2]); // f^2
+ m = A[0][0] + A[1][1] + A[2][2];
+ c1 = (A[0][0]*A[1][1] + A[0][0]*A[2][2] + A[1][1]*A[2][2]) // a*b + a*c + b*c - d^2 - e^2 - f^2
+ - (dd + ee + ff);
+ c0 = A[2][2]*dd + A[0][0]*ee + A[1][1]*ff - A[0][0]*A[1][1]*A[2][2]
+ - 2.0 * A[0][2]*de; // c*d^2 + a*e^2 + b*f^2 - a*b*c - 2*f*d*e)
+
+ float p, sqrt_p, q, c, s, phi;
+ p = SQR(m) - 3.0*c1;
+ q = m*(p - (3.0/2.0)*c1) - (27.0/2.0)*c0;
+ sqrt_p = sqrtf(fabs(p));
+
+ phi = 27.0 * ( 0.25*SQR(c1)*(p - c1) + c0*(q + 27.0/4.0*c0));
+ phi = (1.0/3.0) * atan2(sqrt(fabs(phi)), q);
+
+ c = sqrt_p*cosf(phi);
+ s = (1.0/M_SQRT3)*sqrt_p*sinf(phi);
+
+ w[1] = (1.0/3.0)*(m - c);
+ w[2] = w[1] + s;
+ w[0] = w[1] + c;
+ w[1] -= s;
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+int dsyevv3(float A[3][3], float Q[3][3], float w[3])
+// ----------------------------------------------------------------------------
+// Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3
+// matrix A using Cardano's method for the eigenvalues and an analytical
+// method based on vector cross products for the eigenvectors.
+// Only the diagonal and upper triangular parts of A need to contain meaningful
+// values. However, all of A may be used as temporary storage and may hence be
+// destroyed.
+// ----------------------------------------------------------------------------
+// Parameters:
+// A: The symmetric input matrix
+// Q: Storage buffer for eigenvectors
+// w: Storage buffer for eigenvalues
+// ----------------------------------------------------------------------------
+// Return value:
+// 0: Success
+// -1: Error
+// ----------------------------------------------------------------------------
+// Dependencies:
+// dsyevc3()
+// ----------------------------------------------------------------------------
+// Version history:
+// v1.1 (12 Mar 2012): Removed access to lower triangualr part of A
+// (according to the documentation, only the upper triangular part needs
+// to be filled)
+// v1.0: First released version
+// ----------------------------------------------------------------------------
+{
+#ifndef EVALS_ONLY
+ float norm; // Squared norm or inverse norm of current eigenvector
+ float n0, n1; // Norm of first and second columns of A
+ float n0tmp, n1tmp; // "Templates" for the calculation of n0/n1 - saves a few FLOPS
+ float thresh; // Small number used as threshold for floating point comparisons
+ float error; // Estimated maximum roundoff error in some steps
+ float wmax; // The eigenvalue of maximum modulus
+ float f, t; // Intermediate storage
+ int i, j; // Loop counters
+#endif
+
+ // Calculate eigenvalues
+ dsyevc3(A, w);
+
+#ifndef EVALS_ONLY
+ wmax = fabs(w[0]);
+ if ((t=fabs(w[1])) > wmax)
+ wmax = t;
+ if ((t=fabs(w[2])) > wmax)
+ wmax = t;
+ thresh = SQR(8.0 * DBL_EPSILON * wmax);
+
+ // Prepare calculation of eigenvectors
+ n0tmp = SQR(A[0][1]) + SQR(A[0][2]);
+ n1tmp = SQR(A[0][1]) + SQR(A[1][2]);
+ Q[0][1] = A[0][1]*A[1][2] - A[0][2]*A[1][1];
+ Q[1][1] = A[0][2]*A[0][1] - A[1][2]*A[0][0];
+ Q[2][1] = SQR(A[0][1]);
+
+ // Calculate first eigenvector by the formula
+ // v[0] = (A - w[0]).e1 x (A - w[0]).e2
+ A[0][0] -= w[0];
+ A[1][1] -= w[0];
+ Q[0][0] = Q[0][1] + A[0][2]*w[0];
+ Q[1][0] = Q[1][1] + A[1][2]*w[0];
+ Q[2][0] = A[0][0]*A[1][1] - Q[2][1];
+ norm = SQR(Q[0][0]) + SQR(Q[1][0]) + SQR(Q[2][0]);
+ n0 = n0tmp + SQR(A[0][0]);
+ n1 = n1tmp + SQR(A[1][1]);
+ error = n0 * n1;
+
+ if (n0 <= thresh) // If the first column is zero, then (1,0,0) is an eigenvector
+ {
+ Q[0][0] = 1.0;
+ Q[1][0] = 0.0;
+ Q[2][0] = 0.0;
+ }
+ else if (n1 <= thresh) // If the second column is zero, then (0,1,0) is an eigenvector
+ {
+ Q[0][0] = 0.0;
+ Q[1][0] = 1.0;
+ Q[2][0] = 0.0;
+ }
+ else if (norm < SQR(64.0 * DBL_EPSILON) * error)
+ { // If angle between A[0] and A[1] is too small, don't use
+ t = SQR(A[0][1]); // cross product, but calculate v ~ (1, -A0/A1, 0)
+ f = -A[0][0] / A[0][1];
+ if (SQR(A[1][1]) > t)
+ {
+ t = SQR(A[1][1]);
+ f = -A[0][1] / A[1][1];
+ }
+ if (SQR(A[1][2]) > t)
+ f = -A[0][2] / A[1][2];
+ norm = 1.0/sqrt(1 + SQR(f));
+ Q[0][0] = norm;
+ Q[1][0] = f * norm;
+ Q[2][0] = 0.0;
+ }
+ else // This is the standard branch
+ {
+ norm = sqrt(1.0 / norm);
+ for (j=0; j < 3; j++)
+ Q[j][0] = Q[j][0] * norm;
+ }
+
+
+ // Prepare calculation of second eigenvector
+ t = w[0] - w[1];
+ if (fabs(t) > 8.0 * DBL_EPSILON * wmax)
+ {
+ // For non-degenerate eigenvalue, calculate second eigenvector by the formula
+ // v[1] = (A - w[1]).e1 x (A - w[1]).e2
+ A[0][0] += t;
+ A[1][1] += t;
+ Q[0][1] = Q[0][1] + A[0][2]*w[1];
+ Q[1][1] = Q[1][1] + A[1][2]*w[1];
+ Q[2][1] = A[0][0]*A[1][1] - Q[2][1];
+ norm = SQR(Q[0][1]) + SQR(Q[1][1]) + SQR(Q[2][1]);
+ n0 = n0tmp + SQR(A[0][0]);
+ n1 = n1tmp + SQR(A[1][1]);
+ error = n0 * n1;
+
+ if (n0 <= thresh) // If the first column is zero, then (1,0,0) is an eigenvector
+ {
+ Q[0][1] = 1.0;
+ Q[1][1] = 0.0;
+ Q[2][1] = 0.0;
+ }
+ else if (n1 <= thresh) // If the second column is zero, then (0,1,0) is an eigenvector
+ {
+ Q[0][1] = 0.0;
+ Q[1][1] = 1.0;
+ Q[2][1] = 0.0;
+ }
+ else if (norm < SQR(64.0 * DBL_EPSILON) * error)
+ { // If angle between A[0] and A[1] is too small, don't use
+ t = SQR(A[0][1]); // cross product, but calculate v ~ (1, -A0/A1, 0)
+ f = -A[0][0] / A[0][1];
+ if (SQR(A[1][1]) > t)
+ {
+ t = SQR(A[1][1]);
+ f = -A[0][1] / A[1][1];
+ }
+ if (SQR(A[1][2]) > t)
+ f = -A[0][2] / A[1][2];
+ norm = 1.0/sqrt(1 + SQR(f));
+ Q[0][1] = norm;
+ Q[1][1] = f * norm;
+ Q[2][1] = 0.0;
+ }
+ else
+ {
+ norm = sqrt(1.0 / norm);
+ for (j=0; j < 3; j++)
+ Q[j][1] = Q[j][1] * norm;
+ }
+ }
+ else
+ {
+ // For degenerate eigenvalue, calculate second eigenvector according to
+ // v[1] = v[0] x (A - w[1]).e[i]
+ //
+ // This would really get to complicated if we could not assume all of A to
+ // contain meaningful values.
+ A[1][0] = A[0][1];
+ A[2][0] = A[0][2];
+ A[2][1] = A[1][2];
+ A[0][0] += w[0];
+ A[1][1] += w[0];
+ for (i=0; i < 3; i++)
+ {
+ A[i][i] -= w[1];
+ n0 = SQR(A[0][i]) + SQR(A[1][i]) + SQR(A[2][i]);
+ if (n0 > thresh)
+ {
+ Q[0][1] = Q[1][0]*A[2][i] - Q[2][0]*A[1][i];
+ Q[1][1] = Q[2][0]*A[0][i] - Q[0][0]*A[2][i];
+ Q[2][1] = Q[0][0]*A[1][i] - Q[1][0]*A[0][i];
+ norm = SQR(Q[0][1]) + SQR(Q[1][1]) + SQR(Q[2][1]);
+ if (norm > SQR(256.0 * DBL_EPSILON) * n0) // Accept cross product only if the angle between
+ { // the two vectors was not too small
+ norm = sqrt(1.0 / norm);
+ for (j=0; j < 3; j++)
+ Q[j][1] = Q[j][1] * norm;
+ break;
+ }
+ }
+ }
+
+ if (i == 3) // This means that any vector orthogonal to v[0] is an EV.
+ {
+ for (j=0; j < 3; j++)
+ if (Q[j][0] != 0.0) // Find nonzero element of v[0] ...
+ { // ... and swap it with the next one
+ norm = 1.0 / sqrt(SQR(Q[j][0]) + SQR(Q[(j+1)%3][0]));
+ Q[j][1] = Q[(j+1)%3][0] * norm;
+ Q[(j+1)%3][1] = -Q[j][0] * norm;
+ Q[(j+2)%3][1] = 0.0;
+ break;
+ }
+ }
+ }
+
+
+ // Calculate third eigenvector according to
+ // v[2] = v[0] x v[1]
+ Q[0][2] = Q[1][0]*Q[2][1] - Q[2][0]*Q[1][1];
+ Q[1][2] = Q[2][0]*Q[0][1] - Q[0][0]*Q[2][1];
+ Q[2][2] = Q[0][0]*Q[1][1] - Q[1][0]*Q[0][1];
+#endif
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+ /*
+ float A[3][3] = {{-4,2,1},
+ {2,9,-3},
+ {1,-3,-7}};
+ float Q[3][3];
+ float w[3];
+
+ dsyevv3(A,Q,w);
+ printf("%f %f %f\n", w[0], w[1], w[2]);
+
+ return 0;
+ */
+ strcpy(gResourcePath, "../../../externalIP/resources");
+ gCamera.init();
+
+ FILE *f = fopen("resourcePath.txt", "r");
+ if (f != NULL) {
+ fgets(gResourcePath, 512, f);
+ fclose(f);
+ }
+
+ const char* usage = "Usage:\n"
+ " -msaa Do MSAA Antialiasing (Slower, but better quality). On by default. \n"
+ " -fxaa Do FXAA Antialiasing (Faster, but poorer quality)\n"
+ " -nbThreads n Use n worker threads in PhysX\n"
+ " -nossao Disable SSAO\n"
+ " -nhdr Disable HDR\n"
+ " -grb Use GRB (default is on)\n"
+ " -nogrb Use software PhysX\n"
+ " -maxSubSteps n Enable up to n sub-steps per-frame."
+ "\n"
+ ;
+ printf(usage);
+
+ std::string render_opts;
+ for (int i = 1; i < argc; i++) {
+ std::string arg = argv[i];
+ std::transform(&arg[0], &arg[0] + arg.length(), &arg[0], tolower);
+ if (arg == "-nogrb") { gUseGrb = false; gCurrentUsingGrb = false; }
+ else if (arg == "-grb") gUseGrb = true;
+ else if (arg == "-msaa") {
+ doAA = true;
+ doFXAA = false;
+ }
+ else if (arg == "-fxaa") {
+ doFXAA = true;
+ doAA = false;
+ }
+ else if (arg == "-maxsubsteps")
+ {
+ if (argc > (1 + i))
+ {
+ PxU32 substepCount = atoi(argv[i + 1]);
+ gMaxSubSteps = substepCount;
+ i++;
+ }
+ }
+ else if (arg == "-nbthreads")
+ {
+ if (argc > (1 + i))
+ {
+ PxU32 nbThreads = atoi(argv[i + 1]);
+ gNrWorkerThreads = nbThreads;
+ i++;
+ }
+ }
+ else if (arg == "-nossao")
+ {
+ gDoSSAO = false;
+ }
+ else if (arg == "-nohdr")
+ {
+ gDoHDR = false;
+ }
+
+ }
+
+ if (!InitPhysX()) {
+ ReleaseSDKs();
+ return 0;
+ }
+
+ InitGlut(argc, argv);
+
+ if (!render_opts.empty()) {
+ SampleViewerScene::setRendererOptions(render_opts.c_str());
+ }
+
+ // Initialize physics scene and start the application main loop if scene was created
+
+ SampleViewerScene::setRenderType(SampleViewerScene::rtOPENGL);
+
+ gFontRenderer = new GLFontRenderer();
+
+ CreateSampleViewerScene();
+
+ //Hack! When rendering the first frame of the demo, various extremely large graphics buffers are allocated. In GPUs with relatively small amount of memory,
+ //these allocations can fail. This seems to relate to CUDA allocations fragmenting the heap. Therefore, we initialize the first frame to use CPU simulation, scheduling a transition to
+ //GPU to ensure that these large allocations succeed. They'll never be reallocated again.
+ //Ideally, these allocations would just happen before the GRB scene was initialized but that would require some surgery to the sample framework.
+ //bool useGrb = gUseGrb;
+ //gUseGrb = false;
+ RecreateSDKScenes();
+ //gUseGrb = useGrb;
+
+ //gForceSceneRecreate = useGrb;
+
+ InitSampleViewerScene();
+
+ atexit(CleanupSample);
+
+ glutMainLoop();
+}
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewer.h b/KaplaDemo/samples/sampleViewer3/SampleViewer.h
new file mode 100644
index 00000000..beb093c2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewer.h
@@ -0,0 +1,21 @@
+#ifndef SAMPLE_VIEWER_H
+#define SAMPLE_VIEWER_H
+
+// glut callbacks
+void RenderCallback();
+void ReshapeCallback(int width, int height);
+void IdleCallback();
+void KeyboardCallback(unsigned char key, int x, int y);
+void KeyboardUpCallback(unsigned char key, int x, int y);
+void SpecialCallback(int key, int x, int y);
+void MouseCallback(int button, int state, int x, int y);
+void MotionCallback(int x, int y);
+void InitGlut(int argc, char **argv);
+
+float UpdateTime();
+void WaitForPhysics();
+void RunPhysics();
+
+int main(int argc, char** argv);
+
+#endif // SAMPLE_VIEWER_H
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.cpp b/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.cpp
new file mode 100644
index 00000000..ef6404c4
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.cpp
@@ -0,0 +1,211 @@
+#include "SampleViewerGamepad.h"
+#include "SampleViewerScene.h"
+
+#include <stdio.h>
+#include <direct.h>
+
+#include "PsString.h"
+
+//////////////////////////////////////////////////////////////////////////
+
+static bool gTimeInit = false;
+static const unsigned int MAX_GAMEPADS = 4;
+static const unsigned int MAX_GAMEPAD_AXES = 4;
+static XINPUT_STATE m_lastInputState[MAX_GAMEPADS];
+static int m_lastAxisData[MAX_GAMEPADS][MAX_GAMEPAD_AXES];
+
+//////////////////////////////////////////////////////////////////////////
+
+SampleViewerGamepad::SampleViewerGamepad()
+ : mGamePadConnected(false), mConnectedPad(0), mXInputLibrary(), mpXInputGetState(0), mpXInputGetCapabilities(0)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+SampleViewerGamepad::~SampleViewerGamepad()
+{
+ release();
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void SampleViewerGamepad::init()
+{
+ static const unsigned int xInputLibCount = 4;
+ static const char* xInputLibs[xInputLibCount] = { "xinput1_4.dll",
+ "xinput1_3.dll",
+ "xinput1_2.dll",
+ "xinput1_1.dll" };
+ for (unsigned int i = 0; i < xInputLibCount; ++i)
+ {
+ mXInputLibrary = LoadLibraryA(xInputLibs[i]);
+ if (mXInputLibrary)
+ break;
+ }
+
+ if(!mXInputLibrary)
+ {
+ physx::shdfnd::printString("Could not load XInput library.");
+ }
+
+ if (mXInputLibrary)
+ {
+ mpXInputGetState = (LPXINPUTGETSTATE)GetProcAddress(mXInputLibrary, "XInputGetState");
+ mpXInputGetCapabilities = (LPXINPUTGETCAPABILITIES)GetProcAddress(mXInputLibrary, "XInputGetCapabilities");
+ if(!mpXInputGetState)
+ {
+ physx::shdfnd::printString("Error loading XInputGetState function.");
+ }
+
+ if(!mpXInputGetCapabilities)
+ {
+ physx::shdfnd::printString("Error loading XInputGetCapabilities function.");
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void SampleViewerGamepad::release()
+{
+ if (mXInputLibrary)
+ {
+ FreeLibrary(mXInputLibrary);
+ mXInputLibrary = 0;
+ }
+
+ mpXInputGetState = 0;
+ mpXInputGetCapabilities = 0;
+ mGamePadConnected = false;
+ mConnectedPad = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+void SampleViewerGamepad::processGamepads(SampleViewerScene& viewerScene)
+{
+ if (!gTimeInit)
+ {
+ gTimeInit = true;
+
+ for (unsigned int p = 0; p < MAX_GAMEPADS; p++)
+ {
+ memset(&m_lastInputState[p], 0, sizeof(XINPUT_STATE));
+ for (unsigned int i = 0; i < MAX_GAMEPAD_AXES; i++)
+ {
+ m_lastAxisData[p][i] = 0;
+ }
+ }
+ }
+
+ static int32_t disConnected[4] = { 1, 2, 3, 4 };
+
+ if (!hasXInput())
+ return;
+
+ for (uint32_t p = 0; p < MAX_GAMEPADS; p++)
+ {
+ if ((--disConnected[p]) == 0)
+ {
+ XINPUT_STATE inputState;
+ DWORD state = mpXInputGetState(p, &inputState);
+ if (state == ERROR_DEVICE_NOT_CONNECTED)
+ {
+ disConnected[p] = 4;
+ if (mGamePadConnected && (mConnectedPad == p))
+ {
+ mGamePadConnected = false;
+ mConnectedPad = 0;
+ for (uint32_t k = 0; k < MAX_GAMEPADS; k++)
+ {
+ XINPUT_STATE inputStateDisc;
+ DWORD stateDisc = mpXInputGetState(k, &inputStateDisc);
+ if (stateDisc == ERROR_SUCCESS)
+ {
+ mConnectedPad = k;
+ mGamePadConnected = true;
+ break;
+ }
+ }
+ }
+ }
+ else if (state == ERROR_SUCCESS)
+ {
+ if (!mGamePadConnected)
+ {
+ mGamePadConnected = true;
+ mConnectedPad = p;
+ }
+
+ disConnected[p] = 1; //force to test next time
+ XINPUT_CAPABILITIES caps;
+ mpXInputGetCapabilities(p, XINPUT_FLAG_GAMEPAD, &caps);
+
+ //gamepad
+ {
+ // Process buttons
+ const WORD lastWButtons = m_lastInputState[p].Gamepad.wButtons;
+ const WORD currWButtons = inputState.Gamepad.wButtons;
+
+ const WORD buttonsDown = currWButtons & ~lastWButtons;
+ const WORD buttonsUp = ~currWButtons & lastWButtons;
+ // const WORD buttonsHeld = currWButtons & lastWButtons;
+
+ for (int i = 0; i < 14; i++)
+ {
+ // order has to match struct GamepadControls
+ static const WORD buttonMasks[] = {
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT,
+ XINPUT_GAMEPAD_DPAD_RIGHT,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_BACK,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ };
+
+ if (buttonsDown & buttonMasks[i])
+ viewerScene.handleGamepadButton(i, true);
+ else if (buttonsUp & buttonMasks[i])
+ viewerScene.handleGamepadButton(i, false);
+ }
+
+ {
+ const BYTE newTriggerVal = inputState.Gamepad.bRightTrigger;
+ viewerScene.handleGamepadTrigger(GamepadTrigger::GAMEPAD_RIGHT_SHOULDER_TRIGGER, ((float)newTriggerVal) / 255);
+ }
+ {
+ const BYTE newTriggerVal = inputState.Gamepad.bLeftTrigger;
+ viewerScene.handleGamepadTrigger(GamepadTrigger::GAMEPAD_LEFT_SHOULDER_TRIGGER, ((float)newTriggerVal) / 255);
+ }
+ }
+
+ // Gamepad
+ const int axisData[] = { inputState.Gamepad.sThumbRX, inputState.Gamepad.sThumbRY, inputState.Gamepad.sThumbLX, inputState.Gamepad.sThumbLY };
+ for (uint32_t i = 0; i < MAX_GAMEPAD_AXES; i++)
+ {
+ if (axisData[i] != m_lastAxisData[p][i])
+ {
+ int data = axisData[i];
+ if (abs(data) < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
+ {
+ data = 0;
+ }
+ viewerScene.handleGamepadAxis(i, ((float)data) / SHRT_MAX);
+ }
+ m_lastAxisData[p][i] = axisData[i];
+ }
+ m_lastInputState[p] = inputState;
+ }
+ }
+ }
+
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.h b/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.h
new file mode 100644
index 00000000..4b19a13a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewerGamepad.h
@@ -0,0 +1,69 @@
+#ifndef SAMPLE_VIEWER_GAMEPAD_H
+#define SAMPLE_VIEWER_GAMEPAD_H
+
+#include <WTypes.h>
+#include <XInput.h>
+
+class SampleViewerScene;
+
+class SampleViewerGamepad
+{
+public:
+ enum GamepadTrigger
+ {
+ GAMEPAD_RIGHT_SHOULDER_TRIGGER = 0,
+ GAMEPAD_LEFT_SHOULDER_TRIGGER = 1
+ };
+
+ enum GamepadButtons
+ {
+ GAMEPAD_DPAD_UP = 0,
+ GAMEPAD_DPAD_DOWN,
+ GAMEPAD_DPAD_LEFT,
+ GAMEPAD_DPAD_RIGHT,
+ GAMEPAD_START,
+ GAMEPAD_BACK,
+ GAMEPAD_LEFT_THUMB,
+ GAMEPAD_RIGHT_THUMB,
+ GAMEPAD_Y,
+ GAMEPAD_A,
+ GAMEPAD_X,
+ GAMEPAD_B,
+ GAMEPAD_LEFT_SHOULDER,
+ GAMEPAD_RIGHT_SHOULDER
+ };
+
+ enum GamepadAxis
+ {
+ GAMEPAD_RIGHT_STICK_X = 0,
+ GAMEPAD_RIGHT_STICK_Y,
+ GAMEPAD_LEFT_STICK_X,
+ GAMEPAD_LEFT_STICK_Y
+ };
+
+ SampleViewerGamepad();
+ ~SampleViewerGamepad();
+
+ void init();
+ void release();
+
+ void processGamepads(SampleViewerScene& viewerScene);
+
+private:
+ bool hasXInput() const { return mpXInputGetState && mpXInputGetCapabilities; }
+
+private:
+
+ bool mGamePadConnected;
+ unsigned int mConnectedPad;
+
+ typedef DWORD(WINAPI *LPXINPUTGETSTATE)(DWORD, XINPUT_STATE*);
+ typedef DWORD(WINAPI *LPXINPUTGETCAPABILITIES)(DWORD, DWORD, XINPUT_CAPABILITIES*);
+
+ HMODULE mXInputLibrary;
+ LPXINPUTGETSTATE mpXInputGetState;
+ LPXINPUTGETCAPABILITIES mpXInputGetCapabilities;
+
+};
+
+#endif // SAMPLE_VIEWER_GAMEPAD_H
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewerScene.cpp b/KaplaDemo/samples/sampleViewer3/SampleViewerScene.cpp
new file mode 100644
index 00000000..0f95ae24
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewerScene.cpp
@@ -0,0 +1,106 @@
+#include "SampleViewerScene.h"
+#include "PxMaterial.h"
+#include "ShaderShadow.h"
+
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glut.h>
+
+
+#ifdef USE_OPTIX
+ SampleViewerScene::RenderType SampleViewerScene::mRenderType = SampleViewerScene::rtOPTIX;
+#else
+ SampleViewerScene::RenderType SampleViewerScene::mRenderType = SampleViewerScene::rtOPENGL;
+#endif
+
+OptixRenderer *SampleViewerScene::mOptixRenderer = NULL;
+
+bool SampleViewerScene::mBenchmark = false;
+
+//-----------------------------------------------------------------------------
+SampleViewerScene::SampleViewerScene(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor)
+{
+ mPxPhysics = pxPhysics;
+ mPxCooking = pxCooking;
+ mCameraPos = PxVec3(0.0f, 20.0f, 10.0f);
+ mCameraDir = PxVec3(0.0f, 0.0f, 1.0f);
+ mCameraUp = PxVec3(0.0f, 1.0f, 0.0f);
+ mCameraFov = 40.f;
+ mDefaultShader = defaultShader;
+ //printf("hhh = %s\n", resourcePath);
+ mResourcePath = resourcePath;
+ mSlowMotionFactor = slowMotionFactor;
+ mDefaultMaterial = pxPhysics->createMaterial(0.5f, 0.5f, 0.0f);
+ mCameraDisable = false;
+}
+
+//-----------------------------------------------------------------------------
+SampleViewerScene::~SampleViewerScene()
+{
+ for (int i = 0; i < (int)mShaders.size(); i++)
+ delete mShaders[i];
+ mShaders.clear();
+}
+
+// ----------------------------------------------------------------------------------------------
+void SampleViewerScene::getMouseRay(int xi, int yi, PxVec3 &orig, PxVec3 &dir)
+{
+ GLint viewPort[4];
+ GLdouble modelMatrix[16];
+ GLdouble projMatrix[16];
+ glGetIntegerv(GL_VIEWPORT, viewPort);
+ glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+
+ yi = viewPort[3] - yi - 1;
+ GLdouble x,y,z;
+ gluUnProject((GLdouble) xi, (GLdouble) yi, 0.0f,
+ modelMatrix, projMatrix, viewPort, &x, &y, &z);
+ orig = PxVec3((float)x, (float)y, (float)z);
+ gluUnProject((GLdouble) xi, (GLdouble) yi, 1.0f,
+ modelMatrix, projMatrix, viewPort, &x, &y, &z);
+ dir = PxVec3((float)x, (float)y, (float)z);
+ dir = dir - orig;
+ dir.normalize();
+ orig -= dir * 100.0f; // to catch ray casts
+}
+
+// ----------------------------------------------------------------------------------------------
+void SampleViewerScene::setMaterial(float restitution, float staticFriction, float dynamicFriction)
+{
+ mDefaultMaterial->setRestitution(restitution);
+ mDefaultMaterial->setStaticFriction(staticFriction);
+ mDefaultMaterial->setDynamicFriction(dynamicFriction);
+}
+
+// ----------------------------------------------------------------------------------------------
+void SampleViewerScene::render(bool useShader)
+{
+#ifdef USE_OPTIX
+ if (mRenderType == rtOPTIX && mOptixRenderer == NULL)
+ mOptixRenderer = new OptixRenderer( getRendererOptions() );
+#endif
+}
+
+// ----------------------------------------------------------------------------------------------
+void SampleViewerScene::cleanupStaticResources()
+{
+#ifdef USE_OPTIX
+ if( mOptixRenderer ) {
+ OptixRenderer* ren = mOptixRenderer;
+ mOptixRenderer = 0;
+ delete ren;
+ }
+#endif
+}
+
+// ----------------------------------------------------------------------------------------------
+std::string SampleViewerScene::mRendererOptions;
+
+void SampleViewerScene::setRendererOptions( const char* text )
+{
+ if( text ) mRendererOptions = text;
+ else mRendererOptions.clear();
+}
diff --git a/KaplaDemo/samples/sampleViewer3/SampleViewerScene.h b/KaplaDemo/samples/sampleViewer3/SampleViewerScene.h
new file mode 100644
index 00000000..b6653f1e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SampleViewerScene.h
@@ -0,0 +1,125 @@
+#ifndef SAMPLE_VIEWER_SCENE_H
+#define SAMPLE_VIEWER_SCENE_H
+
+#include "foundation/PxVec3.h"
+#include "foundation/PxTransform.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+
+using namespace physx;
+
+#include <vector>
+#include <string>
+
+class OptixRenderer;
+
+#ifdef USE_OPTIX
+#include "OptixRenderer.h"
+#endif
+
+class Shader;
+class ShaderShadow;
+
+// ---------------------------------------------------------------------
+class SampleViewerScene
+{
+public:
+ SampleViewerScene(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+ virtual ~SampleViewerScene();
+
+ // virtual interface
+
+ virtual void preSim(float dt) {};
+ virtual void postSim(float dt) {};
+ virtual void duringSim(float dt) {};
+ virtual void syncAsynchronousWork() {};
+
+ virtual void handleMouseButton(int button, int state, int x, int y) {};
+ virtual void handleMouseMotion(int x, int y) {};
+
+ virtual void handleKeyDown(unsigned char key, int x, int y) {};
+ virtual void handleKeyUp(unsigned char key, int x, int y) {};
+ virtual void handleSpecialKey(unsigned char key, int x, int y) {};
+
+ virtual void handleGamepadButton(int button, bool state) {};
+ virtual void handleGamepadAxis(int axis, float x) {};
+ virtual void handleGamepadTrigger(int trigger, float x) {};
+
+ virtual void render(bool useShader);
+ virtual void printPerfInfo() {}
+
+ virtual void setSlowMotionFactor(float factor) { mSlowMotionFactor = factor; }
+ virtual std::string getWeaponName() { return ""; };
+ virtual void customizeSceneDesc(PxSceneDesc& desc) {}
+
+ virtual void onInit(PxScene* pxScene){ mPxScene = pxScene; }
+
+ virtual void setScene(PxScene* pxScene) { mPxScene = pxScene; }
+
+ // common code
+
+ void setCamera(const PxVec3 &pos, const PxVec3 &dir, const PxVec3 &up, float fov ) {
+ mCameraPos = pos; mCameraDir = dir; mCameraUp = up; mCameraFov = fov;
+ }
+
+ virtual void getCamera(PxVec3& pos, PxVec3& dir){}
+ virtual bool isCameraDisable() { return mCameraDisable; }
+
+ virtual void getInitialCamera(PxVec3& pos, PxVec3& dir) { pos = PxVec3(0.f, 25.f, 30.f); dir = PxVec3(0.f, -0.3f, -1.f).getNormalized(); }
+
+ void getMouseRay(int xi, int yi, PxVec3 &orig, PxVec3 &dir);
+ std::vector<ShaderShadow*>& getShaders() { return mShaders; }
+
+ enum RenderType {
+ rtOPENGL,
+ rtOPTIX,
+ rtNUM,
+ };
+ static void setRenderType(RenderType renderType) { mRenderType = renderType; }
+ static void toggleRenderType() { setRenderType((RenderType)(((int)mRenderType+1)%rtNUM)); }
+ static RenderType getRenderType() { return mRenderType; }
+ static OptixRenderer* getOptixRenderer() { return mOptixRenderer; }
+
+ // Set option string for renderers.
+ static void setRendererOptions( const char* );
+ static const char* getRendererOptions() {return mRendererOptions.c_str();}
+
+ // Call this before exit().
+ static void cleanupStaticResources();
+ static void setBenchmark( bool on ) { mBenchmark = on; }
+ static bool isBenchmark() { return mBenchmark; }
+
+ virtual bool isSceneKapla() {return false;}
+
+
+ PxPhysics& getPhysics() { return *mPxPhysics; }
+ PxCooking& getCooking() { return *mPxCooking; }
+ PxScene& getScene() { return *mPxScene; }
+
+
+protected:
+ void setMaterial(float restitution = 0.2f, float staticFriction = 0.2f, float dynamicFriction = 0.2f);
+
+ PxPhysics *mPxPhysics;
+ PxCooking *mPxCooking;
+ PxScene *mPxScene;
+
+ PxMaterial *mDefaultMaterial;
+
+ PxVec3 mCameraPos, mCameraDir, mCameraUp;
+ float mCameraFov;
+ std::vector<ShaderShadow*> mShaders;
+ Shader *mDefaultShader;
+ const char *mResourcePath;
+ float mSlowMotionFactor;
+
+ static RenderType mRenderType;
+ static OptixRenderer *mOptixRenderer;
+ static bool mBenchmark;
+ static std::string mRendererOptions;
+
+ bool mCameraDisable;
+};
+
+#endif // SAMPLE_VIEWER_SCENE_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneCrab.cpp b/KaplaDemo/samples/sampleViewer3/SceneCrab.cpp
new file mode 100644
index 00000000..0b6370cc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneCrab.cpp
@@ -0,0 +1,189 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "PxPhysicsAPI.h"
+#include "extensions/PxExtensionsAPI.h"
+#include "SceneCrab.h"
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include <GL/glut.h>
+
+#include "PxTkStream.h"
+#include "PxTkFile.h"
+using namespace PxToolkit;
+// if enabled: runs the crab AI in sync, not as a parallel task to physx.
+#define DEBUG_RENDERING 0
+
+bool mSpawnActive = false;
+
+
+SceneCrab::SceneCrab(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
+ SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
+{
+
+ mNbCrabsX = 20;
+ mNbCrabsZ = 20;
+ mNbSuperCrabs = 2;
+}
+
+void SceneCrab::onInit(PxScene* pxScene)
+{
+ SceneKapla::onInit(pxScene);
+
+ mCrabManager.setSceneCrab(this);
+ mCrabManager.initialize(mNbCrabsX*mNbCrabsZ + mNbSuperCrabs);
+ createTerrain("terrain_ll2.bmp", "", 60.f, true);
+ const PxVec3 dims(0.08f, 0.25f, 1.0f);
+ PxMaterial* towerMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f);
+ ShaderMaterial mat;
+ mat.init();
+
+ PxFilterData queryData;
+ queryData.word0 = 128;
+
+ createCrabs();
+
+ createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(-25.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(-5.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(15.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(35.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ createCylindricalTower(48, 3.6f, 3.6f, 15, dims, PxVec3(55.f, -30.5f, -85.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ //createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-75.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ //createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-55.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ //createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(-35.f, -30.65f, -95.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);
+ /*createCylindricalTower(64, 3.6f, 3.6f, 15, dims, PxVec3(55.f, -1.10f, 55.f), towerMaterial, mat, PxFilterData(), queryData, 0.2f);*/
+
+}
+
+SceneCrab::~SceneCrab()
+{
+
+}
+
+void SceneCrab::setScene(PxScene* scene)
+{
+ SceneKapla::setScene(scene);
+ mCrabManager.setScene(scene);
+}
+
+void SceneCrab::createCrabs()
+{
+ PxVec3 startCrabPos(-75.f, 1.f, -75.f);
+
+ PxReal scale = 0.8f;
+ PxReal crabDepth = 2.0f;
+ PxReal legMass = 0.03f;
+
+ for (PxU32 i = 0; i < mNbCrabsX; ++i)
+ {
+ PxVec3 crabPos = startCrabPos + PxVec3(10.f*i, 0, 0);
+ for (PxU32 j = 0; j < mNbCrabsZ; ++j)
+ {
+ //const PxU32 index = i*mNbCrabsX + j;
+ crabPos.z += 10.f;
+ mCrabManager.createCrab(crabPos, crabDepth, scale, legMass, 4);
+ }
+
+ }
+
+ startCrabPos = PxVec3(-20.f, 1.f, -20.f);
+ crabDepth = 8.f;
+ legMass = 0.3f;
+ scale = 2.f;
+ for (PxU32 i = 0; i < mNbSuperCrabs; ++i)
+ {
+ PxVec3 crabPos = startCrabPos + PxVec3(-20.f*i, 0, -20.f*i);
+ //super crabs
+ mCrabManager.createCrab(crabPos, crabDepth, scale, legMass, 8);
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneCrab::duringSim(float dt)
+{
+ PxSceneWriteLock scopedLock(getScene());
+ mCrabManager.update(dt);
+}
+
+void SceneCrab::syncAsynchronousWork()
+{
+ mCrabManager.syncWork();
+}
+
+void SceneCrab::handleKeyDown(unsigned char key, int x, int y)
+{
+
+ if (key == 'k' || key == 'K')
+ {
+
+ if (!mSpawnActive)
+ {
+ mSpawnActive = true;
+ PxReal scale = 0.8f;
+ PxReal crabDepth = 2.0f;
+ PxReal legMass = 0.03f;
+
+ //Raycast against the static world to get a spawn position....
+
+ PxRaycastBuffer hit;
+
+ PxQueryFilterData fd; fd.flags |= PxQueryFlag::eSTATIC;
+
+ PxVec3 orig, dir;
+ getMouseRay(mMouseX, mMouseY, orig, dir);
+
+ if (mSimScene->getScene()->raycast(mCameraPos, dir, 1000.f, hit, PxHitFlags(PxHitFlag::eDEFAULT), fd))
+ {
+ //Spawn a walker...
+ for (PxU32 a = 0; a < 1; ++a)
+ {
+ for (PxU32 b = 0; b < 1; ++b)
+ {
+ mCrabManager.createCrab(hit.block.position + PxVec3(a*10.f, 0.f, b * 10.f), crabDepth, scale, legMass, 4);
+ }
+ }
+
+ }
+ }
+ }
+
+ SceneKapla::handleKeyDown(key, x, y);
+}
+
+void SceneCrab::handleKeyUp(unsigned char key, int x, int y)
+{
+ if (key == 'k' || key == 'K')
+ {
+ mSpawnActive = false;
+ }
+
+
+ SceneKapla::handleKeyUp(key, x, y);
+}
diff --git a/KaplaDemo/samples/sampleViewer3/SceneCrab.h b/KaplaDemo/samples/sampleViewer3/SceneCrab.h
new file mode 100644
index 00000000..cbe00d94
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneCrab.h
@@ -0,0 +1,80 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef SCENE_CRAB_H
+#define SCENE_CRAB_H
+
+#include "SceneKapla.h"
+#include "foundation/Px.h"
+#include "foundation/PxSimpleTypes.h"
+#include "common/PxPhysXCommonConfig.h"
+#include "task/PxTask.h"
+#include "CrabManager.h"
+#include <vector>
+
+
+namespace physx
+{
+ class PxRigidDynamic;
+ class PxRevoluteJoint;
+ class PxJoint;
+}
+
+class SceneCrab : public SceneKapla
+{
+public:
+ SceneCrab(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb, Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+ ~SceneCrab();
+
+
+
+ virtual void onInit(PxScene* pxScene);
+
+ virtual void setScene(PxScene* scene);
+
+ virtual void duringSim(float dt);
+ virtual void syncAsynchronousWork();
+
+ virtual void getInitialCamera(PxVec3& pos, PxVec3& dir) { pos = PxVec3(-70.f, -5.f, -70.f); dir = PxVec3(1.f, -0.3f, 1.f).getNormalized(); }
+
+ virtual void handleKeyDown(unsigned char key, int x, int y);
+ virtual void handleKeyUp(unsigned char key, int x, int y);
+
+private:
+ void createCrabs();
+
+private:
+
+ CrabManager mCrabManager;
+ PxU32 mNbCrabsX;
+ PxU32 mNbCrabsZ;
+ PxU32 mNbSuperCrabs;
+};
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/SceneCrabInputEventIds.h b/KaplaDemo/samples/sampleViewer3/SceneCrabInputEventIds.h
new file mode 100644
index 00000000..5d6c261e
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneCrabInputEventIds.h
@@ -0,0 +1,45 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+#ifndef SCENE_CRAB_INPUT_EVENT_IDS_H
+#define SCENE_CRAB_INPUT_EVENT_IDS_H
+
+
+// InputEvents used by SampleSubmarine
+enum SampleSubmarineInputEventIds
+{
+ CRAB_FORWARD,
+ CRAB_BACKWARD,
+ CRAB_LEFT,
+ CRAB_RIGHT,
+ CRAB_FORWARD_BACKWARD,
+ CRAB_LEFT_RIGHT,
+
+ CAMERA_SWITCH,
+ SCENE_RESET,
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKapla.cpp b/KaplaDemo/samples/sampleViewer3/SceneKapla.cpp
new file mode 100644
index 00000000..af34f254
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKapla.cpp
@@ -0,0 +1,930 @@
+#include "SceneKapla.h"
+#include "Convex.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxShape.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxMat44.h"
+
+#include <stdio.h>
+#include <GL/glut.h>
+
+#include "ShaderShadow.h"
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include "Mesh.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+
+#include "MathUtils.h"
+
+#include "PxRigidBodyExt.h"
+#include "MediaPath.h"
+
+#include "PxD6Joint.h"
+#include "PxScene.h"
+
+int numCylinderSeg = 30;
+extern bool gDrawGroundPlane;
+extern PxVec3 gGroupPlanePose;
+extern float gGroundY;
+SceneKapla::Weapon SceneKapla::mWeapon = wpBullet;
+
+std::vector<Compound*> meteors;
+
+
+
+extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL);
+
+// ----------------------------------------------------------------------------------------------
+SceneKapla::SceneKapla(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
+ SampleViewerScene(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor),
+ mDefaultContactOffset(0.02f), mDefaultRestOffset(0.0f)
+
+{
+ mShaders.clear();
+ mFrameNr = 0;
+ mWeaponLifeTime = 500; // frames
+ mLaserImpulse = 0.0f;
+ mWeaponImpulse = 5.0f;
+
+ float minConvexSize = 0.02f;
+ mMeteorDistance = 10.0f;
+ mMeteorVelocity = 20.0f;
+ mMeteorSize = 1.0f;
+
+ mSimScene = SimScene::createSimScene(pxPhysics, pxCooking, isGrb, minConvexSize, mDefaultMaterial, resourcePath);
+ mSimScene->setContactImpactRadius(0.0f);
+
+ ShaderShadow::SHADER3D_CHOICES shader3d = ShaderShadow::COMBINE;
+ ShaderShadow::PS_MODE psMode = ShaderShadow::PS_SHADE3D;
+
+ mSimSceneShader = new ShaderShadow(ShaderShadow::VS_TEXINSTANCE, psMode, shader3d);
+ mSimSceneShader->init();
+ mShaders.push_back(mSimSceneShader);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ // For asteroid
+ float bumpTextureUVScale = 0.1f;
+ float roughnessScale = 0.2f;
+ float extraNoiseScale = 2.0f;
+
+ LoadTexture("stoneBump.jpg", mat.texId, true);
+ mSimScene->setShaderMaterial(mSimSceneShader, mat);
+
+ mBulletMesh = PX_NEW(Mesh)();
+ mBulletMesh->loadFromObjFile(std::string(mResourcePath) + "\\bullet.obj");
+ mBulletMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), 0.6f);
+
+ mAsteroidMesh = PX_NEW(Mesh)();
+ mAsteroidMesh->loadFromObjFile(std::string(mResourcePath) + "\\asteroid.obj");
+
+
+
+ mGunActive = false;
+ mMouseX = 1024 / 2;
+ mMouseY = 768 / 2;
+ mMouseDown = false;
+
+ mPickQuadric = NULL;
+
+ mTerrain = NULL;
+ gDrawGroundPlane = false;
+
+ const PxVec3 dims(0.08f, 0.25f, 1.0f);
+
+ mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex0.jpg");
+ mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex1.jpg");
+ mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex2.jpg");
+ mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex3.jpg");
+ mSimScene->diffuseTexNames.push_back(std::string(mResourcePath) + "\\checker_tex4.jpg");
+
+ PxMaterial* DefaultMaterial = pxPhysics->createMaterial(0.4f, 0.15f, 0.1f);
+
+ mSimScene->setFractureForceThreshold(PX_MAX_F32);
+
+ mAsteroidMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), mMeteorSize);
+
+
+ debugDrawNumConvexes = 0;
+ mSimScene->createRenderBuffers();
+
+}
+
+void SceneKapla::onInit(PxScene* pxScene)
+{
+ SampleViewerScene::onInit(pxScene);
+ mSimScene->setScene(pxScene);
+}
+
+void SceneKapla::setScene(PxScene* pxScene)
+{
+ SampleViewerScene::setScene(pxScene); mSimScene->setScene(pxScene);
+}
+
+void SceneKapla::createGroundPlane(PxFilterData simFilterData, PxVec3 pose, PxFilterData queryFilterData)
+{
+ // ground plane
+ PxRigidStatic* groundPlane = PxCreatePlane(*mPxPhysics, PxPlane(0, 1.f, 0, 0.f), *mDefaultMaterial);
+
+ gGroupPlanePose =pose;
+ PxTransform transform(gGroupPlanePose, groundPlane->getGlobalPose().q);
+ groundPlane->setGlobalPose(transform);
+
+
+ PxShape * groundShape;
+ groundPlane->getShapes(&groundShape, 1);
+ groundShape->setSimulationFilterData(simFilterData);
+ //groundShape->setContactOffset(mDefaultContactOffset);
+ //groundShape->setRestOffset(mDefaultRestOffset);
+
+ groundShape->setQueryFilterData(queryFilterData);
+
+
+ mPxScene->addActor(*groundPlane);
+
+ gDrawGroundPlane = true;
+}
+
+void SceneKapla::createTerrain(const char* terrainName, const char* textureName, PxReal maxHeight, bool invert)
+{
+ string fullTerrainName = FindMediaFile(terrainName, mResourcePath);
+ string fullTerrainTexName = (strcmp(textureName, "") == 0) ? textureName:FindMediaFile(textureName, mResourcePath);
+
+ mTerrain = new TerrainMesh(getPhysics(), getCooking(), getScene(), *mDefaultMaterial, PxVec3(-1.0f, -30.85f, -1.0f), fullTerrainName.c_str(),
+ fullTerrainTexName.c_str(), 10.f, maxHeight, mDefaultShader, invert);
+}
+
+static void configD6Joint(PxReal swing0, PxReal swing1, PxReal twistLo, PxReal twistHi, PxD6Joint* joint)
+{
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLIMITED);
+
+ joint->setSwingLimit(PxJointLimitCone(swing0, swing1));
+ joint->setTwistLimit(PxJointAngularLimitPair(twistLo, twistHi));
+}
+
+static void finishBody(PxRigidDynamic* dyn, PxReal density, PxReal inertiaScale)
+{
+ dyn->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ dyn->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*dyn, density);
+ dyn->setMassSpaceInertiaTensor(dyn->getMassSpaceInertiaTensor() * inertiaScale);
+ dyn->setAngularDamping(0.15f);
+}
+
+void SceneKapla::createRagdoll(PxVec3 pos, PxVec3 vel, ShaderMaterial& mat)
+{
+
+ PxVec3 tempVel = vel;
+ vel = vel * 0.75f;
+
+ PxReal density = 4.f;
+ //Head (a sphere)
+
+ PxPhysics* physics = getSimScene()->getPxPhysics();
+
+ mSimScene->getCompoundCreator()->createSphere(PxVec3(0.4f), 4); //Spheres defined by dims - not radius!
+
+ Compound* head = createObject(PxTransform(pos + PxVec3(0.f, 0.9f, 0.f)), vel, PxVec3(0), false, mat);
+
+ mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.25f, 10);
+
+ Compound* neck = createObject(PxTransform(pos + PxVec3(0.f, 0.65f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ PxRigidDynamic* headBody = head->getPxActor();
+ PxRigidDynamic* neckBody = neck->getPxActor();
+
+ finishBody(headBody, density, 4.f);
+ finishBody(neckBody, density, 4.f);
+
+ PxD6Joint *neckJoint = PxD6JointCreate(*physics, headBody,
+ headBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.75f, -0.05f))), neckBody, neckBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.75f, -0.05f))));
+
+ configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14f / 8.f, 3.14f / 8.f, neckJoint);
+
+ mSimScene->getCompoundCreator()->createCylinder(0.25f, 0.55f, 10);
+
+ Compound* upperTorso = createObject(PxTransform(pos + PxVec3(0.f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
+
+ mSimScene->getCompoundCreator()->createCylinder(0.2f, 0.45f, 10);
+
+ Compound* lowerTorso = createObject(PxTransform(pos + PxVec3(0.f, 0.075f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
+
+ Compound* hips = createObject(PxTransform(pos + PxVec3(0.f, -0.225f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), tempVel, PxVec3(0), false, mat);
+
+
+ finishBody(upperTorso->getPxActor(), density, 4.f);
+ finishBody(lowerTorso->getPxActor(), density, 4.f);
+ finishBody(hips->getPxActor(), density, 4.f);
+
+
+ PxD6Joint *neckTorsoJoint = PxD6JointCreate(*physics, neckBody,
+ neckBody->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.6f, -0.05f))), upperTorso->getPxActor(), upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.6f, -0.05f))));
+
+ configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14f / 8.f, 3.14f / 8.f, neckTorsoJoint);
+
+ PxD6Joint *TorsoTorsoJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
+ upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.25f, -0.1f))), lowerTorso->getPxActor(),
+ lowerTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, 0.25f, -0.1f))));
+
+ configD6Joint(3.14 / 4.f, 3.14f / 4.f, -3.14f / 4.f, 3.14f / 4.f, neckTorsoJoint);
+
+ PxD6Joint *hipTorsoJoint = PxD6JointCreate(*physics, lowerTorso->getPxActor(),
+ lowerTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, -0.1f, -0.1f))), hips->getPxActor(),
+ hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.f, -0.1f, -0.1f))));
+
+ configD6Joint(3.14 / 4.f, 3.14f / 4.f, -3.14f / 4.f, 3.14f / 4.f, neckTorsoJoint);
+
+ mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.55f, 10);
+
+ Compound* leftShoulder = createObject(PxTransform(pos + PxVec3(-0.48f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+ Compound* rightShoulder = createObject(PxTransform(pos + PxVec3(0.48f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ finishBody(leftShoulder->getPxActor(), density, 4.f);
+ finishBody(rightShoulder->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftShoulderJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
+ upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.28f, 0.375f, 0.f))),
+ leftShoulder->getPxActor(), leftShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.28f, 0.375f, 0.f))));
+
+ configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, leftShoulderJoint);
+
+ PxD6Joint *rightShoulderJoint = PxD6JointCreate(*physics, upperTorso->getPxActor(),
+ upperTorso->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.28f, 0.375f, -0.f))),
+ rightShoulder->getPxActor(), rightShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.28f, 0.375f, -0.f))));
+
+ configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, rightShoulderJoint);
+
+ Compound* leftForearm = createObject(PxTransform(pos + PxVec3(-0.88f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+ Compound* rightForearm = createObject(PxTransform(pos + PxVec3(0.88f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ finishBody(leftForearm->getPxActor(), density, 4.f);
+ finishBody(rightForearm->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftElbowJoint = PxD6JointCreate(*physics, leftShoulder->getPxActor(),
+ leftShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.68f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ leftForearm->getPxActor(), leftForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.68f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, leftElbowJoint);
+
+ PxD6Joint *rightElbowJoint = PxD6JointCreate(*physics, rightShoulder->getPxActor(),
+ rightShoulder->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.68f, 0.375f, -0.f), PxQuat(3.141592f/2.f, PxVec3(0.f, 1.f, 0.f)))),
+ rightForearm->getPxActor(), rightForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.68f, 0.375f, -0.f), PxQuat(3.141592f/2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, rightElbowJoint);
+
+ mSimScene->getCompoundCreator()->createBox(PxVec3(0.2f, 0.05f, 0.2f));
+
+ Compound* leftHand = createObject(PxTransform(pos + PxVec3(-1.18f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+ Compound* rightHand = createObject(PxTransform(pos + PxVec3(1.18f, 0.375f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(0.f, 1.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ finishBody(leftHand->getPxActor(), density, 4.f);
+ finishBody(rightHand->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftWristJoint = PxD6JointCreate(*physics, leftForearm->getPxActor(),
+ leftForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-1.13f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ leftHand->getPxActor(), leftHand->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-1.13f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14 / 2.f, 3.14f / 2.f, leftWristJoint);
+
+ PxD6Joint *rightWristJoint = PxD6JointCreate(*physics, rightForearm->getPxActor(),
+ rightForearm->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(1.13f, 0.375f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ rightHand->getPxActor(), rightHand->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(1.13f, 0.375f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 8.f, 3.14f / 8.f, -3.14 / 2.f, 3.14f / 2.f, rightWristJoint);
+
+
+ mSimScene->getCompoundCreator()->createCylinder(0.125f, 0.7f, 10);
+
+ Compound* leftThigh = createObject(PxTransform(pos + PxVec3(-0.15f, -0.7f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
+ Compound* rightThigh = createObject(PxTransform(pos + PxVec3(0.15f, -0.7f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ finishBody(leftThigh->getPxActor(), density, 4.f);
+ finishBody(rightThigh->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftHipJoint = PxD6JointCreate(*physics, hips->getPxActor(),
+ hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -0.4f, 0.f))),
+ leftThigh->getPxActor(), leftThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -0.4f, 0.f))));
+
+ configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, leftHipJoint);
+
+ PxD6Joint *rightHipJoint = PxD6JointCreate(*physics, hips->getPxActor(),
+ hips->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -0.4f, 0.f))),
+ rightThigh->getPxActor(), rightThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -0.4f, 0.f))));
+
+ configD6Joint(3.14 / 2.5f, 3.14f / 2.5f, -3.14f / 2.5f, 3.14f / 2.5f, rightHipJoint);
+
+ mSimScene->getCompoundCreator()->createCylinder(0.1f, 0.7f, 10);
+
+ Compound* leftShin = createObject(PxTransform(pos + PxVec3(-0.15f, -1.3f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
+ Compound* rightShin = createObject(PxTransform(pos + PxVec3(0.15f, -1.3f, 0.f), PxQuat(3.14159 / 2.f, PxVec3(1.f, 0.f, 0.f))), vel, PxVec3(0), false, mat);
+
+ finishBody(leftShin->getPxActor(), density, 4.f);
+ finishBody(rightShin->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftKneeJoint = PxD6JointCreate(*physics, leftThigh->getPxActor(),
+ leftThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ leftShin->getPxActor(), leftShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, leftKneeJoint);
+
+ PxD6Joint *rightKneeJoint = PxD6JointCreate(*physics, rightThigh->getPxActor(),
+ rightThigh->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ rightShin->getPxActor(), rightShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 2.5f, rightKneeJoint);
+
+ mSimScene->getCompoundCreator()->createBox(PxVec3(0.2f, 0.1f, 0.4f));
+
+ Compound* leftFoot = createObject(PxTransform(pos + PxVec3(-0.15f, -1.65f, 0.15f)), vel, PxVec3(0), false, mat);
+ Compound* rightFoot = createObject(PxTransform(pos + PxVec3(0.15f, -1.65f, 0.15f)), vel, PxVec3(0), false, mat);
+
+ finishBody(leftFoot->getPxActor(), density, 4.f);
+ finishBody(rightFoot->getPxActor(), density, 4.f);
+
+ PxD6Joint *leftAnkle = PxD6JointCreate(*physics, leftShin->getPxActor(),
+ leftShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.6f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ leftFoot->getPxActor(), leftFoot->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(-0.15f, -1.6f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 8.f, leftAnkle);
+
+ PxD6Joint *rightAnkle = PxD6JointCreate(*physics, rightShin->getPxActor(),
+ rightShin->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.6f, 0.0f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))),
+ rightFoot->getPxActor(), rightFoot->getPxActor()->getGlobalPose().transformInv(PxTransform(pos + PxVec3(0.15f, -1.6f, 0.f), PxQuat(3.141592f / 2.f, PxVec3(0.f, 1.f, 0.f)))));
+
+ configD6Joint(3.14 / 16.f, 3.14f / 16.f, -3.14 / 16.f, 3.14f / 8.f, rightAnkle);
+
+
+}
+
+void SceneKapla::createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat,
+ PxFilterData& simFilterData, PxFilterData& queryFilterData, PxReal density, bool bUseSweeps, bool bStartAsleep)
+{
+
+
+
+ PxShape* shape;
+ PxVec3 vel(0), omega(0);
+
+ mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
+
+ PxReal startHeight = 0.f;
+
+ PxTransform objectTransform(PxVec3(3.172 - 2.3 - 39.87), PxQuat());
+
+ for (PxU32 i = 0; i < height; ++i)
+ {
+ PxReal radius = minRadius + (maxRadius - minRadius) * (1.f - PxReal(i) / PxReal(height));
+ for (PxU32 a = 0; a < nbRadialPoints; ++a)
+ {
+ PxF32 angle = 6.28f*PxF32(a) / PxF32(nbRadialPoints);
+ PxVec3 innerPos(cosf(angle)*radius, dims.y + startHeight, sinf(angle)*radius);
+
+ PxQuat rot(3.14 / 2.f - angle, PxVec3(0.f, 1.f, 0.f));
+
+ PxTransform transform(innerPos + centerPos, rot);
+
+
+ Compound* compound = createObject(transform, vel, omega, false, mat);
+ PxRigidDynamic* innerBox = compound->getPxActor();
+ innerBox->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+ shape->setQueryFilterData(queryFilterData);
+ shape->setSimulationFilterData(simFilterData);
+
+
+
+
+ innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ innerBox->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
+ innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
+
+ if (bStartAsleep)
+ innerBox->putToSleep();
+
+ }
+
+ PxReal innerCircumference = (radius - (dims.z - dims.x)) * 3.1415928 * 2.f;
+ PxReal midCircumference = (radius)* 3.1415928 * 2.f;
+ PxReal outerCircumference = (radius + (dims.z - dims.x)) * 3.1415928 * 2.f;
+
+ PxU32 nbInnerSlabs = innerCircumference / (dims.z * 2);
+ PxU32 nbMidSlabs = midCircumference / (dims.z * 2);
+ PxU32 nbOuterSlabs = outerCircumference / (dims.z * 2);
+
+
+ for (PxU32 a = 0; a < nbInnerSlabs; a++)
+ {
+ PxF32 angle = 6.28f*PxF32(a) / PxF32(nbInnerSlabs);
+
+ PxVec3 innerPos(cosf(angle)*(radius - (dims.z - dims.x)), 3.f * dims.y + startHeight, sinf(angle)*(radius - (dims.z - dims.x)));
+
+ PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
+
+ Compound* compound = createObject(PxTransform(innerPos + centerPos, rot), vel, omega, false, mat);
+ PxRigidDynamic* innerBox = compound->getPxActor();
+ innerBox->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ shape->setQueryFilterData(queryFilterData);
+ shape->setSimulationFilterData(simFilterData);
+
+ innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ innerBox->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
+ innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
+
+ if (bStartAsleep)
+ innerBox->putToSleep();
+ }
+
+ for (PxU32 a = 0; a < nbMidSlabs; a++)
+ {
+ PxF32 angle = 6.28f*PxF32(a) / PxF32(nbMidSlabs);
+ PxVec3 innerPos(cosf(angle)*(radius), 3.f * dims.y + startHeight, sinf(angle)*(radius));
+
+ PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
+
+ Compound* compound = createObject(PxTransform(innerPos + centerPos, rot), vel, omega, false, mat);
+ PxRigidDynamic* innerBox = compound->getPxActor();
+ innerBox->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ shape->setQueryFilterData(queryFilterData);
+ shape->setSimulationFilterData(simFilterData);
+
+ innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ innerBox->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
+ innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
+
+ if (bStartAsleep)
+ innerBox->putToSleep();
+ }
+
+ for (PxU32 a = 0; a < nbOuterSlabs; a++)
+ {
+ PxF32 angle = 6.28f*PxF32(a) / PxF32(nbOuterSlabs);
+ PxVec3 outerPos(cosf(angle)*(radius + (dims.z - dims.x)), 3.f * dims.y + startHeight, sinf(angle)*(radius + (dims.z - dims.x)));
+
+ PxQuat rot(-angle, PxVec3(0.f, 1.f, 0.f));
+
+ Compound* compound = createObject(PxTransform(outerPos + centerPos, rot), vel, omega, false, mat);
+ PxRigidDynamic* outerBox = compound->getPxActor();
+ outerBox->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ shape->setQueryFilterData(queryFilterData);
+ shape->setSimulationFilterData(simFilterData);
+
+ outerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ outerBox->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*outerBox, density);
+ outerBox->setMassSpaceInertiaTensor(outerBox->getMassSpaceInertiaTensor() * 4.f);
+
+ if (bStartAsleep)
+ outerBox->putToSleep();
+ }
+
+ startHeight += 4.f * dims.y;
+ density *= 0.975f;
+ }
+
+ //Now place the lid on the structure...
+
+ PxReal midCircumference = (minRadius - dims.z) * 3.1415928 * 2.f;
+
+ PxU32 nbMidSlabs = midCircumference / (dims.y * 2);
+
+ PxQuat baseRotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
+
+ for (PxU32 a = 0; a < nbMidSlabs; ++a)
+ {
+ const PxF32 angle = 6.28f*PxF32(a) / PxF32(nbMidSlabs);
+ PxVec3 innerPos(cosf(angle)*minRadius, dims.x + startHeight, sinf(angle)*minRadius);
+
+ PxQuat rot(3.14 / 2.f - angle, PxVec3(0.f, 1.f, 0.f));
+
+ Compound* compound = createObject(PxTransform(innerPos + centerPos, rot*baseRotation), vel, omega, false, mat);
+ PxRigidDynamic* innerBox = compound->getPxActor();
+ innerBox->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ shape->setQueryFilterData(queryFilterData);
+ shape->setSimulationFilterData(simFilterData);
+
+ innerBox->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ innerBox->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*innerBox, density);
+ innerBox->setMassSpaceInertiaTensor(innerBox->getMassSpaceInertiaTensor() * 4.f);
+
+ if (bStartAsleep)
+ innerBox->putToSleep();
+ }
+
+}
+
+
+
+
+// ----------------------------------------------------------------------------------------------
+std::string SceneKapla::getWeaponName()
+{
+ switch (mWeapon) {
+ case wpBullet : return "Bullet";
+ case wpBall : return "Ball";
+ case wpMeteor : return "Meteor";
+ }
+ return "";
+}
+
+// ----------------------------------------------------------------------------------------------
+Compound* SceneKapla::createObject(const PxVec3 &pos, const PxVec3 &vel, const PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader, int matID, int surfMatID)
+{
+ Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
+
+ PxTransform pose(pos);
+ cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, shader, matID, surfMatID);
+ cp->setShader(shader ? shader : mSimSceneShader, mat);
+ mSimScene->addCompound(cp);
+
+
+ return cp;
+}
+
+Compound* SceneKapla::createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern, ShaderShadow* shader, int matID, int surfMatID)
+{
+ Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
+
+ ShaderShadow* myShader = shader ? shader : mSimSceneShader;
+
+ cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, myShader, matID, surfMatID);
+ cp->setShader(shader ? shader : mSimSceneShader, mat);
+ mSimScene->addCompound(cp);
+ return cp;
+}
+
+Compound* SceneKapla::createObject(PxRigidDynamic* body, const ShaderMaterial &mat, ShaderShadow* shader, int matID, int surfMatID)
+{
+ Compound *cp = (Compound*)mSimScene->createCompound(mDefaultContactOffset, mDefaultRestOffset);
+
+ ShaderShadow* myShader = shader ? shader : mSimSceneShader;
+ cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), body, myShader, matID, surfMatID);
+ cp->setShader(shader ? shader : mSimSceneShader, mat);
+ mSimScene->addCompound(cp);
+ return cp;
+}
+// ----------------------------------------------------------------------------------------------
+SceneKapla::~SceneKapla()
+{
+ if (mTerrain) delete mTerrain;
+ mTerrain = NULL;
+ if (mSimScene != NULL)
+ delete mSimScene;
+
+ if (mPickQuadric != NULL)
+ gluDeleteQuadric(mPickQuadric);
+
+ if (mBulletMesh)
+ delete mBulletMesh;
+
+ if (mAsteroidMesh)
+ delete mAsteroidMesh;
+
+ meteors.clear();
+}
+
+// ----------------------------------------------------------------------------------------------
+
+void SceneKapla::preSim(float dt)
+{
+ if (mSimScene)
+ mSimScene->preSim(dt);
+
+ if (meteors.size() > 0)
+ {
+ /*static vector<PxVec3> sites;
+ sites.clear();*/
+
+ int num = 0;
+ const int numSamples = 20;
+ for (int i = 0; i < (int)meteors.size(); i++)
+ {
+ if (meteors[i]->getLifeFrames() > 1 && meteors[i]->getPxActor() != NULL)
+ {
+ meteors[num] = meteors[i];
+ num++;
+ }
+ }
+ meteors.resize(num);
+ }
+
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::postSim(float dt)
+{
+ if (mSimScene)
+ mSimScene->postSim(dt, NULL);
+
+ mFrameNr++;
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::handleMouseButton(int button, int state, int x, int y)
+{
+ mMouseX = x;
+ mMouseY = y;
+
+ mMouseDown = (state == GLUT_DOWN);
+
+ PxVec3 orig, dir;
+ getMouseRay(x,y, orig, dir);
+
+ if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+ if (mSimScene)
+ mSimScene->pickStart(orig, dir);
+ }
+ }
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ if (mSimScene)
+ mSimScene->pickRelease();
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::handleMouseMotion(int x, int y)
+{
+ mMouseX = x;
+ mMouseY = y;
+
+ if (mSimScene && mSimScene->getPickActor() != NULL) {
+ PxVec3 orig, dir;
+ getMouseRay(x,y, orig, dir);
+ mSimScene->pickMove(orig, dir);
+ }
+}
+//ofstream orays("ray.txt");
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::handleKeyDown(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case ' ':
+ {
+ if (!mGunActive)
+ {
+ float vel = 1.0f;
+ PxVec3 orig, dir;
+ getMouseRay(mMouseX, mMouseY, orig, dir);
+ /*
+ float sx = 0.0f, sy = 30.0f, sz = 0.0f;
+ int nx = 10;
+ int ny = 10;
+ float dx = 1.0f;
+ for (int i = 0; i < ny; i++) {
+ for (int j = 0; j < nx; j++) {
+ shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f));
+ }
+ }
+
+ */
+ shoot(mCameraPos, dir);
+ }
+ mGunActive = true;
+ //orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n";
+ //orays.flush();
+ //printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z);
+ break;
+ }
+ /*
+ case 'j':
+ {
+ mSimScene->dumpSceneGeometry();
+ break;
+ }
+ */
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::handleKeyUp(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case 'v':
+ if (mSimScene) mSimScene->toggleDebugDrawing(); break;
+ case ' ':
+ {
+ mGunActive = false;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::handleSpecialKey(unsigned char key, int x, int y)
+{
+ switch (key)
+ {
+ case GLUT_KEY_F4: mWeapon = (Weapon)(((int)mWeapon+1)%numWeapons); break;
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::shoot(PxVec3 &orig, PxVec3 &dir)
+{
+ if (mSimScene == NULL)
+ return;
+
+ mGunActive = true;
+ if (mWeapon == wpBall || mWeapon == wpBullet || mWeapon == wpMeteor) {
+ PxVec3 dims(0.4f, 0.4f, 0.4f);
+ Compound* cp = (Compound*)mSimScene->createCompound( mDefaultContactOffset, mDefaultRestOffset); // invincible
+ PxTransform pose = PX_TRANSFORM_ID;
+ PxVec3 vel, omega;
+ omega = PxVec3(0.0f, 0.0f, 0.0f);
+ if (mWeapon == wpMeteor)
+ {
+ float idist = 1000.f;
+
+ PxRaycastBuffer buffer;
+ if (getScene().raycast(orig, dir, idist, buffer, PxHitFlag::eDEFAULT, PxQueryFilterData(PxQueryFlag::eDYNAMIC)))
+ idist = buffer.getAnyHit(0).distance;
+
+ PxVec3 impactPos = orig + dir*idist;
+
+ PxVec3 cameraRight = mCameraDir.cross(mCameraUp);
+ const float angle = 45.0f * physx::PxPi / 180.0f;
+ const float distance = mMeteorDistance;
+ PxVec3 meteorDirection = cos(angle)*cameraRight + sin(angle)*mCameraUp;
+ pose.p = impactPos + meteorDirection*distance;
+ vel = -meteorDirection*mMeteorVelocity* mSlowMotionFactor;
+ }
+ else
+ {
+ {
+ pose.p = mCameraPos;
+ PxVec3 a0;
+ if (fabs(dir.x) < fabs(dir.y) && fabs(dir.x) < fabs(dir.z))
+ a0 = PxVec3(1.0f, 0.0f, 0.0f);
+ else if (fabs(dir.y) < fabs(dir.z))
+ a0 = PxVec3(0.f, 1.0f, 0.0f);
+ else
+ a0 = PxVec3(0.0f, 0.0f, 1.0f);
+ PxVec3 a1 = dir.cross(a0);
+ a1.normalize();
+ a0 = a1.cross(dir);
+ pose.q = PxQuat(PxMat33(a1, dir, a0));
+ float dist = 1000.0f;
+
+ vel = orig + dir * dist - mCameraPos;
+ vel.normalize();
+ }
+ vel *= 30.0f * mSlowMotionFactor;
+ }
+
+ //vel *= 0.0f;
+ ShaderMaterial mat;
+ mat.init();
+ mat.color[0] = 0.9f;
+ mat.color[1] = 0.2f;
+ mat.color[2] = 0.2f;
+ cp->setShader(NULL, mat);
+
+ if (mWeapon == wpMeteor)
+ {
+
+ vel *= 2.0f;
+ PxVec3 a0;
+ PxVec3 dir = vel;
+ dir.normalize();
+ if (fabs(dir.x) < fabs(dir.y) && fabs(dir.x) < fabs(dir.z))
+ a0 = PxVec3(1.0f, 0.0f, 0.0f);
+ else if (fabs(dir.y) < fabs(dir.z))
+ a0 = PxVec3(0.f, 1.0f, 0.0f);
+ else
+ a0 = PxVec3(0.0f, 0.0f, 1.0f);
+ PxVec3 a1 = dir.cross(a0);
+ a1.normalize();
+ a0 = a1.cross(dir);
+ pose.q = PxQuat(PxMat33(dir, a0, a1)).getNormalized();
+
+ const float maxRot = 50.0f;
+ omega = PxVec3(randRange(-maxRot, maxRot),randRange(-maxRot, maxRot),randRange(-maxRot, maxRot));
+
+ mAsteroidMesh->normalize(PxVec3(0.0f, 0.0f, 0.0f), mMeteorSize);
+ cp->createFromMesh(mAsteroidMesh, pose, vel, omega);
+ cp->getPxActor()->setMass(10000000.0f);
+ cp->getPxActor()->setMaxContactImpulse(2.5f);
+ cp->getPxActor()->setMaxDepenetrationVelocity(1.f);
+
+ cp->setKinematic(vel);
+ cp->setLifeFrames(mWeaponLifeTime);
+ cp->setAdditionalImpactImpulse(mWeaponImpulse, mWeaponImpulse);
+
+ meteors.push_back(cp);
+ }
+ else if (mWeapon == wpBall)
+ {
+ mSimScene->getCompoundCreator()->createSphere(dims, 8);
+ cp->createFromGeometry(mSimScene->getCompoundCreator()->getGeometry(), pose, vel, omega, NULL);
+ PxRigidBodyExt::updateMassAndInertia(*cp->getPxActor(), 1000.f);
+ cp->getPxActor()->setAngularDamping(0.75f);
+ }
+ else
+ {
+ cp->createFromMesh(mBulletMesh, pose, vel, omega);
+ cp->setKinematic(vel);
+ cp->setLifeFrames(mWeaponLifeTime);
+ cp->setAdditionalImpactImpulse(mWeaponImpulse, mWeaponImpulse);
+ }
+
+
+
+ mSimScene->addCompound(cp);
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKapla::render(bool useShader)
+{
+ SampleViewerScene::render(useShader);
+
+ if (mSimScene != NULL) {
+ mSimScene->setCamera( mCameraPos, mCameraDir, mCameraUp, mCameraFov );
+ mSimScene->draw(useShader);
+ }
+
+ if (useShader && mTerrain) {
+ mTerrain->draw(useShader);
+
+ }
+
+ pickDraw();
+ //if (useShader)
+ //renderCrossLines();
+
+// mFracPattern.getGeometry().debugDraw();
+}
+
+//-----------------------------------------------------------------------------
+void SceneKapla::pickDraw()
+{
+ if (mSimScene && mSimScene->getPickActor() == NULL)
+ return;
+
+ PxRigidDynamic *pickActor = mSimScene->getPickActor();
+
+ float r = 0.05f;
+
+ if (mPickQuadric == NULL) {
+ mPickQuadric = gluNewQuadric();
+ gluQuadricDrawStyle(mPickQuadric, GLU_FILL);
+ }
+
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ const PxVec3 &pickPos = mSimScene->getPickPos();
+ glTranslatef(pickPos.x, pickPos.y, pickPos.z);
+ gluSphere(mPickQuadric, r, 10, 10);
+ glPopMatrix();
+
+ PxVec3 pos = pickActor->getGlobalPose().transform(mSimScene->getPickLocalPos());
+
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glTranslatef(pos.x, pos.y, pos.z);
+ gluSphere(mPickQuadric, r, 10, 10);
+ glPopMatrix();
+
+ glBegin(GL_LINES);
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glVertex3f(pickPos.x, pickPos.y, pickPos.z);
+ glColor3f(1.0f, 0.0f, 0.0f);
+ glVertex3f(pos.x, pos.y, pos.z);
+ glEnd();
+
+ glColor3f(1, 1, 1);
+
+}
+
+//-----------------------------------------------------------------------------
+void SceneKapla::printPerfInfo()
+{
+ if (mSimScene != NULL) {
+ printf("num SDK bodies %i\n", mSimScene->getCompounds().size());
+ /* if(mSimScene->getParticles())
+ printf("num particles %i\n", mSimScene->getParticles()->getNumParticles());*/
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKapla.h b/KaplaDemo/samples/sampleViewer3/SceneKapla.h
new file mode 100644
index 00000000..836f6f62
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKapla.h
@@ -0,0 +1,122 @@
+#ifndef SCENE_FRACTURE_H
+#define SCENE_FRACTURE_H
+
+
+#include "SampleViewerScene.h"
+#include "Compound.h"
+#include "Shader.h"
+
+#include "foundation/PxVec3.h"
+
+#include "PhysXMacros.h"
+#include "PxFiltering.h"
+
+extern int DEFAULT_SOLVER_ITERATIONS;
+
+using namespace physx;
+
+class GLUquadric;
+class Particles;
+class ShaderShadow;
+class SimScene;
+class Mesh;
+class RegularCell3D;
+class TerrainMesh;
+
+// ---------------------------------------------------------------------
+class SceneKapla : public SampleViewerScene
+{
+public:
+ SceneKapla(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+
+ virtual ~SceneKapla();
+
+ virtual void preSim(float dt);
+ virtual void postSim(float dt);
+
+ virtual void handleMouseButton(int button, int state, int x, int y);
+ virtual void handleMouseMotion(int x, int y);
+
+ virtual void handleKeyDown(unsigned char key, int x, int y);
+ virtual void handleKeyUp(unsigned char key, int x, int y);
+ virtual void handleSpecialKey(unsigned char key, int x, int y);
+
+ virtual void render(bool useShader);
+ virtual void printPerfInfo();
+ SimScene* getSimScene() {return mSimScene;}
+
+ ShaderShadow* getSimSceneShader() {return mSimSceneShader;}
+
+ virtual std::string getWeaponName();
+
+ virtual bool isSceneKapla() {return true;}
+
+ void shoot(PxVec3 &orig, PxVec3 &dir);
+
+ void createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat,
+ PxFilterData& simFilterData, PxFilterData& queryFilterData, PxReal density = 1.f, const bool useSweep = false, bool startAsleep = false);
+ void createWall(PxReal radius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat, PxFilterData& simFilterData, PxFilterData& queryFilterData,
+ PxReal density = 1.f);
+ void createGroundPlane(PxFilterData simFilterData = PxFilterData(), PxVec3 pose = PxVec3(0,0,0), PxFilterData queryFilterData = PxFilterData());
+ void createTerrain(const char* terrainName, const char* textureName, PxReal maxHeight = 30.f, bool invert = false);
+
+ void createRagdoll(PxVec3 pos, PxVec3 vel, ShaderMaterial& mat);
+
+ virtual void onInit(PxScene* pxScene);
+
+ virtual void setScene(PxScene* pxScene);
+
+ ShaderShadow* mSimSceneShader;
+
+ Compound* createObject(const PxVec3 &pos, const PxVec3 &vel, const PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
+
+ Compound* createObject(const PxTransform &pose, const PxVec3 &vel, const PxVec3 &omega,
+ bool particles, const ShaderMaterial &mat, bool useSecondaryPattern = false, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
+
+ Compound* createObject(PxRigidDynamic* body, const ShaderMaterial &mat, ShaderShadow* shader = NULL, int matID = 0, int surfMatID = 0);
+
+protected:
+
+ void pickDraw();
+
+ GLUquadric *mPickQuadric;
+
+ SimScene *mSimScene;
+ //RegularCell3D* mFluidSim;
+
+
+ bool mGunActive;
+ int mMouseX;
+ int mMouseY;
+ bool mMouseDown;
+
+ int mFrameNr;
+
+ enum Weapon {
+ wpMeteor,
+ wpBullet,
+ wpBall,
+ numWeapons,
+ };
+
+ static Weapon mWeapon;
+ int mWeaponLifeTime;
+ Mesh *mBulletMesh;
+ Mesh *mAsteroidMesh;
+ float mMeteorDistance;
+ float mMeteorVelocity;
+ float mMeteorSize;
+ float mLaserImpulse;
+ float mWeaponImpulse;
+
+ PxReal mDefaultContactOffset;
+ PxReal mDefaultRestOffset;
+
+ int debugDrawNumConvexes;
+ TerrainMesh* mTerrain;
+
+
+};
+#endif // SCENE_BOXES_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.cpp b/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.cpp
new file mode 100644
index 00000000..ac3ede53
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.cpp
@@ -0,0 +1,53 @@
+#include "SceneKaplaArena.h"
+#include "Convex.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxShape.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxMat44.h"
+
+#include <stdio.h>
+#include <GL/glut.h>
+
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+
+#include "MathUtils.h"
+
+#include "PxRigidBodyExt.h"
+
+
+extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL);
+
+// ----------------------------------------------------------------------------------------------
+SceneKaplaArena::SceneKaplaArena(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
+ SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
+{
+
+ //onInit(pxPhysics);
+}
+
+void SceneKaplaArena::onInit(PxScene* pxScene)
+{
+ SceneKapla::onInit(pxScene);
+ createGroundPlane();
+
+ const PxVec3 dims(0.08f, 0.25f, 1.0f);
+ PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.4f, 0.15f, 0.1f);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ const PxU32 nbOuterRadialLayouts = 384;
+ const PxReal outerRadius = 40;
+
+ PxFilterData queryFilterData;
+ PxFilterData simFilterData;
+
+ createCylindricalTower(nbOuterRadialLayouts, outerRadius, outerRadius, 8, dims, PxVec3(0.f, 0.f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData);
+ createCylindricalTower(nbOuterRadialLayouts, outerRadius - 2.f, outerRadius - 2.f, 8, dims, PxVec3(0.f, 0.f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData);
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.h b/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.h
new file mode 100644
index 00000000..8c2c9b6f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKaplaArena.h
@@ -0,0 +1,24 @@
+#ifndef SCENE_KAPLA_ARENA_H
+#define SCENE_KAPLA_ARENA_H
+
+#include "SceneKapla.h"
+
+using namespace physx;
+
+// ---------------------------------------------------------------------
+class SceneKaplaArena : public SceneKapla
+{
+public:
+ SceneKaplaArena(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+
+ virtual ~SceneKaplaArena(){}
+
+ virtual void onInit(PxScene* pxScene);
+
+private:
+
+
+
+};
+#endif // SCENE_BOXES_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.cpp b/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.cpp
new file mode 100644
index 00000000..b0465703
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.cpp
@@ -0,0 +1,694 @@
+#include "SceneKaplaTower.h"
+#include "Convex.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxShape.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxMat44.h"
+
+#include <stdio.h>
+#include <GL/glut.h>
+
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include "Mesh.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+
+#include "MathUtils.h"
+
+#include "PxRigidBodyExt.h"
+#include "PxD6Joint.h"
+
+static PxU32 gMaxNbPermittedProjectiles = 0;
+
+#define PROJECTILES_USE_GOLD_MATERIAL 1
+
+
+
+extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL);
+
+// ----------------------------------------------------------------------------------------------
+SceneKaplaTower::SceneKaplaTower(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
+ SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
+{
+ hadInteraction = false;
+ mAccumulatedTime = -5.f;
+ nbProjectiles = 0;
+}
+
+static void finishBody(PxRigidDynamic* dyn, PxReal density, PxReal inertiaScale)
+{
+ dyn->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ dyn->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*dyn, density);
+ dyn->setMassSpaceInertiaTensor(dyn->getMassSpaceInertiaTensor() * inertiaScale);
+ dyn->setAngularDamping(0.15f);
+}
+
+void SceneKaplaTower::preSim(float dt)
+{
+ SceneKapla::preSim(dt);
+}
+
+void SceneKaplaTower::postSim(float dt)
+{
+
+ if (hadInteraction)
+ {
+ mAccumulatedTime = -5.f;
+ hadInteraction = false;
+ }
+
+ mAccumulatedTime += dt;
+
+
+ if (mAccumulatedTime > 0.25f && nbProjectiles < gMaxNbPermittedProjectiles)
+ {
+ nbProjectiles++;
+ mAccumulatedTime = 0.f;
+
+ float wx = randRange(0.5f, 1.5f);
+ float wz = randRange(0.5f, 1.0f);
+ float h = randRange(0.5f, 0.8f);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ PxReal angle = randRange(0.f, 3.14159*2.f); //Random direction...
+
+ PxReal range = randRange(30.f, 40.f);
+
+ PxVec3 pos(range * cosf(angle), 2.f, range * sinf(angle) - 22.f);
+
+ PxReal speed = randRange(10.f, 60.f);
+
+ PxVec3 vel = (PxVec3(0, 0, -22) - pos).getNormalized() * speed + PxVec3(0.f, 250.f/speed, 0.f);
+
+ PxVec3 omega(10.0f, 30.0f, 20.0f);
+ int randomNumber = rand();
+
+ bool createBody = true;
+
+ switch (randomNumber % 4)
+ {
+ case 0:
+ {
+ float r = randRange(0.1f, 0.2f);
+ float R = r + randRange(0.4f, 0.5f);
+ mSimScene->getCompoundCreator()->createTorus(R, r, 15, 10);
+ break;
+ }
+ case 1:
+ {
+ float minLen = 0.6f;
+ float maxLen = 0.9f;
+ PxVec3 dims(randRange(minLen, maxLen), randRange(minLen, maxLen), randRange(minLen, maxLen));
+ mSimScene->getCompoundCreator()->createBox(dims);
+ break;
+ }
+ case 2:
+ {
+ float r = randRange(0.5f, 0.5f);
+ float h = randRange(0.6f, 0.8f);
+ mSimScene->getCompoundCreator()->createCylinder(r, h, 15);
+ break;
+ }
+ case 3:
+ {
+ vel += PxVec3(0.f, 5.f, 0.f);
+ createRagdoll(pos, vel, mat);
+ createBody = false;
+ break;
+ }
+ }
+ if (createBody)
+ {
+ Compound* compound = createObject(pos, vel, omega, false, mat, false
+
+#if PROJECTILES_USE_GOLD_MATERIAL
+ , 0, 1, 1
+#endif
+ );
+ PxRigidDynamic* dyn = compound->getPxActor();
+ finishBody(dyn, 2.f, 1.f);
+
+ if ((randomNumber % 4) == 0)
+ {
+ PxU32 nbLinks = ((randomNumber / 4) & 3);
+ PxTransform trans(pos);
+
+ PxQuat deltaRot(3.1415f / 2.f, PxVec3(1.f, 0.f, 0.f));
+
+ for (PxU32 a = 1; a < nbLinks; ++a)
+ {
+ trans.q = (trans.q * deltaRot).getNormalized();
+ trans.p.x += 0.8f;
+ Compound* compound = createObject(trans, vel, omega, false, mat, false
+#if PROJECTILES_USE_GOLD_MATERIAL
+ , 0, 1, 1
+#endif
+ );
+ PxRigidDynamic* dyn = compound->getPxActor();
+ finishBody(dyn, 2.f, 1.f);
+ }
+ }
+
+ }
+
+ }
+
+ SceneKapla::postSim(dt);
+}
+
+void SceneKaplaTower::onInit(PxScene* pxScene)
+{
+ SceneKapla::onInit(pxScene);
+ createGroundPlane();
+
+ mAccumulatedTime = 0.f;
+ const PxVec3 dims(0.08f, 0.25f, 1.0f);
+ PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ const PxU32 nbInnerInnerRadialLayouts = 40;
+ const PxU32 nbInnerRadialLayouts = 48;
+ const PxU32 nbMidRadialLayouts = 72;
+ const PxU32 nbOuterRadialLayouts = 96;
+ const PxU32 nbOuterOuterRadialLayouts = 128;
+
+ const PxReal innerInnerRadius = 2.5f;
+ const PxReal innerRadius = 4.5f;
+ const PxReal midRadius = 6.5f;
+ const PxReal outerRadius = 8.5f;
+ const PxReal outerOuterRadius = 10.5f;
+
+
+ /*createRectangularTower(10, 10, 4, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
+ createRectangularTower(8, 8, 7, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
+ createRectangularTower(6, 6, 10, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
+ createRectangularTower(4, 4, 14, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);
+ createRectangularTower(2, 2, 18, dims, PxVec3(10, 0.f, -30), DefaultMaterial, mat);*/
+
+ PxFilterData queryFilterData;
+ PxFilterData simFilterData;
+ createCylindricalTower(nbInnerInnerRadialLayouts, innerInnerRadius, innerInnerRadius, 22, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData,1,false,true);
+ createCylindricalTower(nbInnerRadialLayouts, innerRadius, innerRadius, 15, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
+ createCylindricalTower(nbMidRadialLayouts, midRadius, midRadius, 11, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
+ createCylindricalTower(nbOuterRadialLayouts, outerRadius, outerRadius, 8, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
+ createCylindricalTower(nbOuterOuterRadialLayouts, outerOuterRadius, outerOuterRadius, 6, dims, PxVec3(0, 0.f, -22), DefaultMaterial, mat, simFilterData, queryFilterData, 1, false, true);
+
+ createTwistTower(30, 6, dims, PxVec3(13, 0, -28), DefaultMaterial, mat);
+ createTwistTower(30, 6, dims, PxVec3(13, 0, -23), DefaultMaterial, mat);
+ createTwistTower(30, 6, dims, PxVec3(13, 0, -18), DefaultMaterial, mat);
+ createTwistTower(30, 6, dims, PxVec3(13, 0, -13), DefaultMaterial, mat);
+
+
+
+
+ const PxReal capRadius = PxSqrt(dims.z*dims.z + dims.z*dims.z);
+
+ mSimScene->getCompoundCreator()->createCylinder(capRadius, 2*dims.y, 20);
+
+ Compound* compound0 = createObject(PxTransform(PxVec3(-20, dims.y + 15 * 2 * dims.y, -35.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
+ Compound* compound1 = createObject(PxTransform(PxVec3(20, dims.y + 15 * 2 * dims.y, -35.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
+ Compound* compound2 = createObject(PxTransform(PxVec3(-20, dims.y + 15 * 2 * dims.y, -9.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
+ Compound* compound3 = createObject(PxTransform(PxVec3(20, dims.y + 15 * 2 * dims.y, -9.5), PxQuat(3.1415 / 2.f, PxVec3(1.f, 0.f, 0.f))), PxVec3(0), PxVec3(0), false, mat);
+
+ PxRigidDynamic* cylinder0 = compound0->getPxActor();
+ PxRigidDynamic* cylinder1 = compound1->getPxActor();
+ PxRigidDynamic* cylinder2 = compound2->getPxActor();
+ PxRigidDynamic* cylinder3 = compound3->getPxActor();
+
+ finishBody(cylinder0, 0.2f, 4.f);
+ finishBody(cylinder1, 0.2f, 4.f);
+ finishBody(cylinder2, 0.2f, 4.f);
+ finishBody(cylinder3, 0.2f, 4.f);
+
+ createGeometricTower(15, 4, dims, PxVec3(-20, 0, -35.5), 1.f, DefaultMaterial, mat);
+ createGeometricTower(15, 4, dims, PxVec3(20, 0, -35.5), 1.f, DefaultMaterial, mat);
+
+ createGeometricTower(40, 4, dims, PxVec3(-20, 16 * 2 * dims.y, -35.5), 0.74f, DefaultMaterial, mat);
+ createGeometricTower(40, 4, dims, PxVec3(20, 16 * 2 * dims.y, -35.5), 0.74f, DefaultMaterial, mat);
+
+ createGeometricTower(15, 4, dims, PxVec3(-20, 0, -9.5), 1.f, DefaultMaterial, mat);
+ createGeometricTower(15, 4, dims, PxVec3(20, 0, -9.5), 1.f, DefaultMaterial, mat);
+
+ createGeometricTower(40, 4, dims, PxVec3(-20, 16 * 2 * dims.y, -9.5), 0.74f, DefaultMaterial, mat);
+ createGeometricTower(40, 4, dims, PxVec3(20, 16 * 2 * dims.y, -9.5), 0.74f, DefaultMaterial, mat);
+
+
+
+ createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), 0.15f, 0.75f, 0.05f, capRadius,
+ cylinder0, cylinder1, DefaultMaterial, mat, PxQuat(3.14159f/2.f, PxVec3(0,1,0)));
+
+ createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
+ cylinder2, cylinder3, DefaultMaterial, mat, PxQuat(3.14159f / 2.f, PxVec3(0, 1, 0)));
+
+ createCommunicationWire(PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(-20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
+ cylinder0, cylinder2, DefaultMaterial, mat, PxQuat(PxIdentity));
+
+ createCommunicationWire(PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -35.5), PxVec3(20, dims.y / 2.f + 15 * 2 * dims.y, -9.5), 0.15f, 0.75f, 0.05f, capRadius,
+ cylinder1, cylinder3, DefaultMaterial, mat, PxQuat(PxIdentity));
+
+
+
+
+
+ createRectangularTower(27, 19, 6, dims, PxVec3(0.f, 0.f, -20.f), DefaultMaterial, mat);
+}
+
+void SceneKaplaTower::createCommunicationWire(PxVec3 startPos, PxVec3 endPos,
+ PxReal connectRadius, PxReal connectHeight, PxReal density, PxReal offset, PxRigidDynamic* startBody, PxRigidDynamic* endBody, PxMaterial* material, ShaderMaterial& mat,
+ PxQuat& rot)
+{
+ mSimScene->getCompoundCreator()->createCylinder(connectRadius, connectHeight, 8);
+
+ PxVec3 layDir = (endPos - startPos).getNormalized();
+
+ PxReal distance = (startPos - endPos).magnitude() - 2.f * offset;
+
+ PxU32 nbToConnect = (distance) / connectHeight;
+
+ PxReal gap = distance / nbToConnect;
+
+ PxVec3 pos = startPos + layDir* (offset + connectHeight / 2.f);
+
+ PxRigidDynamic* rootActor = startBody;
+
+ PxVec3 anchorPos = startPos + layDir * offset;
+
+ PxPhysics* physics = getSimScene()->getPxPhysics();
+
+ PxRigidDynamic** dyns = new PxRigidDynamic*[nbToConnect];
+
+ for (PxU32 a = 0; a < nbToConnect; ++a)
+ {
+ Compound* compound = createObject(PxTransform(pos, rot), PxVec3(0), PxVec3(0), false, mat);
+
+ PxRigidDynamic* dyn = compound->getPxActor();
+
+ dyns[a] = dyn;
+
+ finishBody(dyn, density, 10.f);
+ dyn->setLinearDamping(0.1f);
+ dyn->setAngularDamping(0.15f);
+ dyn->setStabilizationThreshold(0.f);
+
+ //Now create the constraint
+ PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
+ PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), dyn, PxTransform(dyn->getGlobalPose().transformInv(anchorPos)));
+
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+ //if (a == 0)
+ {
+ joint->setBreakForce((dyn->getMass() + rootActor->getMass()) * 3000.f, (dyn->getMass() + rootActor->getMass()) * 2000.f);
+ }
+
+ joint->setDrive(PxD6Drive::eSWING, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
+ joint->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
+
+ pos += layDir * gap;
+ anchorPos += layDir * gap;
+ rootActor = dyn;
+ }
+
+ PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
+ PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), endBody, PxTransform(endBody->getGlobalPose().transformInv(anchorPos)));
+
+ joint->setBreakForce((endBody->getMass() + rootActor->getMass()) * 3000.f, (endBody->getMass() + rootActor->getMass()) * 2000.f);
+
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+
+ joint->setDrive(PxD6Drive::eSWING, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
+ joint->setDrive(PxD6Drive::eTWIST, PxD6JointDrive(0.f, 0.15f, PX_MAX_F32));
+
+ //Now add some bunting to the connections...
+
+ mSimScene->getCompoundCreator()->createBox(PxVec3(connectRadius, connectHeight, connectHeight));
+
+ for (PxU32 a = 2; a < nbToConnect; a += 3)
+ {
+ //Create a little box to attach
+
+ PxRigidDynamic* rootActor = dyns[a];
+ PxTransform transform = rootActor->getGlobalPose();
+
+ transform.p += PxVec3(0.f, -(connectRadius + 0.5*connectHeight), 0.f);
+
+ Compound* compound = createObject(transform, PxVec3(0), PxVec3(0), false, mat);
+
+ PxRigidDynamic* dyn = compound->getPxActor();
+
+ finishBody(dyn, density*0.5f, 10.f);
+ dyn->setLinearDamping(0.1f);
+ dyn->setAngularDamping(0.15f);
+ dyn->setStabilizationThreshold(0.f);
+
+ anchorPos = transform.p + PxVec3(0, 0.5f*connectHeight, 0);
+
+ PxD6Joint *joint = PxD6JointCreate(*physics, rootActor,
+ PxTransform(rootActor->getGlobalPose().transformInv(anchorPos)), dyn, PxTransform(dyn->getGlobalPose().transformInv(anchorPos)));
+
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLOCKED);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLOCKED);
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eLOCKED);
+
+
+
+
+ }
+
+
+ delete dyns;
+
+
+
+}
+
+
+void SceneKaplaTower::createGeometricTower(PxU32 height, PxU32 nbFacets, PxVec3 dims, PxVec3 startPos, PxReal startDensity, PxMaterial* material, ShaderMaterial& mat)
+{
+ PX_UNUSED(nbFacets);
+ //Create a tower of geometric shaps
+ PxReal angle = (3.14159 / 2.f); //the angle between each facet...
+ PxQuat zRot(3.1415 / 2.f, PxVec3(0, 1, 0));
+
+ PxQuat rotation[] = { PxQuat(PxIdentity), PxQuat(3.1415 / 4.f, PxVec3(0, 1, 0)) };
+
+ PxReal offset = dims.z;
+ PxReal density = startDensity;
+
+ PxShape* shape;
+
+ PxVec3 vel(0), omega(0);
+
+ mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
+
+ for (PxU32 i = 0; i < height; ++i)
+ {
+ PxVec3 yOffset(0, dims.y + i * dims.y * 2, 0);
+ PxQuat rot = rotation[i & 1];
+
+ PxVec3 basis0 = rot.getBasisVector0();
+ PxVec3 basis2 = rot.getBasisVector2();
+
+ PxVec3 pos0 = -basis0 * offset + basis2 * dims.x;
+ PxVec3 pos1 = basis0 * offset - basis2 * dims.x;
+ PxVec3 pos2 = basis0 * dims.x + basis2 * offset;
+ PxVec3 pos3 = -basis0 * dims.x - basis2 * offset;
+
+ //PxRigidDynamic* box0 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos0 + startPos + yOffset, rot, dims);
+ //PxRigidDynamic* box1 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos1 + startPos + yOffset, rot, dims);
+ //PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + startPos + yOffset, zRot * rot, dims);
+ //PxRigidDynamic* box3 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos3 + startPos + yOffset, zRot * rot, dims);
+
+ Compound* compound0 = createObject(PxTransform(pos0 + startPos + yOffset, rot), vel, omega, false, mat);
+ PxRigidDynamic* box0 = compound0->getPxActor();
+ box0->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ Compound* compound1 = createObject(PxTransform(pos1 + startPos + yOffset, rot), vel, omega, false, mat);
+ PxRigidDynamic* box1 = compound1->getPxActor();
+ box1->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ Compound* compound2 = createObject(PxTransform(pos2 + startPos + yOffset, zRot * rot), vel, omega, false, mat);
+ PxRigidDynamic* box2 = compound2->getPxActor();
+ box2->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ Compound* compound3 = createObject(PxTransform(pos3 + startPos + yOffset, zRot * rot), vel, omega, false, mat);
+ PxRigidDynamic* box3 = compound3->getPxActor();
+ box3->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box0->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box0->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box0, density);
+ box0->setMassSpaceInertiaTensor(box0->getMassSpaceInertiaTensor() * 4.f);
+
+ box1->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box1->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box1, density);
+ box1->setMassSpaceInertiaTensor(box1->getMassSpaceInertiaTensor() * 4.f);
+
+ box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box2->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box2, density);
+ box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
+
+ box3->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box3->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box3, density);
+ box3->setMassSpaceInertiaTensor(box3->getMassSpaceInertiaTensor() * 4.f);
+
+ density = density * 0.98f;
+
+ }
+
+
+
+}
+
+
+void SceneKaplaTower::createTwistTower(PxU32 height, PxU32 nbBlocksPerLayer, PxVec3 dims, PxVec3 startPos, PxMaterial* material, ShaderMaterial& mat)
+{
+ PxQuat rotation(PxIdentity);//3.14/2.f, PxVec3(0,0,1));
+ PxQuat rotationDelta(3.14 / 10.f, PxVec3(0, 1, 0));
+ PxReal density = 1.f;
+ PxShape* shape;
+ PxVec3 vel(0), omega(0);
+
+ mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
+
+ for (PxU32 i = 0; i < height; ++i)
+ {
+ PxReal startY = i * dims.y * 2 + dims.y;
+ PxVec3 xVec = rotation.getBasisVector0();
+ for (PxU32 a = 0; a < nbBlocksPerLayer; ++a)
+ {
+ PxVec3 pos = xVec * dims.x * 2 * (PxReal(a) - PxReal(nbBlocksPerLayer) / 2.f) + PxVec3(0, startY, 0);
+ //PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + startPos, rotation, dims);
+ Compound* compound = createObject(PxTransform(pos + startPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+ }
+
+ rotation = rotationDelta * rotation;
+ density *= 0.95f;
+ }
+}
+
+
+void SceneKaplaTower::createRectangularTower(PxU32 nbX, PxU32 nbZ, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat)
+{
+ PxReal startHeight = 0.f;
+ PxReal density = 1.f;
+
+ PxU32 nbXSupports = 1 + 2 * nbX;
+
+ PxReal xSpacing = dims.z;
+
+ PxU32 nbZSlabs = (2.f*dims.z * nbZ) / (2.f*dims.y);
+
+ PxQuat rotation = PxQuat(3.14 / 2.f, PxVec3(0, 1, 0)) * PxQuat(3.14 / 2.f, PxVec3(0, 0, 1));
+
+ mSimScene->getCompoundCreator()->createBox(2.f*dims);//0.5f, 0.2f, 20, 20);
+ PxVec3 pos(-2.0f, 1.5f, 0.0f);
+ PxVec3 vel(0.0f, 0.0f, 0.0f);
+ PxVec3 omega(0.0f, 0.0f, 0.0f);
+
+ for (PxU32 i = 0; i < height; ++i)
+ {
+ //First, lets lay down the supports...
+
+ PxVec3 rowColExtents((nbX)* dims.z, 0.f, (nbZ)* dims.z);
+
+ PxShape* shape;
+
+ //Back row
+ for (PxU32 a = 0; a < nbXSupports; ++a)
+ {
+ PxVec3 pos(a * xSpacing - rowColExtents.x, startHeight + dims.y, -rowColExtents.z);
+ PxVec3 pos2(a * xSpacing - rowColExtents.x, startHeight + dims.y, rowColExtents.z);
+
+ Compound* compound = createObject(PxTransform(pos + centerPos), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+
+ Compound* compound2 = createObject(PxTransform(pos2 + centerPos), vel, omega, false, mat);
+ PxRigidDynamic* box2 = compound2->getPxActor();
+ box2->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box2->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box2, density);
+ box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
+ }
+
+ for (PxU32 a = 0; a < nbX; ++a)
+ {
+ PxVec3 pos(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z - dims.y);
+ PxVec3 pos2(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y);
+
+ Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ //PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + centerPos, rotation, dims);
+ Compound* compound2 = createObject(PxTransform(pos2 + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box2 = compound2->getPxActor();
+ box2->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+
+ box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box2->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box2, density);
+ box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
+
+
+ PxVec3 pos3(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, rowColExtents.z - dims.y);
+ PxVec3 pos4(dims.z + a * dims.z * 2 - rowColExtents.x, startHeight + 2 * dims.y + dims.x, rowColExtents.z + dims.y);
+
+ //PxRigidDynamic* box3 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos3 + centerPos, rotation, dims);
+
+ Compound* compound3 = createObject(PxTransform(pos3 + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box3 = compound3->getPxActor();
+ box3->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ //PxRigidDynamic* box4 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos4 + centerPos, rotation, dims);
+ Compound* compound4 = createObject(PxTransform(pos4 + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box4 = compound4->getPxActor();
+ box4->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box3->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box3->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box3, density);
+ box3->setMassSpaceInertiaTensor(box3->getMassSpaceInertiaTensor() * 4.f);
+
+ box4->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box4->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box4, density);
+ box4->setMassSpaceInertiaTensor(box4->getMassSpaceInertiaTensor() * 4.f);
+
+ }
+
+ //Sides...
+ for (PxU32 a = 1; a < nbZ; ++a)
+ {
+ for (PxU32 b = 0; b < 3; b++)
+ {
+ PxVec3 pos(b * xSpacing - rowColExtents.x, startHeight + dims.y, -rowColExtents.z + a * dims.z * 2);
+ PxVec3 pos2(rowColExtents.x - b * xSpacing, startHeight + dims.y, -rowColExtents.z + a * dims.z * 2);
+
+ //PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, PxQuat(PxIdentity), dims);
+ Compound* compound = createObject(PxTransform(pos + centerPos), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+
+ //PxRigidDynamic* box2 = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos2 + centerPos, PxQuat(PxIdentity), dims);
+ Compound* compound2 = createObject(PxTransform(pos2 + centerPos), vel, omega, false, mat);
+ PxRigidDynamic* box2 = compound2->getPxActor();
+ box2->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box2->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box2->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box2, density);
+ box2->setMassSpaceInertiaTensor(box2->getMassSpaceInertiaTensor() * 4.f);
+ }
+ }
+
+ for (PxU32 a = 1; a < nbZSlabs - 1; a++)
+ {
+ PxVec3 pos(dims.z - rowColExtents.x, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y + 2 * dims.y*a);
+
+ //PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, rotation, dims);
+ Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+ }
+
+ for (PxU32 a = 1; a < nbZSlabs - 1; a++)
+ {
+ PxVec3 pos(rowColExtents.x - dims.z, startHeight + 2 * dims.y + dims.x, -rowColExtents.z + dims.y + 2 * dims.y*a);
+
+ //PxRigidDynamic* box = PxTkCreateDynamicBox(*mSDK, mScene, material, mObjectCreationParams, pos + centerPos, rotation, dims);
+ Compound* compound = createObject(PxTransform(pos + centerPos, rotation), vel, omega, false, mat);
+ PxRigidDynamic* box = compound->getPxActor();
+ box->getShapes(&shape, 1);
+ shape->setMaterials(&material, 1);
+
+ box->setSolverIterationCounts(DEFAULT_SOLVER_ITERATIONS);
+ box->setMaxDepenetrationVelocity(2.f);
+ PxRigidBodyExt::updateMassAndInertia(*box, density);
+ box->setMassSpaceInertiaTensor(box->getMassSpaceInertiaTensor() * 4.f);
+ }
+
+ startHeight += 2 * (dims.y + dims.x);
+ density *= 0.975f;
+
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneKaplaTower::handleKeyDown(unsigned char key, int x, int y)
+{
+ switch (key) {
+ case 'b':
+ case 'B':
+ {
+ if (gMaxNbPermittedProjectiles == 0)
+ gMaxNbPermittedProjectiles = 512;
+ else
+ gMaxNbPermittedProjectiles = 0;
+
+ break;
+ }
+ }
+
+ SceneKapla::handleKeyDown(key, x, y);
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.h b/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.h
new file mode 100644
index 00000000..d709251c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneKaplaTower.h
@@ -0,0 +1,41 @@
+#ifndef SCENE_KAPLA_TOWER_H
+#define SCENE_KAPLA_TOWER_H
+
+#include "SceneKapla.h"
+
+using namespace physx;
+
+// ---------------------------------------------------------------------
+class SceneKaplaTower : public SceneKapla
+{
+public:
+ SceneKaplaTower(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+
+ virtual ~SceneKaplaTower(){}
+
+ virtual void handleKeyDown(unsigned char key, int x, int y);
+
+ virtual void preSim(float dt);
+ virtual void postSim(float dt);
+
+ virtual void onInit(PxScene* pxScene);
+
+private:
+
+
+
+ void createGeometricTower(PxU32 height, PxU32 nbFacets, PxVec3 dims, PxVec3 startPos, PxReal startDensity, PxMaterial* material, ShaderMaterial& mat);
+ void createCommunicationWire(PxVec3 startPos, PxVec3 endPos,PxReal connectRadius, PxReal connectHeight, PxReal density, PxReal offset, PxRigidDynamic* startBody,
+ PxRigidDynamic* endBody, PxMaterial* material, ShaderMaterial& mat, PxQuat& rot);
+ void createTwistTower(PxU32 height, PxU32 nbBlocksPerLayer, PxVec3 dims, PxVec3 startPos, PxMaterial* material, ShaderMaterial& mat);
+ void createRectangularTower(PxU32 nbX, PxU32 nbZ, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat);
+ //void createCylindricalTower(PxU32 nbRadialPoints, PxReal maxRadius, PxReal minRadius, PxU32 height, PxVec3 dims, PxVec3 centerPos, PxMaterial* material, ShaderMaterial& mat);
+
+ PxReal mAccumulatedTime;
+
+ bool hadInteraction;
+ PxU32 nbProjectiles;
+
+};
+#endif // SCENE_BOXES_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.cpp b/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.cpp
new file mode 100644
index 00000000..84b407d7
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.cpp
@@ -0,0 +1,106 @@
+#include "SceneRagdollWashingMachine.h"
+#include "Convex.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxShape.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxMat44.h"
+
+#include <stdio.h>
+#include <GL/glut.h>
+
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include "Mesh.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+
+#include "MathUtils.h"
+
+#include "PxRigidBodyExt.h"
+#include "PxD6Joint.h"
+
+using namespace physx;
+using namespace physx::shdfnd;
+
+static PxReal speeds[] = { 3.141692f*0.125f, 3.141592f*0.25f, 3.141592f*0.75f, 3.141592f*0.5f, 3.141592f*0.25f };
+static PxReal spinDurations[] = { 10, 15, 5, 5, 10 };
+
+SceneRagdollWashingMachine::SceneRagdollWashingMachine(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) : SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor),
+ mWashingMachine(NULL)
+{
+ mChangeSpeedTime = 15.f;
+ mSpeedState = 0;
+}
+
+void SceneRagdollWashingMachine::preSim(float dt)
+{
+ mChangeSpeedTime -= dt;
+ if (mChangeSpeedTime < 0.f)
+ {
+ mSpeedState = (mSpeedState + 1)%5;
+ mChangeSpeedTime = spinDurations[mSpeedState];
+ }
+
+ PxQuat rotationPerFrame(speeds[mSpeedState]*dt, PxVec3(0,0,1));
+
+ PxTransform trans = mWashingMachine->getGlobalPose();
+ trans.q = trans.q * rotationPerFrame;
+ mWashingMachine->setKinematicTarget(trans);
+
+ SceneKapla::preSim(dt);
+}
+
+void SceneRagdollWashingMachine::onInit(PxScene* pxScene)
+{
+ //(1) Create the washing machine :)
+
+ SceneKapla::onInit(pxScene);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ PxVec3 dims(3.f, 1.f, 35.f);
+
+ PxReal radius = 7.f;
+
+ PxReal circumference = 2.f * radius * 3.141592f;
+
+ //Now work out how many slabs you need to satisfy this...
+
+ PxU32 nbSlabs = PxU32((circumference / dims.x)) + 5;
+
+ PxVec3 offset(0, radius, 0);
+
+ for (PxU32 a = 0; a < nbSlabs; ++a)
+ {
+ PxQuat rotation(a*2.f*3.141592 / PxReal(nbSlabs), PxVec3(0, 0, 1));
+
+ PxTransform localTransform(rotation.rotate(offset), rotation);
+
+ mSimScene->getCompoundCreator()->createBox(dims, &localTransform, a == 0);
+ }
+
+ PxTransform localTransform(PxVec3(0, radius - dims.x/2.f, 0.f), PxQuat(3.141592*0.5f, PxVec3(0, 0, 1)));
+ mSimScene->getCompoundCreator()->createBox(dims, &localTransform, false);
+
+ Compound* compound = createObject(PxTransform(PxVec3(0, radius+5.f, -dims.z)), PxVec3(0), PxVec3(0), false, mat,false);
+ mWashingMachine = compound->getPxActor();
+ mWashingMachine->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+
+ for (PxU32 a = 0; a < 20; ++a)
+ {
+ for (PxU32 b = 0; b < 35; ++b)
+ {
+ createRagdoll(PxVec3(-radius + 2.f + a * 0.5f, radius+5.f, -dims.z*0.8f - b * 0.5f), PxVec3(0), mat);
+ }
+ }
+
+ createGroundPlane(PxFilterData(), PxVec3(0, -2.f, 0));
+
+ mSimScene->getCompoundCreator()->createBox(PxVec3(20.f, 20.f, 2.f));
+ Compound* staticCompound = createObject(PxTransform(PxVec3(0.f, radius+5.f, -1.5f*dims.z)), PxVec3(0), PxVec3(0),false,mat,false);
+ staticCompound->getPxActor()->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+} \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.h b/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.h
new file mode 100644
index 00000000..32f4157d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneRagdollWashingMachine.h
@@ -0,0 +1,25 @@
+#ifndef SCENE_RAGDOLL_WASHING_MACHINE_H
+#define CENE_RAGDOLL_WASHING_MACHINE_H
+
+#include "SceneKapla.h"
+
+using namespace physx;
+
+// ---------------------------------------------------------------------
+class SceneRagdollWashingMachine : public SceneKapla
+{
+ PxReal mChangeSpeedTime;
+ PxU32 mSpeedState;
+ PxRigidDynamic* mWashingMachine;
+public:
+ SceneRagdollWashingMachine(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+
+ virtual ~SceneRagdollWashingMachine(){}
+
+ virtual void preSim(float dt);
+
+ virtual void onInit(PxScene* pxScene);
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp b/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp
new file mode 100644
index 00000000..69468a48
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicle.cpp
@@ -0,0 +1,1193 @@
+#include "SceneVehicle.h"
+#include "Convex.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxShape.h"
+#include "foundation/PxMathUtils.h"
+#include "foundation/PxMat44.h"
+#include "PsString.h"
+#include "CmPhysxCommon.h"
+
+#include <stdio.h>
+#include <GL/glut.h>
+
+#include "SimScene.h"
+#include "CompoundCreator.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+
+#include "PxRigidBodyExt.h"
+
+#include "vehicle/PxVehicleSDK.h"
+#include "vehicle/PxVehicleDrive4W.h"
+#include "vehicle/PxVehicleUtilSetup.h"
+#include "vehicle/PxVehicleUtil.h"
+#include "SceneVehicleCooking.h"
+#include "SceneVehicleSceneQuery.h"
+#include "SampleViewerGamepad.h"
+#include "RawLoader.h"
+#include "TerrainRandomSamplePrecompute.h"
+#include "MediaPath.h"
+#include "glmesh.h"
+#include "Texture.h"
+#include "PxShapeExt.h"
+
+static bool createVehicleDemo = true;
+
+
+
+///////////////////////////////////
+//VEHICLE START PARAMETERS
+///////////////////////////////////
+
+
+#define NUM_PLAYER_CARS 1
+static PxTransform gPlayerCarStartTransforms[NUM_PLAYER_CARS] =
+{
+ PxTransform(PxVec3(-154.699753f, 9.863837f, 87.684113f), PxQuat(-0.000555f, -0.267015, 0.000155, -0.963692))
+};
+
+////////////////////////////////////////////////////////////////
+//VEHICLE SETUP DATA
+////////////////////////////////////////////////////////////////
+
+PxF32 gChassisMass = 1500.0f;
+PxF32 gSuspensionShimHeight = 0.125f;
+
+
+////////////////////////////////////////////////////////////////
+//RENDER USER DATA TO ASSOCIATE EACH RENDER MESH WITH A
+//VEHICLE PHYSICS COMPONENT
+////////////////////////////////////////////////////////////////
+
+enum
+{
+ CAR_PART_FRONT_LEFT_WHEEL = 0,
+ CAR_PART_FRONT_RIGHT_WHEEL,
+ CAR_PART_REAR_LEFT_WHEEL,
+ CAR_PART_REAR_RIGHT_WHEEL,
+ CAR_PART_CHASSIS,
+ CAR_PART_WINDOWS,
+ NUM_CAR4W_RENDER_COMPONENTS,
+ CAR_PART_EXTRA_WHEEL0 = NUM_CAR4W_RENDER_COMPONENTS,
+ CAR_PART_EXTRA_WHEEL1,
+ NUM_CAR6W_RENDER_COMPONENTS
+};
+
+enum MaterialID
+{
+ MATERIAL_TERRAIN_MUD = 1000,
+ MATERIAL_ROAD_TARMAC = 1001,
+ MATERIAL_ROAD_SNOW = 1002,
+ MATERIAL_ROAD_GRASS = 1003,
+};
+
+
+static const char gCarPartNames[NUM_CAR4W_RENDER_COMPONENTS][64] =
+{
+ "frontwheelleftshape",
+ "frontwheelrightshape",
+ "backwheelleftshape",
+ "backwheelrightshape",
+ "car_02_visshape",
+ "car_02_windowsshape"
+};
+
+////////////////////////////////////////////////////////////////
+//TRANSFORM APPLIED TO CHASSIS RENDER MESH VERTS
+//THAT IS REQUIRED TO PLACE AABB OF CHASSIS RENDER MESH AT ORIGIN
+//AT CENTRE-POINT OF WHEELS.
+////////////////////////////////////////////////////////////////
+
+static PxVec3 gChassisMeshTransform(0, 0, 0);
+
+////////////////////////////////////////////////////////////////
+//WHEEL CENTRE OFFSETS FROM CENTRE OF CHASSIS RENDER MESH AABB
+//OF 4-WHEELED VEHICLE
+////////////////////////////////////////////////////////////////
+
+static PxVec3 gWheelCentreOffsets4[4];
+
+////////////////////////////////////////////////////////////////
+//CONVEX HULL OF RENDER MESH FOR CHASSIS AND WHEELS OF
+//4-WHEELED VEHICLE
+////////////////////////////////////////////////////////////////
+
+static PxConvexMesh* gChassisConvexMesh = NULL;
+static PxConvexMesh* gWheelConvexMeshes4[4] = { NULL, NULL, NULL, NULL };
+static GLMesh* gCarPartRenderMesh[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
+
+
+extern bool LoadTexture(const char *filename, GLuint &texId, bool createMipmaps, GLuint type = GL_TEXTURE_2D, int *width = NULL, int *height = NULL);
+
+// ----------------------------------------------------------------------------------------------
+SceneVehicle::SceneVehicle(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor) :
+ SceneKapla(pxPhysics, pxCooking, isGrb, defaultShader, resourcePath, slowMotionFactor)
+{
+ mChassisMaterialDrivable = NULL;
+ mChassisMaterialNonDrivable = NULL;
+ if (createVehicleDemo)
+ mCameraDisable = true;
+ else
+ mCameraDisable = false;
+ mNumTextures = 0;
+ mNumMaterials = 0;
+ //onInit(pxPhysics, pxCooking, pxScene);
+}
+
+
+void SceneVehicle::onInit(PxScene* pxScene)
+{
+ SceneKapla::onInit(pxScene);
+ createStandardMaterials();
+ if (createVehicleDemo)
+ createVehicle(mPxPhysics);
+ SceneKapla::createTerrain("terrain_ll2.bmp", "");
+
+ const PxVec3 dims(0.08f, 0.25f, 1.0f);
+
+ PxMaterial* DefaultMaterial = mPxPhysics->createMaterial(0.5f, 0.25f, 0.1f);
+
+ ShaderMaterial mat;
+ mat.init();
+
+ PxFilterData simFilterData;
+ simFilterData.word0 = COLLISION_FLAG_OBSTACLE;
+ simFilterData.word1 = COLLISION_FLAG_OBSTACLE_AGAINST;
+ //simFilterData.word2 = PxPairFlag::eMODIFY_CONTACTS;
+
+ PxFilterData queryFilterData;
+ //VehicleSetupDrivableShapeQueryFilterData(&queryFilterData);
+
+ createCylindricalTower(96, 3.6f, 3.6f, 14, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f);
+ createCylindricalTower(96, 5.8f, 5.8f, 10, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f);
+ createCylindricalTower(128, 8.f, 8.f, 8, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f);
+ createCylindricalTower(196, 10.2f, 10.2f, 6, dims, PxVec3(-10.f, -1.10f, 20.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f);
+
+
+ createCylindricalTower(384, 35.f, 35.f, 6, dims, PxVec3(0.f, -1.10f, 0.f), DefaultMaterial, mat, simFilterData, queryFilterData, 10.f);
+
+
+ /*PxFilterData planeFilterData;
+ simFilterData.word0 = COLLISION_FLAG_GROUND;
+ simFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST;
+
+ VehicleSetupDrivableShapeQueryFilterData(&queryFilterData);
+
+ createGroundPlane(planeFilterData, PxVec3(0,0,0), queryFilterData);
+
+ PxTransform pose = mVehicleManager.getVehicle()->getRigidDynamicActor()->getGlobalPose();
+ pose.p.y += 3.f;
+
+ mVehicleManager.getVehicle()->getRigidDynamicActor()->setGlobalPose(pose);*/
+
+}
+
+void SceneVehicle::setScene(PxScene* pxScene)
+{
+ SceneKapla::setScene(pxScene);
+ mVehicleManager.clearBatchQuery();
+}
+
+void SceneVehicle::createStandardMaterials()
+{
+ const PxF32 restitutions[MAX_NUM_SURFACE_TYPES] = { 0.2f, 0.2f, 0.2f, 0.2f };
+ const PxF32 staticFrictions[MAX_NUM_SURFACE_TYPES] = { 0.5f, 0.5f, 0.5f, 0.5f };
+ const PxF32 dynamicFrictions[MAX_NUM_SURFACE_TYPES] = { 0.5f, 0.5f, 0.5f, 0.5f };
+
+ for (PxU32 i = 0; i<MAX_NUM_SURFACE_TYPES; i++)
+ {
+ //Create a new material.
+ mStandardMaterials[i] = getPhysics().createMaterial(staticFrictions[i], dynamicFrictions[i], restitutions[i]);
+ if (!mStandardMaterials[i])
+ {
+ printf("SceneVehicle : create mStandardMaterials failed");
+ }
+
+ //Set up the drivable surface type that will be used for the new material.
+ mVehicleDrivableSurfaceTypes[i].mType = i;
+ }
+
+ mChassisMaterialDrivable = getPhysics().createMaterial(0.0f, 0.0f, 0.0f);
+ if (!mChassisMaterialDrivable)
+ {
+ printf("SceneVehicle : create mChassisMaterialDrivable failed");
+ }
+
+ mChassisMaterialNonDrivable = getPhysics().createMaterial(1.0f, 1.0f, 0.0f);
+ if (!mChassisMaterialNonDrivable)
+ {
+ printf("SceneVehicle : create mChassisMaterialNonDrivable failed");
+ }
+}
+
+static void computeTerrain(bool* done, float* pVB, PxU32 x0, PxU32 y0, PxU32 currentSize, float value, PxU32 initSize, TerrainRandomSamplePrecompute& randomPrecomputed)
+{
+ // Compute new size
+ currentSize >>= 1;
+ if (currentSize > 0)
+ {
+ const PxU32 x1 = (x0 + currentSize) % initSize;
+ const PxU32 x2 = (x0 + currentSize + currentSize) % initSize;
+ const PxU32 y1 = (y0 + currentSize) % initSize;
+ const PxU32 y2 = (y0 + currentSize + currentSize) % initSize;
+
+ if (!done[x1 + y0*initSize]) pVB[(x1 + y0*initSize) * 9 + 1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y0*initSize) * 9 + 1] + pVB[(x2 + y0*initSize) * 9 + 1]);
+ if (!done[x0 + y1*initSize]) pVB[(x0 + y1*initSize) * 9 + 1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y0*initSize) * 9 + 1] + pVB[(x0 + y2*initSize) * 9 + 1]);
+ if (!done[x2 + y1*initSize]) pVB[(x2 + y1*initSize) * 9 + 1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x2 + y0*initSize) * 9 + 1] + pVB[(x2 + y2*initSize) * 9 + 1]);
+ if (!done[x1 + y2*initSize]) pVB[(x1 + y2*initSize) * 9 + 1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y2*initSize) * 9 + 1] + pVB[(x2 + y2*initSize) * 9 + 1]);
+ if (!done[x1 + y1*initSize]) pVB[(x1 + y1*initSize) * 9 + 1] = randomPrecomputed.getRandomInRange(-0.5f*value, 0.5f*value) + 0.5f * (pVB[(x0 + y1*initSize) * 9 + 1] + pVB[(x2 + y1*initSize) * 9 + 1]);
+
+ done[x1 + y0*initSize] = true;
+ done[x0 + y1*initSize] = true;
+ done[x2 + y1*initSize] = true;
+ done[x1 + y2*initSize] = true;
+ done[x1 + y1*initSize] = true;
+
+ // Recurse through 4 corners
+ value *= 0.5f;
+ computeTerrain(done, pVB, x0, y0, currentSize, value, initSize, randomPrecomputed);
+ computeTerrain(done, pVB, x0, y1, currentSize, value, initSize, randomPrecomputed);
+ computeTerrain(done, pVB, x1, y0, currentSize, value, initSize, randomPrecomputed);
+ computeTerrain(done, pVB, x1, y1, currentSize, value, initSize, randomPrecomputed);
+ }
+}
+
+void SceneVehicle::createTerrain(PxU32 size, float width, float chaos)
+{
+ mNbTerrainVerts = size*size;
+
+ // Vertex buffer
+ mTerrainVB = new PxF32[(sizeof(float)*mNbTerrainVerts * 3 * 3)];
+ for (PxU32 y = 0; y<size; y++)
+ {
+ for (PxU32 x = 0; x<size; x++)
+ {
+ mTerrainVB[(x + y*size) * 9 + 0] = (float(x) - (float(size - 1)*0.5f))* width;
+ mTerrainVB[(x + y*size) * 9 + 1] = 0.0f;
+ mTerrainVB[(x + y*size) * 9 + 2] = (float(y) - (float(size - 1)*0.5f))* width;
+ mTerrainVB[(x + y*size) * 9 + 3] = 0.0f; mTerrainVB[(x + y*size) * 9 + 4] = 1.0f; mTerrainVB[(x + y*size) * 9 + 5] = 0.0f;
+ mTerrainVB[(x + y*size) * 9 + 6] = 0.5f; mTerrainVB[(x + y*size) * 9 + 7] = 0.4f; mTerrainVB[(x + y*size) * 9 + 8] = 0.2f;
+ }
+ }
+
+ // Fractalize
+ bool* doneBuffer = new bool[(sizeof(bool)*mNbTerrainVerts)];
+ PxU32* tagBuffer = new PxU32[(sizeof(PxU32)*mNbTerrainVerts)];
+ for (PxU32 i = 0; i<mNbTerrainVerts; i++)
+ {
+ doneBuffer[i] = false;
+ tagBuffer[i] = 0;
+ }
+ mTerrainVB[1] = 10.0f;
+ mTerrainVB[(size - 1) * 9 + 1] = 10.0f;
+ mTerrainVB[(size*(size - 1)) * 9 + 1] = 10.0f;
+ mTerrainVB[(mNbTerrainVerts - 1) * 9 + 1] = 10.0f;
+
+ TerrainRandomSamplePrecompute randomPrecomputed(*this, mResourcePath);
+ computeTerrain(doneBuffer, mTerrainVB, 0, 0, size, chaos / 16.0f, size, randomPrecomputed);
+
+ const PxU32 street0 = (PxU32)(size / 3.0f);
+ const PxU32 streetSize = (PxU32)(size / 30.0f);
+ float ay = 0.0f;
+
+ for (PxU32 y = 0; y<size; y++)
+ {
+ for (PxU32 x = street0; x<street0 + streetSize; x++)
+ {
+ ay += mTerrainVB[(x + y*size) * 9 + 1];
+ ay += mTerrainVB[(y + x*size) * 9 + 1];
+ }
+ }
+
+ const float cx = size / 2.0f;
+ const float cy = size / 2.0f;
+ const float r = size / 3.0f;
+ const float g = streetSize / 2.0f;
+
+ for (PxU32 i = 0; i<mNbTerrainVerts; i++)
+ tagBuffer[i] = false;
+
+ ay /= streetSize*size;
+ ay -= streetSize;
+ for (PxU32 y = 15; y<size - 15; y++)
+ {
+ bool smoothBorder = true;
+
+ for (PxU32 x = street0; x<street0 + streetSize; x++)
+ {
+ if (y > size*0.5f && y < size*0.7f)
+ {
+ mTerrainVB[(x + y*size) * 9 + 1] = ay + sinf(((float)y)*12.0f + 4.0f)*2.0f;
+ smoothBorder = false;
+ }
+ else
+ {
+ mTerrainVB[(x + y*size) * 9 + 1] = ay;
+ }
+
+ if (y > size*0.55f && y < size*0.75f)
+ {
+ mTerrainVB[(y + x*size) * 9 + 1] = ay + sinf(y*12.0f)*0.75f;
+ //mTerrainVB[(y+x*size)*9+1]=ay;
+ tagBuffer[y + x*size] = 3;
+ tagBuffer[x + y*size] = 3;
+ smoothBorder = false;
+ }
+ else if (y < size*0.15f)
+ {
+ const float s = size*0.15f - (float)y;
+ mTerrainVB[(y + x*size) * 9 + 1] = ay + s*0.25f;
+ smoothBorder = false;
+ }
+ else if (y > size*0.85f)
+ {
+ const float s = (float)y - size*0.85f;
+ mTerrainVB[(y + x*size) * 9 + 1] = ay + s*0.7f;
+ smoothBorder = false;
+ }
+ else
+ {
+ mTerrainVB[(y + x*size) * 9 + 1] = ay;
+ tagBuffer[y + x*size] = 1;
+ tagBuffer[x + y*size] = 1;
+ }
+
+ }
+ if (smoothBorder)
+ {
+ mTerrainVB[((street0 - 1) + y*size) * 9 + 1] = ay*0.5f + mTerrainVB[((street0 - 1) + y*size) * 9 + 1] * 0.5f;
+ mTerrainVB[(y + (street0 - 1)*size) * 9 + 1] = ay*0.5f + mTerrainVB[(y + (street0 - 1)*size) * 9 + 1] * 0.5f;
+ mTerrainVB[((street0 + 1) + y*size) * 9 + 1] = ay*0.5f + mTerrainVB[((street0 + 1) + y*size) * 9 + 1] * 0.5f;
+ mTerrainVB[(y + (street0 + 1)*size) * 9 + 1] = ay*0.5f + mTerrainVB[(y + (street0 + 1)*size) * 9 + 1] * 0.5f;
+ }
+ }
+
+ // Circle street
+ for (PxU32 y = 0; y<size; y++)
+ {
+ for (PxU32 x = 0; x<size; x++)
+ {
+ const float x0 = x - cx;
+ const float y0 = y - cy;
+ const float d = sqrtf(x0*x0 + y0*y0);
+ if (d >= r && d < r + streetSize)
+ {
+ mTerrainVB[(y + x*size) * 9 + 1] = ay;
+
+ if (y > size*0.55f && y < size*0.75f)
+ tagBuffer[y + x*size] = 2;
+ else
+ tagBuffer[y + x*size] = 1;
+
+ }
+ else if (d >= r + streetSize && d < r + streetSize + g)
+ {
+ const float a = (d - (r + streetSize)) / g;
+ mTerrainVB[(y + x*size) * 9 + 1] = ay*(1.0f - a) + mTerrainVB[(y + x*size) * 9 + 1] * a;
+ }
+ else if (d >= r - g && d < r)
+ {
+ const float a = (d - (r - g)) / g;
+ mTerrainVB[(y + x*size) * 9 + 1] = ay*a + mTerrainVB[(y + x*size) * 9 + 1] * (1.0f - a);
+ }
+ }
+ }
+
+ // Borders
+ const float b = size / 25.0f;
+ const float bd = size / 2.0f - b;
+ for (PxU32 y = 0; y<size; y++)
+ {
+ for (PxU32 x = 0; x<size; x++)
+ {
+ const float x0 = fabsf(x - cx);
+ const float y0 = fabsf(y - cy);
+ if (x0 > bd || y0 > bd)
+ {
+ float a0 = (x0 - bd) / b;
+ float a1 = (y0 - bd) / b;
+ if (a1 > a0)
+ a0 = a1;
+ mTerrainVB[(y + x*size) * 9 + 1] = 20.0f*a0 + mTerrainVB[(y + x*size) * 9 + 1] * (1 - a0);
+ }
+ }
+ }
+
+ // Sobel filter
+ for (PxU32 y = 1; y<size - 1; y++)
+ {
+ for (PxU32 x = 1; x<size - 1; x++)
+ {
+ // 1 0 -1
+ // 2 0 -2
+ // 1 0 -1
+ float dx;
+ dx = mTerrainVB[((x - 1) + (y - 1)*size) * 9 + 1];
+ dx -= mTerrainVB[((x + 1) + (y - 1)*size) * 9 + 1];
+ dx += 2.0f*mTerrainVB[((x - 1) + (y + 0)*size) * 9 + 1];
+ dx -= 2.0f*mTerrainVB[((x + 1) + (y + 0)*size) * 9 + 1];
+ dx += mTerrainVB[((x - 1) + (y + 1)*size) * 9 + 1];
+ dx -= mTerrainVB[((x + 1) + (y + 1)*size) * 9 + 1];
+
+ // 1 2 1
+ // 0 0 0
+ // -1 -2 -1
+ float dy;
+ dy = mTerrainVB[((x - 1) + (y - 1)*size) * 9 + 1];
+ dy += 2.0f*mTerrainVB[((x + 0) + (y - 1)*size) * 9 + 1];
+ dy += mTerrainVB[((x + 1) + (y - 1)*size) * 9 + 1];
+ dy -= mTerrainVB[((x - 1) + (y + 1)*size) * 9 + 1];
+ dy -= 2.0f*mTerrainVB[((x + 0) + (y + 1)*size) * 9 + 1];
+ dy -= mTerrainVB[((x + 1) + (y + 1)*size) * 9 + 1];
+
+ const float nx = dx / width*0.15f;
+ const float ny = 1.0f;
+ const float nz = dy / width*0.15f;
+
+ const float len = sqrtf(nx*nx + ny*ny + nz*nz);
+
+ mTerrainVB[(x + y*size) * 9 + 3] = nx / len;
+ mTerrainVB[(x + y*size) * 9 + 4] = ny / len;
+ mTerrainVB[(x + y*size) * 9 + 5] = nz / len;
+ }
+ }
+
+ // Static lighting (two directional lights)
+ const float l0[3] = { 0.25f / 0.8292f, 0.75f / 0.8292f, 0.25f / 0.8292f };
+ const float l1[3] = { 0.65f / 0.963f, 0.55f / 0.963f, 0.45f / 0.963f };
+ //const float len = sqrtf(l1[0]*l1[0]+l1[1]*l1[1]+l1[2]*l1[2]);
+ for (PxU32 y = 0; y<size; y++)
+ {
+ for (PxU32 x = 0; x<size; x++)
+ {
+ const float nx = mTerrainVB[(x + y*size) * 9 + 3], ny = mTerrainVB[(x + y*size) * 9 + 4], nz = mTerrainVB[(x + y*size) * 9 + 5];
+
+ const float a = 0.3f;
+ float dot0 = l0[0] * nx + l0[1] * ny + l0[2] * nz;
+ float dot1 = l1[0] * nx + l1[1] * ny + l1[2] * nz;
+ if (dot0 < 0.0f) { dot0 = 0.0f; }
+ if (dot1 < 0.0f) { dot1 = 0.0f; }
+
+ const float l = dot0*0.7f + dot1*0.3f;
+
+ mTerrainVB[(x + y*size) * 9 + 6] = mTerrainVB[(x + y*size) * 9 + 6] * (l + a);
+ mTerrainVB[(x + y*size) * 9 + 7] = mTerrainVB[(x + y*size) * 9 + 7] * (l + a);
+ mTerrainVB[(x + y*size) * 9 + 8] = mTerrainVB[(x + y*size) * 9 + 8] * (l + a);
+
+ /*mTerrainVB[(x+y*size)*9+3] = 0.0f;
+ mTerrainVB[(x+y*size)*9+4] = -1.0f;
+ mTerrainVB[(x+y*size)*9+5] = 0.0f;*/
+ }
+ }
+
+ // Index buffers
+ const PxU32 maxNbTerrainTriangles = (size - 1)*(size - 1) * 2;
+
+ mNbIB = 4;
+ mRenderMaterial[0] = MATERIAL_TERRAIN_MUD;
+ mRenderMaterial[1] = MATERIAL_ROAD_TARMAC;
+ mRenderMaterial[2] = MATERIAL_ROAD_SNOW;
+ mRenderMaterial[3] = MATERIAL_ROAD_GRASS;
+
+ for (PxU32 i = 0; i<mNbIB; i++)
+ {
+ mIB[i] = new PxU32[(sizeof(PxU32)*maxNbTerrainTriangles * 3)];
+ mNbTriangles[i] = 0;
+ }
+
+ for (PxU32 j = 0; j<size - 1; j++)
+ {
+ for (PxU32 i = 0; i<size - 1; i++)
+ {
+ PxU32 tris[6];
+ tris[0] = i + j*size; tris[1] = i + (j + 1)*size; tris[2] = i + 1 + (j + 1)*size;
+ tris[3] = i + j*size; tris[4] = i + 1 + (j + 1)*size; tris[5] = i + 1 + j*size;
+
+ for (PxU32 t = 0; t<2; t++)
+ {
+ const PxU32 vt0 = tagBuffer[tris[t * 3 + 0]];
+ const PxU32 vt1 = tagBuffer[tris[t * 3 + 1]];
+ const PxU32 vt2 = tagBuffer[tris[t * 3 + 2]];
+
+ PxU32 buffer = 0;
+ if (vt0 == vt1 && vt0 == vt2)
+ buffer = vt0;
+
+ mIB[buffer][mNbTriangles[buffer] * 3 + 0] = tris[t * 3 + 0];
+ mIB[buffer][mNbTriangles[buffer] * 3 + 1] = tris[t * 3 + 1];
+ mIB[buffer][mNbTriangles[buffer] * 3 + 2] = tris[t * 3 + 2];
+ mNbTriangles[buffer]++;
+ }
+ }
+ }
+
+ delete[] tagBuffer;
+ delete[] doneBuffer;
+}
+
+
+void SceneVehicle::newMesh(const RAWMesh& data)
+{
+
+ PxU32 carPart = 0xffffffff;
+ if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_CHASSIS]))
+ {
+ carPart = CAR_PART_CHASSIS;
+
+ //Find the min and max of the set of verts.
+ PxVec3 vmin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
+ PxVec3 vmax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
+ for (PxU32 i = 0; i < data.mNbVerts; i++)
+ {
+ vmin.x = PxMin(vmin.x, data.mVerts[i].x);
+ vmin.y = PxMin(vmin.y, data.mVerts[i].y);
+ vmin.z = PxMin(vmin.z, data.mVerts[i].z);
+ vmax.x = PxMax(vmax.x, data.mVerts[i].x);
+ vmax.y = PxMax(vmax.y, data.mVerts[i].y);
+ vmax.z = PxMax(vmax.z, data.mVerts[i].z);
+ }
+
+ //Make sure the chassis has an aabb that is centred at (0,0,0).
+ //This just makes it a lot easier to set the centre of mass offset relative to the centre of the actor.
+ gChassisMeshTransform = (vmin + vmax)*0.5f;
+
+ //Make sure wheel offsets are symmetric (they are not quite symmetric left to right or front to back).
+ gWheelCentreOffsets4[CAR_PART_FRONT_LEFT_WHEEL].x = -gWheelCentreOffsets4[CAR_PART_FRONT_RIGHT_WHEEL].x;
+ gWheelCentreOffsets4[CAR_PART_REAR_LEFT_WHEEL].x = -gWheelCentreOffsets4[CAR_PART_REAR_RIGHT_WHEEL].x;
+ gWheelCentreOffsets4[CAR_PART_FRONT_LEFT_WHEEL].y = gWheelCentreOffsets4[CAR_PART_REAR_LEFT_WHEEL].y;
+ gWheelCentreOffsets4[CAR_PART_FRONT_RIGHT_WHEEL].y = gWheelCentreOffsets4[CAR_PART_REAR_RIGHT_WHEEL].y;
+
+ //Make an adjustment so that the the centre of the four wheels is at the origin.
+ //Again, this just makes it a lot easier to set the centre of mass because we have a known point
+ //that represents the origin. Also, it kind of makes sense that the default centre of mass is at the
+ //centre point of the wheels.
+ PxF32 wheelOffsetZ = 0;
+ for (PxU32 i = 0; i <= CAR_PART_REAR_RIGHT_WHEEL; i++)
+ {
+ wheelOffsetZ += gWheelCentreOffsets4[i].z;
+ }
+ wheelOffsetZ *= 0.25f;
+ gChassisMeshTransform.z += wheelOffsetZ;
+
+ //Reposition the mesh verts.
+ PxVec3* verts = const_cast<PxVec3*>(data.mVerts);
+ for (PxU32 i = 0; i < data.mNbVerts; i++)
+ {
+ verts[i] -= gChassisMeshTransform;
+ }
+
+ //Need a convex mesh for the chassis.
+ gChassisConvexMesh = createChassisConvexMesh(data.mVerts, data.mNbVerts, getPhysics(), getCooking());
+ }
+ else if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_FRONT_LEFT_WHEEL]))
+ {
+ carPart = CAR_PART_FRONT_LEFT_WHEEL;
+ gWheelConvexMeshes4[CAR_PART_FRONT_LEFT_WHEEL] = createWheelConvexMesh(data.mVerts, data.mNbVerts, getPhysics(), getCooking());
+ }
+ else if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_FRONT_RIGHT_WHEEL]))
+ {
+ carPart = CAR_PART_FRONT_RIGHT_WHEEL;
+ gWheelConvexMeshes4[CAR_PART_FRONT_RIGHT_WHEEL] = createWheelConvexMesh(data.mVerts, data.mNbVerts, getPhysics(), getCooking());
+ }
+ else if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_REAR_LEFT_WHEEL]))
+ {
+ carPart = CAR_PART_REAR_LEFT_WHEEL;
+ gWheelConvexMeshes4[CAR_PART_REAR_LEFT_WHEEL] = createWheelConvexMesh(data.mVerts, data.mNbVerts, getPhysics(), getCooking());
+ }
+ else if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_REAR_RIGHT_WHEEL]))
+ {
+ carPart = CAR_PART_REAR_RIGHT_WHEEL;
+ gWheelConvexMeshes4[CAR_PART_REAR_RIGHT_WHEEL] = createWheelConvexMesh(data.mVerts, data.mNbVerts, getPhysics(), getCooking());
+ }
+ else if (0 == Ps::strcmp(data.mName, gCarPartNames[CAR_PART_WINDOWS]))
+ {
+ carPart = CAR_PART_WINDOWS;
+ //Take the offset that was required to centre the chassis and apply it to everything that is dependent on the chassis transform.
+ PxVec3* verts = const_cast<PxVec3*>(data.mVerts);
+ for (PxU32 i = 0; i<data.mNbVerts; i++)
+ {
+ verts[i] -= gChassisMeshTransform;
+ }
+ for (PxU32 i = 0; i <= CAR_PART_REAR_RIGHT_WHEEL; i++)
+ {
+ gWheelCentreOffsets4[i] -= gChassisMeshTransform;
+ }
+ }
+
+ gCarPartRenderMesh[carPart] = createRenderMesh(data);
+
+ //Store the wheel offsets from the centre.
+ for (PxU32 i = 0; i <= CAR_PART_REAR_RIGHT_WHEEL; i++)
+ {
+ if (0 == Ps::strcmp(data.mName, gCarPartNames[i]))
+ {
+ // gWheelCentreOffsets4[i] = meshActor->getTransform().p;
+
+ gWheelCentreOffsets4[i] = data.mTransform.p;
+ gWheelCentreOffsets4[i].y -= gSuspensionShimHeight;
+
+ //The left and right wheels seem to be mixed up.
+ //Swap them to correct this.
+ gWheelCentreOffsets4[i].x *= -1.0f;
+ }
+ }
+
+}
+
+
+void SceneVehicle::importRAWFile(const char* fname, PxReal scale, bool recook)
+{
+
+ bool status = loadRAWfile(FindMediaFile(fname, mResourcePath), *this, scale);
+ if (!status)
+ {
+ std::string msg = "Sample can not load file ";
+ msg += FindMediaFile(fname, mResourcePath);
+ msg += "\n";
+ printf("%s", msg.c_str());
+ }
+}
+
+void SceneVehicle::createVehicle(PxPhysics* pxPhysics)
+{
+ //Initialise the sdk.
+
+ mVehicleManager.init(getPhysics(), (const PxMaterial**)mStandardMaterials, mVehicleDrivableSurfaceTypes);
+
+ importRAWFile("car2.raw", 1.0f);
+
+ mVehicleManager.create4WVehicle(getScene(), getPhysics(), getCooking(), *mChassisMaterialDrivable, gChassisMass, gWheelCentreOffsets4, gChassisConvexMesh,
+ gWheelConvexMeshes4, gPlayerCarStartTransforms[0], true);
+}
+
+//-----------------------------------------------------------------------------------------------
+
+void SceneVehicle::newMaterial(const RAWMaterial& data)
+{
+ ShaderMaterial& materials = mCarPartMaterial[mNumMaterials++];
+ materials.init(mTextureIds[mNumMaterials - 1]);
+ //materials.setColor(data.mDiffuseColor.x, data.mDiffuseColor.y, data.mDiffuseColor.z);
+ materials.setColor(1, 0, 0);
+ materials.diffuseCoeff = 0.5f;
+ materials.specularCoeff = 0.707f;
+}
+
+//-----------------------------------------------------------------------------------------------
+
+void SceneVehicle::newTexture(const RAWTexture& data)
+{
+ char fullPath[512];
+ int len = strlen(data.mName);
+ for (PxU32 i = 0; i < len-4; ++i)
+ {
+ fullPath[i] = data.mName[i];
+ }
+ fullPath[len - 4] = '\0';
+ strcat(fullPath, ".bmp");
+
+
+ string fName = FindMediaFile(fullPath, mResourcePath);
+ //string fName = FindMediaFile("car02_diffuse2.bmp", mResourcePath);
+
+ mTextureIds[mNumTextures++] = loadImgTexture(fName.c_str());
+
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::handleMouseButton(int button, int state, int x, int y)
+{
+ mMouseX = x;
+ mMouseY = y;
+
+ mMouseDown = (state == GLUT_DOWN);
+
+ PxVec3 orig, dir;
+ getMouseRay(x, y, orig, dir);
+
+ if (glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+ if (mSimScene)
+ mSimScene->pickStart(orig, dir);
+ }
+ }
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ if (mSimScene)
+ mSimScene->pickRelease();
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::handleMouseMotion(int x, int y)
+{
+ mMouseX = x;
+ mMouseY = y;
+
+ if (mSimScene && mSimScene->getPickActor() != NULL) {
+ PxVec3 orig, dir;
+ getMouseRay(x, y, orig, dir);
+ mSimScene->pickMove(orig, dir);
+ }
+}
+//ofstream orays("ray.txt");
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::handleKeyDown(unsigned char key, int x, int y)
+{
+ if (mCameraDisable)
+ {
+ switch (key)
+ {
+ case ' ':
+ {
+ float vel = 1.0f;
+ PxVec3 orig, dir;
+ getMouseRay(mMouseX, mMouseY, orig, dir);
+ /*
+ float sx = 0.0f, sy = 30.0f, sz = 0.0f;
+ int nx = 10;
+ int ny = 10;
+ float dx = 1.0f;
+ for (int i = 0; i < ny; i++) {
+ for (int j = 0; j < nx; j++) {
+ shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f));
+ }
+ }
+
+ */
+ shoot(mCameraPos, dir);
+ //orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n";
+ //orays.flush();
+ //printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z);
+ break;
+ }
+ case 'w':
+ case 'W':
+ {
+ mControlInputs.setAccelKeyPressed(true);
+ break;
+ }
+ case 's':
+ case 'S':
+ {
+ mControlInputs.setBrakeKeyPressed(true);
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ mControlInputs.setSteerRightKeyPressed(true);
+
+ break;
+ }
+ case 'd':
+ case 'D':
+ {
+ mControlInputs.setSteerLeftKeyPressed(true);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::handleKeyUp(unsigned char key, int x, int y)
+{
+ if (mCameraDisable)
+ {
+ switch (key)
+ {
+ case 'v':
+ if (mSimScene) mSimScene->toggleDebugDrawing(); break;
+ case ' ':
+ {
+ mGunActive = false;
+ }
+ case 'w':
+ case 'W':
+ {
+ mControlInputs.setAccelKeyPressed(false);
+ break;
+ }
+ case 's':
+ case 'S':
+ {
+ mControlInputs.setBrakeKeyPressed(false);
+ break;
+ }
+ case 'a':
+ case 'A':
+ {
+ mControlInputs.setSteerRightKeyPressed(false);
+
+ break;
+ }
+ case 'd':
+ case 'D':
+ {
+ mControlInputs.setSteerLeftKeyPressed(false);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::handleSpecialKey(unsigned char key, int x, int y)
+{
+ SceneKapla::handleSpecialKey(key, x, y);
+ switch (key)
+ {
+ case GLUT_KEY_F7: {
+ mCameraDisable = !mCameraDisable;
+ break;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void SceneVehicle::handleGamepadButton(int button, bool state)
+{
+ if (mCameraDisable)
+ {
+ switch (button)
+ {
+ case SampleViewerGamepad::GAMEPAD_A:
+ {
+ float vel = 1.0f;
+ PxVec3 orig, dir;
+ getMouseRay(mMouseX, mMouseY, orig, dir);
+ /*
+ float sx = 0.0f, sy = 30.0f, sz = 0.0f;
+ int nx = 10;
+ int ny = 10;
+ float dx = 1.0f;
+ for (int i = 0; i < ny; i++) {
+ for (int j = 0; j < nx; j++) {
+ shoot(PxVec3(sx+j*dx, sy, sz + i*dx), PxVec3(0.0f,1.0f,0.0f));
+ }
+ }
+
+ */
+ shoot(mCameraPos, dir);
+ //orays<<"{"<<mCameraPos.x<<","<<mCameraPos.y<<","<<mCameraPos.z<<","<<dir.x<<","<<dir.y<<","<<dir.z<<"},\n";
+ //orays.flush();
+ //printf("{%f,%f,%f,%f,%f,%f},\n ", mCameraPos.x, mCameraPos.y, mCameraPos.z, dir.x, dir.y, dir.z);
+ break;
+ }
+ case SampleViewerGamepad::GAMEPAD_DPAD_LEFT:
+ {
+ mControlInputs.setGearDown(state);
+ break;
+ }
+ case SampleViewerGamepad::GAMEPAD_DPAD_RIGHT:
+ {
+ mControlInputs.setGearUp(state);
+ break;
+ }
+ case SampleViewerGamepad::GAMEPAD_DPAD_DOWN:
+ {
+ mControlInputs.setHandbrake(state);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void SceneVehicle::handleGamepadAxis(int axis, float val)
+{
+ switch (axis)
+ {
+ case SampleViewerGamepad::GAMEPAD_LEFT_STICK_X:
+ {
+ mControlInputs.setSteer(-val);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+
+void SceneVehicle::handleGamepadTrigger(int trigger, float val)
+{
+ if(trigger == SampleViewerGamepad::GAMEPAD_RIGHT_SHOULDER_TRIGGER)
+ {
+ mControlInputs.setAccel(val);
+ }
+ else
+ {
+ if (trigger == SampleViewerGamepad::GAMEPAD_LEFT_SHOULDER_TRIGGER)
+ {
+ mControlInputs.setBrake(val);
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void SceneVehicle::getCamera(PxVec3& pos, PxVec3& dir)
+{
+ if (mCameraDisable)
+ {
+ pos = mCameraPos;
+ dir = mCameraDir.getNormalized();
+ }
+
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::preSim(float dt)
+{
+ SceneKapla::preSim(dt);
+
+ if (createVehicleDemo)
+ {
+ mVehicleController.setCarKeyboardInputs(
+ mControlInputs.getAccelKeyPressed(),
+ mControlInputs.getBrakeKeyPressed(),
+ mControlInputs.getHandbrakeKeyPressed(),
+ mControlInputs.getSteerLeftKeyPressed(),
+ mControlInputs.getSteerRightKeyPressed(),
+ mControlInputs.getGearUpKeyPressed(),
+ mControlInputs.getGearDownKeyPressed());
+
+ mVehicleController.setCarGamepadInputs(
+ mControlInputs.getAccel(),
+ mControlInputs.getBrake(),
+ mControlInputs.getSteer(),
+ mControlInputs.getGearUp(),
+ mControlInputs.getGearDown(),
+ mControlInputs.getHandbrake());
+
+ mVehicleController.update(dt, mVehicleManager.getWheelQueryResult(), *mVehicleManager.getVehicle());
+ }
+
+
+
+}
+
+// ----------------------------------------------------------------------------------------------
+void SceneVehicle::postSim(float dt)
+{
+
+ SceneKapla::postSim(dt);
+
+ if (createVehicleDemo)
+ {
+ //update vehicle
+ //mVehicleManager.suspensionRaycasts(&getScene());
+ mVehicleManager.suspensionSweeps(&getScene());
+
+ if (dt > 0.f)
+ {
+ mVehicleManager.update(dt, getScene().getGravity());
+ }
+
+ //Update the camera.
+ mCameraController.setInputs(
+ mControlInputs.getRotateY(),
+ mControlInputs.getRotateZ());
+
+ mCameraController.update(dt, *mVehicleManager.getVehicle(), getScene());
+
+ setCamera(mCameraController.getCameraPos(), mCameraController.getCameraTar() - mCameraController.getCameraPos(), PxVec3(0.f, 1.f, 0.f), 40.f);
+ }
+
+
+}
+
+void SceneVehicle::renderCar(bool useShader)
+{
+ PxRigidDynamic* dyn = mVehicleManager.getVehicle()->getRigidDynamicActor();
+
+ PxShape* shapes[5];
+
+ dyn->getShapes(shapes, 5);
+
+ PxMat44 bodyGlobalPose(dyn->getGlobalPose());// PxShapeExt::getGlobalPose(*shapes[i], *dyn));
+
+ if (useShader)
+ mDefaultShader->activate(mCarPartMaterial[0]);
+
+ for (PxU32 i = 0; i < 5; ++i)
+ {
+
+ PxMat44 globalPose(PxShapeExt::getGlobalPose(*shapes[i], *dyn));
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glPushMatrix();
+
+ glMultMatrixf(&globalPose.column0.x);
+
+ gCarPartRenderMesh[i]->drawVBOIBO();
+
+ glPopMatrix();
+
+ }
+
+ if (useShader)
+ mDefaultShader->deactivate();
+
+
+ if (useShader)
+ mDefaultShader->activate(mCarPartMaterial[1]);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glPushMatrix();
+
+ glMultMatrixf(&bodyGlobalPose.column0.x);
+
+ gCarPartRenderMesh[5]->drawVBOIBO();
+
+ glPopMatrix();
+
+ if (useShader)
+ mDefaultShader->deactivate();
+
+}
+
+void SceneVehicle::render(bool useShader)
+{
+ if (createVehicleDemo)
+ renderCar(useShader);
+
+ SceneKapla::render(useShader);
+}
+
+
+PxFilterFlags VehicleFilterShader
+(PxFilterObjectAttributes attributes0, PxFilterData filterData0,
+PxFilterObjectAttributes attributes1, PxFilterData filterData1,
+PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
+{
+ PX_UNUSED(attributes0);
+ PX_UNUSED(attributes1);
+ PX_UNUSED(constantBlock);
+ PX_UNUSED(constantBlockSize);
+
+ if ((0 == (filterData0.word0 & filterData1.word1)) && (0 == (filterData1.word0 & filterData0.word1)))
+ {
+ if (filterData0.word0 != 0 && filterData1.word0 != 0)
+ return PxFilterFlag::eSUPPRESS;
+ }
+
+ pairFlags = PxPairFlag::eCONTACT_DEFAULT;
+ pairFlags |= PxPairFlags(PxU16(filterData0.word2 | filterData1.word2));
+
+ return PxFilterFlags();
+
+ //pairFlags = PxPairFlag::eDETECT_DISCRETE_CONTACT;
+ //return PxFilterFlags();
+}
+
+struct ActorUserData
+{
+ ActorUserData()
+ : vehicle(NULL),
+ actor(NULL)
+ {
+ }
+
+ const PxVehicleWheels* vehicle;
+ const PxActor* actor;
+};
+
+struct ShapeUserData
+{
+ ShapeUserData()
+ : isWheel(false),
+ wheelId(0xffffffff)
+ {
+ }
+
+ bool isWheel;
+ PxU32 wheelId;
+};
+
+ActorUserData gActorUserData;
+ShapeUserData gShapeUserDatas[PX_MAX_NB_WHEELS];
+
+#define POINT_REJECT_ANGLE 45.0f*PxPi/180.0f
+#define NORMAL_REJECT_ANGLE 30.0f*PxPi/180.0f
+#define WHEEL_TANGENT_VELOCITY_MULTIPLIER 0.1f
+
+//The class WheelContactModifyCallback identifies and modifies rigid body contacts
+//that involve a wheel. Contacts that can be identified and managed by the suspension
+//system are ignored. Any contacts that remain are modified to account for the rotation
+//speed of the wheel around the rolling axis.
+class WheelContactModifyCallback : public PxContactModifyCallback
+{
+public:
+
+ WheelContactModifyCallback()
+ : PxContactModifyCallback()
+ {
+ }
+
+ ~WheelContactModifyCallback(){}
+
+ void onContactModify(PxContactModifyPair* const pairs, PxU32 count)
+ {
+ for (PxU32 i = 0; i < count; i++)
+ {
+ const PxRigidActor** actors = pairs[i].actor;
+ const PxShape** shapes = pairs[i].shape;
+
+ //Search for actors that represent vehicles and shapes that represent wheels.
+ for (PxU32 j = 0; j < 2; j++)
+ {
+ const PxActor* actor = actors[j];
+ if (actor->userData && (static_cast<ActorUserData*>(actor->userData))->vehicle)
+ {
+ const PxVehicleWheels* vehicle = (static_cast<ActorUserData*>(actor->userData))->vehicle;
+ PX_ASSERT(vehicle->getRigidDynamicActor() == actors[j]);
+
+ const PxShape* shape = shapes[j];
+ if (shape->userData && (static_cast<ShapeUserData*>(shape->userData))->isWheel)
+ {
+ const PxU32 wheelId = (static_cast<ShapeUserData*>(shape->userData))->wheelId;
+ PX_ASSERT(wheelId < vehicle->mWheelsSimData.getNbWheels());
+
+ //Modify wheel contacts.
+ PxVehicleModifyWheelContacts(*vehicle, wheelId, WHEEL_TANGENT_VELOCITY_MULTIPLIER, 0.5f, pairs[i]);
+ }
+ }
+ }
+ }
+ }
+
+
+private:
+
+};
+WheelContactModifyCallback gWheelContactModifyCallback;
+
+//----------------------------------------------------------------------------------------------------
+void SceneVehicle::customizeSceneDesc(PxSceneDesc& sceneDesc)
+{
+ sceneDesc.filterShader = VehicleFilterShader; //Set the filter shader
+ sceneDesc.contactModifyCallback = &gWheelContactModifyCallback; //Enable contact modification
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicle.h b/KaplaDemo/samples/sampleViewer3/SceneVehicle.h
new file mode 100644
index 00000000..ae74a54f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicle.h
@@ -0,0 +1,98 @@
+#ifndef SCENE_VEHICLE_H
+#define SCENE_VEHICLE_H
+
+#include "SceneKapla.h"
+#include "vehicle/PxVehicleWheels.h"
+#include "RawLoader.h"
+#include "VehicleManager.h"
+#include "VehicleController.h"
+#include "VehicleControlInputs.h"
+#include "VehicleCameraController.h"
+
+using namespace physx;
+
+// ---------------------------------------------------------------------
+class SceneVehicle : public SceneKapla, public RAWImportCallback
+{
+public:
+ SceneVehicle(PxPhysics* pxPhysics, PxCooking *pxCooking, bool isGrb,
+ Shader *defaultShader, const char *resourcePath, float slowMotionFactor);
+
+ virtual ~SceneVehicle(){}
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // Implements RAWImportCallback
+ virtual void newMaterial(const RAWMaterial&);
+ virtual void newMesh(const RAWMesh&);
+ virtual void newTexture(const RAWTexture&);
+ virtual void newShape(const RAWShape&){}
+ virtual void newHelper(const RAWHelper&){}
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+
+ virtual void handleMouseButton(int button, int state, int x, int y);
+ virtual void handleMouseMotion(int x, int y);
+
+ virtual void handleKeyDown(unsigned char key, int x, int y);
+ virtual void handleKeyUp(unsigned char key, int x, int y);
+ virtual void handleSpecialKey(unsigned char key, int x, int y);
+
+ virtual void handleGamepadButton(int button, bool state);
+ virtual void handleGamepadAxis(int axis, float x);
+ virtual void handleGamepadTrigger(int trigger, float x);
+
+ virtual void getCamera(PxVec3& pos, PxVec3& dir);
+
+ virtual void preSim(float dt);
+ virtual void postSim(float dt);
+
+ virtual void render(bool useShader);
+
+ virtual void customizeSceneDesc(PxSceneDesc& desc);
+
+ virtual void onInit(PxScene* pxScene);
+
+ virtual void setScene(PxScene* pxScene);
+
+private:
+
+ void renderCar(bool useShader);
+ void createStandardMaterials();
+ void createVehicle(PxPhysics* pxPhysics);
+ void createTerrain(PxU32 size, float width, float chaos);
+ void importRAWFile(const char* relativePath, PxReal scale, bool recook = false);
+
+ enum
+ {
+ MAX_NUM_INDEX_BUFFERS = 16
+ };
+ PxU32 mNbIB;
+ PxU32* mIB[MAX_NUM_INDEX_BUFFERS];
+ PxU32 mNbTriangles[MAX_NUM_INDEX_BUFFERS];
+ PxU32 mRenderMaterial[MAX_NUM_INDEX_BUFFERS];
+
+ PxVehicleDrivableSurfaceType mVehicleDrivableSurfaceTypes[MAX_NUM_INDEX_BUFFERS];
+ PxMaterial* mStandardMaterials[MAX_NUM_INDEX_BUFFERS];
+
+ PxMaterial* mChassisMaterialDrivable;
+ PxMaterial* mChassisMaterialNonDrivable;
+
+ VehicleManager mVehicleManager;
+ VehicleController mVehicleController;
+ VehicleControlInputs mControlInputs;
+ VehicleCameraController mCameraController;
+
+ //Terrain
+ PxF32* mTerrainVB;
+ PxU32 mNbTerrainVerts;
+
+ //render car
+ GLuint mTextureIds[2];
+ ShaderMaterial mCarPartMaterial[2];
+
+ PxU32 mNumMaterials;
+ PxU32 mNumTextures;
+};
+#endif // SCENE_BOXES_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.cpp b/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.cpp
new file mode 100644
index 00000000..25c81d82
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.cpp
@@ -0,0 +1,214 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "SceneVehicleCooking.h"
+#include "PxTkStream.h"
+#include "extensions/PxDefaultStreams.h"
+#include "glmesh.h"
+#include "RawLoader.h"
+
+using namespace physx;
+
+PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
+{
+ // Create descriptor for convex mesh
+ PxConvexMeshDesc convexDesc;
+ convexDesc.points.count = numVerts;
+ convexDesc.points.stride = sizeof(PxVec3);
+ convexDesc.points.data = verts;
+ convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+
+ PxConvexMesh* convexMesh = NULL;
+ PxDefaultMemoryOutputStream buf;
+ if (cooking.cookConvexMesh(convexDesc, buf))
+ {
+ PxDefaultMemoryInputData id(buf.getData(), buf.getSize());
+ convexMesh = physics.createConvexMesh(id);
+ }
+
+ return convexMesh;
+}
+
+PxConvexMesh* createCuboidConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
+{
+ PxVec3 verts[8] =
+ {
+ PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
+ PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
+ PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
+ PxVec3(-halfExtents.x, +halfExtents.y, +halfExtents.z),
+ PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
+ PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
+ PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z),
+ PxVec3(+halfExtents.x, +halfExtents.y, +halfExtents.z)
+ };
+ PxU32 numVerts = 8;
+
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+PxConvexMesh* createWedgeConvexMesh(const PxVec3& halfExtents, PxPhysics& physics, PxCooking& cooking)
+{
+ PxVec3 verts[6] =
+ {
+ PxVec3(-halfExtents.x, -halfExtents.y, -halfExtents.z),
+ PxVec3(-halfExtents.x, -halfExtents.y, +halfExtents.z),
+ PxVec3(-halfExtents.x, +halfExtents.y, -halfExtents.z),
+ PxVec3(+halfExtents.x, -halfExtents.y, -halfExtents.z),
+ PxVec3(+halfExtents.x, -halfExtents.y, +halfExtents.z),
+ PxVec3(+halfExtents.x, +halfExtents.y, -halfExtents.z)
+ };
+ PxU32 numVerts = 6;
+
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+PxConvexMesh* createCylinderConvexMesh(const PxF32 width, const PxF32 radius, const PxU32 numCirclePoints, PxPhysics& physics, PxCooking& cooking)
+{
+#define MAX_NUM_VERTS_IN_CIRCLE 16
+ PX_ASSERT(numCirclePoints<MAX_NUM_VERTS_IN_CIRCLE);
+ PxVec3 verts[2 * MAX_NUM_VERTS_IN_CIRCLE];
+ PxU32 numVerts = 2 * numCirclePoints;
+ const PxF32 dtheta = 2 * PxPi / (1.0f*numCirclePoints);
+ for (PxU32 i = 0; i<MAX_NUM_VERTS_IN_CIRCLE; i++)
+ {
+ const PxF32 theta = dtheta*i;
+ const PxF32 cosTheta = radius*PxCos(theta);
+ const PxF32 sinTheta = radius*PxSin(theta);
+ verts[2 * i + 0] = PxVec3(-0.5f*width, cosTheta, sinTheta);
+ verts[2 * i + 1] = PxVec3(+0.5f*width, cosTheta, sinTheta);
+ }
+
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+PxConvexMesh* createSquashedCuboidMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height1, const PxF32 height2, PxPhysics& physics, PxCooking& cooking)
+{
+ const PxF32 x = baseLength*0.5f;
+ const PxF32 z = baseDepth*0.5f;
+ PxVec3 verts[8] =
+ {
+ PxVec3(-x, -0.5f*height1, -z),
+ PxVec3(-x, -0.5f*height1, +z),
+ PxVec3(+x, -0.5f*height1, -z),
+ PxVec3(+x, -0.5f*height1, +z),
+ PxVec3(-x, -0.5f*height1 + height2, -z),
+ PxVec3(-x, +0.5f*height1, +z),
+ PxVec3(+x, -0.5f*height1 + height2, -z),
+ PxVec3(+x, +0.5f*height1, +z)
+ };
+ PxU32 numVerts = 8;
+
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+
+PxConvexMesh* createPrismConvexMesh(const PxF32 baseLength, const PxF32 baseDepth, const PxF32 height, PxPhysics& physics, PxCooking& cooking)
+{
+ const PxF32 x = baseLength*0.5f;
+ const PxF32 z = baseDepth*0.5f;
+
+ PxVec3 verts[6] =
+ {
+ PxVec3(-x, 0, -z),
+ PxVec3(-x, 0, +z),
+ PxVec3(+x, 0, -z),
+ PxVec3(+x, 0, +z),
+ PxVec3(-x, height, 0),
+ PxVec3(+x, height, 0),
+ };
+ PxU32 numVerts = 6;
+
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+PxConvexMesh* createChassisConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
+{
+ return createConvexMesh(verts, numVerts, physics, cooking);
+}
+
+PxConvexMesh* createWheelConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking)
+{
+ //Extract the wheel radius and width from the aabb of the wheel convex mesh.
+ PxVec3 wheelMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
+ PxVec3 wheelMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
+ for (PxU32 i = 0; i<numVerts; i++)
+ {
+ wheelMin.x = PxMin(wheelMin.x, verts[i].x);
+ wheelMin.y = PxMin(wheelMin.y, verts[i].y);
+ wheelMin.z = PxMin(wheelMin.z, verts[i].z);
+ wheelMax.x = PxMax(wheelMax.x, verts[i].x);
+ wheelMax.y = PxMax(wheelMax.y, verts[i].y);
+ wheelMax.z = PxMax(wheelMax.z, verts[i].z);
+ }
+ const PxF32 wheelWidth = wheelMax.x - wheelMin.x;
+ const PxF32 wheelRadius = PxMax(wheelMax.y, wheelMax.z);
+
+ return createCylinderConvexMesh(wheelWidth, wheelRadius, 8, physics, cooking);
+}
+
+GLMesh* createRenderMesh(const RAWMesh& data)
+{
+ GLMesh* mesh =new GLMesh(GL_TRIANGLES);
+ const PxU32 nbVerts = data.mNbVerts;
+ const PxU32 nbTris = data.mNbFaces;
+ mesh->vertices.resize(nbVerts);
+ mesh->normals.resize(nbVerts);
+ mesh->texCoords.resize(nbVerts * 2);
+ mesh->indices.resize(nbTris*3);
+
+ const PxU32* src = data.mIndices;
+
+ PxU32* indices = new PxU32[sizeof(PxU16)*nbTris * 3];
+ for (PxU32 i = 0; i<nbTris; i++)
+ {
+ indices[i * 3 + 0] = src[i * 3 + 0];
+ indices[i * 3 + 1] = src[i * 3 + 1];
+ indices[i * 3 + 2] = src[i * 3 + 2];
+ }
+
+
+ for (PxU32 i = 0; i < nbVerts; ++i)
+ {
+ mesh->vertices[i] = data.mVerts[i];
+ mesh->normals[i] = data.mVertexNormals[i];
+ mesh->texCoords[i*2] = data.mUVs[i*2];
+ mesh->texCoords[i * 2 + 1] = 1.f-data.mUVs[i*2+1];
+ }
+
+ for (PxU32 i = 0; i < nbTris * 3; ++i)
+ {
+ mesh->indices[i] = indices[i];
+ }
+
+ mesh->genVBOIBO();
+ mesh->updateVBOIBO(true);
+
+ return mesh;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.h b/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.h
new file mode 100644
index 00000000..c376cd32
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicleCooking.h
@@ -0,0 +1,50 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef VEHICLE_COOKING_H
+#define VEHICLE_COOKING_H
+
+#include "PxPhysicsAPI.h"
+
+class RAWMesh;
+class GLMesh;
+
+physx::PxConvexMesh* createConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createCuboidConvexMesh(const physx::PxVec3& halfExtents, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createWedgeConvexMesh(const physx::PxVec3& halfExtents, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createCylinderConvexMesh(const physx::PxF32 width, const physx::PxF32 radius, const physx::PxU32 numCirclePoints, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createSquashedCuboidMesh(const physx::PxF32 baseLength, const physx::PxF32 baseDepth, const physx::PxF32 height1, const physx::PxF32 height2, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createPrismConvexMesh(const physx::PxF32 baseLength, const physx::PxF32 baseDepth, const physx::PxF32 height, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createWheelConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
+physx::PxConvexMesh* createChassisConvexMesh(const physx::PxVec3* verts, const physx::PxU32 numVerts, physx::PxPhysics& physics, physx::PxCooking& cooking);
+
+GLMesh* createRenderMesh(const RAWMesh& data);
+
+
+#endif //VEHICLE_COOKING_H
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.cpp b/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.cpp
new file mode 100644
index 00000000..5b41709a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.cpp
@@ -0,0 +1,100 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "SceneVehicleSceneQuery.h"
+#include "vehicle/PxVehicleSDK.h"
+#include "PxFiltering.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+
+#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
+#define SIZEALIGN16(size) (((unsigned)(size)+15)&((unsigned)(~15)));
+
+void VehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
+{
+ CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
+ qryFilterData->word3 = (PxU32)VEHICLE_DRIVABLE_SURFACE;
+}
+
+void VehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData)
+{
+ CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
+ qryFilterData->word3 = (PxU32)VEHICLE_UNDRIVABLE_SURFACE;
+}
+
+void VehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData)
+{
+ CHECK_MSG(0 == qryFilterData->word3, "word3 is reserved for filter data for vehicle raycast queries");
+ qryFilterData->word3 = (PxU32)VEHICLE_UNDRIVABLE_SURFACE;
+}
+
+VehicleSceneQueryData* VehicleSceneQueryData::allocate(const PxU32 maxNumWheels)
+{
+
+ VehicleSceneQueryData* sqData = (VehicleSceneQueryData*)PX_ALLOC(sizeof(VehicleSceneQueryData), "PxVehicleNWSceneQueryData");
+ sqData->init();
+ sqData->mSqResults = (PxRaycastQueryResult*)PX_ALLOC(sizeof(PxRaycastQueryResult)*maxNumWheels, "PxRaycastQueryResult");
+ sqData->mNbSqResults = maxNumWheels;
+ sqData->mSqHitBuffer = (PxRaycastHit*)PX_ALLOC(sizeof(PxRaycastHit)*maxNumWheels, "PxRaycastHit");
+ sqData->mNumQueries = maxNumWheels;
+
+ sqData->mSqSweepResults = (PxSweepQueryResult*)PX_ALLOC(sizeof(PxSweepQueryResult) * maxNumWheels, "PxSweepQueryResult");
+ sqData->mNbSqSweepResults = maxNumWheels;
+ sqData->mSqSweepHitBuffer = (PxSweepHit*)PX_ALLOC(sizeof(PxSweepHit) * maxNumWheels, "PxSweepHit");
+ sqData->mNumSweepQueries = maxNumWheels;
+
+ return sqData;
+}
+
+void VehicleSceneQueryData::free()
+{
+ PX_FREE(this);
+}
+
+PxBatchQuery* VehicleSceneQueryData::setUpBatchedSceneQuery(PxScene* scene)
+{
+ PxBatchQueryDesc sqDesc(mNbSqResults, 0, 0);
+ sqDesc.queryMemory.userRaycastResultBuffer = mSqResults;
+ sqDesc.queryMemory.userRaycastTouchBuffer = mSqHitBuffer;
+ sqDesc.queryMemory.raycastTouchBufferSize = mNumQueries;
+ sqDesc.preFilterShader = mPreFilterShader;
+ return scene->createBatchQuery(sqDesc);
+}
+
+PxBatchQuery* VehicleSceneQueryData::setUpBatchedSceneQuerySweep(PxScene* scene)
+{
+ PxBatchQueryDesc sqDesc(0, mNbSqResults, 0);
+ sqDesc.queryMemory.userSweepResultBuffer = mSqSweepResults;
+ sqDesc.queryMemory.userSweepTouchBuffer = mSqSweepHitBuffer;
+ sqDesc.queryMemory.sweepTouchBufferSize = mNumQueries;
+ sqDesc.preFilterShader = mPreFilterShader;
+ return scene->createBatchQuery(sqDesc);
+}
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.h b/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.h
new file mode 100644
index 00000000..0f676444
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/SceneVehicleSceneQuery.h
@@ -0,0 +1,147 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef VEHICLE_UTILSCENEQUERY_H
+#define VEHICLE_UTILSCENEQUERY_H
+
+#include "common/PxPhysXCommonConfig.h"
+#include "vehicle/PxVehicleSDK.h"
+#include "foundation/PxPreprocessor.h"
+#include "PxScene.h"
+#include "PxBatchQueryDesc.h"
+
+using namespace physx;
+
+//Make sure that suspension raycasts only consider shapes flagged as drivable that don't belong to the owner vehicle.
+enum
+{
+ VEHICLE_DRIVABLE_SURFACE = 0xffff0000,
+ VEHICLE_UNDRIVABLE_SURFACE = 0x0000ffff
+};
+
+static PxQueryHitType::Enum SampleVehicleWheelRaycastPreFilter(
+ PxFilterData filterData0,
+ PxFilterData filterData1,
+ const void* constantBlock, PxU32 constantBlockSize,
+ PxHitFlags& queryFlags)
+{
+ //filterData0 is the vehicle suspension raycast.
+ //filterData1 is the shape potentially hit by the raycast.
+ PX_UNUSED(queryFlags);
+ PX_UNUSED(constantBlockSize);
+ PX_UNUSED(constantBlock);
+ PX_UNUSED(filterData0);
+ return ((0 == (filterData1.word3 & VEHICLE_DRIVABLE_SURFACE)) ? PxQueryHitType::eNONE : PxQueryHitType::eBLOCK);
+}
+
+
+//Set up query filter data so that vehicles can drive on shapes with this filter data.
+//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
+void VehicleSetupDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
+
+//Set up query filter data so that vehicles cannot drive on shapes with this filter data.
+//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
+void VehicleSetupNonDrivableShapeQueryFilterData(PxFilterData* qryFilterData);
+
+//Set up query filter data for the shapes of a vehicle to ensure that vehicles cannot drive on themselves
+//but can drive on the shapes of other vehicles.
+//Note that we have reserved word3 of the PxFilterData for vehicle raycast query filtering.
+void VehicleSetupVehicleShapeQueryFilterData(PxFilterData* qryFilterData);
+
+//Data structure for quick setup of scene queries for suspension raycasts.
+class VehicleSceneQueryData
+{
+public:
+
+ //Allocate scene query data for up to maxNumWheels suspension raycasts.
+ static VehicleSceneQueryData* allocate(const PxU32 maxNumWheels);
+
+ //Free allocated buffer for scene queries of suspension raycasts.
+ void free();
+
+ //Create a PxBatchQuery instance that will be used as a single batched raycast of multiple suspension lines of multiple vehicles
+ PxBatchQuery* setUpBatchedSceneQuery(PxScene* scene);
+
+ PxBatchQuery* setUpBatchedSceneQuerySweep(PxScene* scene);
+
+ //Get the buffer of scene query results that will be used by PxVehicleNWSuspensionRaycasts
+ PxRaycastQueryResult* getRaycastQueryResultBuffer() { return mSqResults; }
+
+ //Get the number of scene query results that have been allocated for use by PxVehicleNWSuspensionRaycasts
+ PxU32 getRaycastQueryResultBufferSize() const { return mNumQueries; }
+
+
+ //Get the buffer of scene query results that will be used by PxVehicleNWSuspensionRaycasts
+ PxSweepQueryResult* getSweepQueryResultBuffer() { return mSqSweepResults; }
+
+ //Get the number of scene query results that have been allocated for use by PxVehicleNWSuspensionRaycasts
+ PxU32 getSweepQueryResultBufferSize() const { return mNumSweepQueries; }
+
+ //Set the pre-filter shader
+ void setPreFilterShader(PxBatchQueryPreFilterShader preFilterShader) { mPreFilterShader = preFilterShader; }
+
+private:
+
+ //One result for each wheel.
+ PxRaycastQueryResult* mSqResults;
+ PxU32 mNbSqResults;
+
+ //One hit for each wheel.
+ PxRaycastHit* mSqHitBuffer;
+
+ PxSweepQueryResult* mSqSweepResults;
+ PxU32 mNbSqSweepResults;
+ PxSweepHit* mSqSweepHitBuffer;
+
+ //Filter shader used to filter drivable and non-drivable surfaces
+ PxBatchQueryPreFilterShader mPreFilterShader;
+
+ //Maximum number of suspension raycasts that can be supported by the allocated buffers
+ //assuming a single query and hit per suspension line.
+ PxU32 mNumQueries;
+
+ PxU32 mNumSweepQueries;
+
+ void init()
+ {
+ mPreFilterShader = SampleVehicleWheelRaycastPreFilter;
+ }
+
+ VehicleSceneQueryData()
+ {
+ init();
+ }
+
+ ~VehicleSceneQueryData()
+ {
+ }
+};
+
+
+#endif //SAMPLEVEHICLE_UTILSCENEQUERY_H
diff --git a/KaplaDemo/samples/sampleViewer3/Shader.cpp b/KaplaDemo/samples/sampleViewer3/Shader.cpp
new file mode 100644
index 00000000..b1d4a41f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Shader.cpp
@@ -0,0 +1,750 @@
+#include "Shader.h"
+#include <assert.h>
+//#define NOMINMAX
+#include <windows.h>
+
+#include "foundation/PxMat44.h"
+
+// --------------------------------------------------------------------------------------------
+Shader::Shader()
+{
+ mVertexShaderSource = NULL;
+ mVertexShaderSourceLength = 0;
+
+ mGeometryShaderSource = NULL;
+ mGeometryShaderSourceLength = 0;
+
+ mFragmentShaderSource = NULL;
+ mFragmentShaderSourceLength = 0;
+
+ mShaderProgram = 0;
+ mVertexShader = 0;
+ mGeometryShader = 0;
+ mFragmentShader = 0;
+
+ mErrorMessage = "";
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::loadShaders(const char* vertexShaderFile, const char* fragmentShaderFile)
+{
+ mErrorMessage = "";
+
+ if (vertexShaderFile == NULL || fragmentShaderFile == NULL)
+ return false;
+
+ if (!GLEW_VERSION_2_0)
+ return false;
+
+ if (!loadFile(vertexShaderFile, mVertexShaderSource, mVertexShaderSourceLength)) {
+ printf("Can't load vertex shader\n");
+ return false;
+ }
+
+ if (mGeometryShaderSource) {
+ free(mGeometryShaderSource);
+ mGeometryShaderSource = NULL;
+ mGeometryShaderSourceLength = 0;
+ }
+
+ if (!loadFile(fragmentShaderFile, mFragmentShaderSource, mFragmentShaderSourceLength)) {
+ printf("Can't load fragment shader\n");
+ return false;
+ }
+
+ if (!compileShaders()) {
+ printf("Can't compile shaders\n");
+ return false;
+ }
+
+ findVariables();
+
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::loadShaders(const char* vertexShaderFile, const char* geometryShaderFile, const char* fragmentShaderFile)
+{
+ mErrorMessage = "";
+
+ if (vertexShaderFile == NULL || geometryShaderFile == NULL || fragmentShaderFile == NULL)
+ return false;
+
+ if (!GLEW_VERSION_2_0)
+ return false;
+
+ if (!loadFile(vertexShaderFile, mVertexShaderSource, mVertexShaderSourceLength))
+ return false;
+
+ if (!loadFile(geometryShaderFile, mGeometryShaderSource, mGeometryShaderSourceLength))
+ return false;
+
+ if (!loadFile(fragmentShaderFile, mFragmentShaderSource, mFragmentShaderSourceLength))
+ return false;
+
+ if (!compileShaders())
+ return false;
+
+ findVariables();
+
+ return true;
+}
+
+
+
+
+// --------------------------------------------------------------------------------------------
+bool Shader::loadShaderCode(const char* vertexShaderCode, const char* fragmentShaderCode)
+{
+/*
+ mErrorMessage = "";
+
+ if (!GLEW_VERSION_2_0)
+ return false;
+
+ size_t size;
+
+ if (mVertexShaderSource != NULL)
+ free(mVertexShaderSource);
+
+ size = strlen(vertexShaderCode)+1;
+ mVertexShaderSourceLength = size-1;
+ mVertexShaderSource = (char*)malloc(size * sizeof(char));
+ strcpy_s(mVertexShaderSource, size, vertexShaderCode);
+
+ if (mFragmentShaderSource != NULL)
+ free(mFragmentShaderSource);
+
+ size = strlen(fragmentShaderCode)+1;
+ mFragmentShaderSourceLength = size-1;
+ mFragmentShaderSource = (char*)malloc(size * sizeof(char));
+ strcpy_s(mFragmentShaderSource, size, fragmentShaderCode);
+
+ if (!compileShaders())
+ return false;
+
+ findVariables();
+
+ return true;
+ */
+ return loadShaderCode(vertexShaderCode, NULL, fragmentShaderCode);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::loadShaderCode(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
+{
+ mErrorMessage = "";
+
+ if (!GLEW_VERSION_2_0)
+ return false;
+
+ size_t size;
+
+ if (mVertexShaderSource != NULL)
+ free(mVertexShaderSource);
+
+ size = strlen(vertexShaderCode)+1;
+ mVertexShaderSourceLength = size-1;
+ mVertexShaderSource = (char*)malloc(size * sizeof(char));
+ strcpy_s(mVertexShaderSource, size, vertexShaderCode);
+
+ if (mFragmentShaderSource != NULL)
+ free(mFragmentShaderSource);
+
+ if (mGeometryShaderSource != NULL) {
+ free(mGeometryShaderSource);
+ mGeometryShaderSource = NULL;
+ }
+
+ if (geometryShaderCode) {
+ size = strlen(geometryShaderCode)+1;
+ mGeometryShaderSourceLength = size-1;
+ mGeometryShaderSource = (char*)malloc(size * sizeof(char));
+ strcpy_s(mGeometryShaderSource, size, geometryShaderCode);
+
+ }
+
+ if (mFragmentShaderSource != NULL)
+ free(mFragmentShaderSource);
+
+ size = strlen(fragmentShaderCode)+1;
+ mFragmentShaderSourceLength = size-1;
+ mFragmentShaderSource = (char*)malloc(size * sizeof(char));
+ strcpy_s(mFragmentShaderSource, size, fragmentShaderCode);
+
+ if (!compileShaders())
+ return false;
+
+ findVariables();
+
+ return true;
+}
+
+
+// --------------------------------------------------------------------------------------------
+Shader::~Shader()
+{
+ deleteShaders();
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::deleteShaders()
+{
+ glDetachShader(mShaderProgram, mVertexShader);
+ glDeleteShader(mVertexShader);
+
+ glDetachShader(mShaderProgram, mFragmentShader);
+ glDeleteShader(mFragmentShader);
+
+
+ glDeleteProgram(mShaderProgram);
+
+ mVertexShader = 0;
+ mFragmentShader = 0;
+ mShaderProgram = 0;
+
+ free(mVertexShaderSource);
+ free(mFragmentShaderSource);
+
+ mVertexShaderSource = NULL;
+ mFragmentShaderSource = NULL;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::compileShaders()
+{
+ if (mShaderProgram != 0) {
+ glDetachShader(mShaderProgram, mVertexShader);
+ glDeleteShader(mVertexShader);
+
+
+ glDetachShader(mShaderProgram, mGeometryShader);
+ glDeleteShader(mGeometryShader);
+
+ glDetachShader(mShaderProgram, mFragmentShader);
+ glDeleteShader(mFragmentShader);
+
+ glDeleteProgram(mShaderProgram);
+
+ mVertexShader = 0;
+ mGeometryShader = 0;
+ mFragmentShader = 0;
+ mShaderProgram = 0;
+ }
+
+ bool ok = true;
+
+ mShaderProgram = glCreateProgram();
+ mVertexShader = glCreateShader(GL_VERTEX_SHADER);
+ if (mGeometryShaderSource) {
+ mGeometryShader = glCreateShader(GL_GEOMETRY_SHADER_ARB);
+ }
+ mFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+ mGlShaderAttributes = 0;
+
+ const GLchar* sources[3];
+ GLint lengths[3];
+
+ char header[128];
+ sprintf_s(header, 128, "\n");
+ sources[0] = header;
+ lengths[0] = strlen(header);
+
+ char footer[2] = "\n";
+ sources[2] = footer;
+ lengths[2] = strlen(footer);
+
+ sources[1] = mVertexShaderSource;
+ lengths[1] = mVertexShaderSourceLength;
+
+ glShaderSource(mVertexShader, 3, sources, lengths);
+ glCompileShader(mVertexShader);
+
+ sources[1] = mFragmentShaderSource;
+ lengths[1] = mFragmentShaderSourceLength;
+
+ glShaderSource(mFragmentShader, 3, sources, lengths);
+ glCompileShader(mFragmentShader);
+
+
+ if (mGeometryShaderSource) {
+ sources[1] = mGeometryShaderSource;
+ lengths[1] = mGeometryShaderSourceLength;
+
+ glShaderSource(mGeometryShader, 3, sources, lengths);
+ glCompileShader(mGeometryShader);
+
+ }
+
+ // error checking
+ int param;
+
+ glGetShaderiv(mVertexShader, GL_COMPILE_STATUS, &param);
+ if (param != GL_TRUE) {
+ getCompileError(mVertexShader);
+ deleteShaders();
+ return false;
+ }
+
+ if (mGeometryShader) {
+ glGetShaderiv(mGeometryShader, GL_COMPILE_STATUS, &param);
+ if (param != GL_TRUE) {
+ getCompileError(mGeometryShader);
+ deleteShaders();
+ return false;
+ }
+ }
+
+ glGetShaderiv(mFragmentShader, GL_COMPILE_STATUS, &param);
+ if (param != GL_TRUE) {
+ getCompileError(mFragmentShader);
+ deleteShaders();
+ return false;
+ }
+
+
+ // link
+ glAttachShader(mShaderProgram, mVertexShader);
+ if (mGeometryShader) {
+ GLenum gsInput = GL_POINTS;
+ GLenum gsOutput = GL_TRIANGLE_STRIP;
+ GLuint maxGSVOut = 4;
+ glAttachShader(mShaderProgram, mGeometryShader);
+
+ glProgramParameteriEXT(mShaderProgram, GL_GEOMETRY_INPUT_TYPE_EXT, gsInput);
+ glProgramParameteriEXT(mShaderProgram, GL_GEOMETRY_OUTPUT_TYPE_EXT, gsOutput);
+ glProgramParameteriEXT(mShaderProgram, GL_GEOMETRY_VERTICES_OUT_EXT, maxGSVOut);
+ }
+ glAttachShader(mShaderProgram, mFragmentShader);
+
+
+ glLinkProgram(mShaderProgram);
+ glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &param);
+
+ // check if program linked
+
+ if (!param) {
+ char temp[4096];
+ glGetProgramInfoLog(mShaderProgram, 4096, 0, temp);
+ fprintf(stderr, "Failed to link program:\n%s\n", temp);
+ //printf("..\n");
+ getLinkError(mShaderProgram);
+ printf(mErrorMessage.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::findVariables()
+{
+ // Find uniforms
+ GLint numUniforms, maxLength;
+ mUniforms.clear();
+ mAttributes.clear();
+ glGetProgramiv(mShaderProgram, GL_ACTIVE_UNIFORMS, &numUniforms);
+ glGetProgramiv(mShaderProgram, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLength);
+ assert(maxLength < 256);
+ char buf[256];
+
+ for (GLint i = 0; i < numUniforms; i++)
+ {
+ GLint length;
+ UniformVariable u;
+ glGetActiveUniform(mShaderProgram, i, 256, &length, &u.size, &u.type, buf);
+ assert(length < 256);
+ if (strncmp("gl_", buf, 3) != 0)
+ {
+ u.index = glGetUniformLocation(mShaderProgram, buf);
+ mUniforms[buf] = u;
+ }
+ }
+
+ // Find attribs
+ GLint numAttribs;
+ glGetProgramiv(mShaderProgram, GL_ACTIVE_ATTRIBUTES, &numAttribs);
+ glGetProgramiv(mShaderProgram, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength);
+ assert(maxLength < 256);
+
+ for (GLint i = 0; i < numAttribs; i++)
+ {
+ GLint length;
+ AttributeVariable a;
+ glGetActiveAttrib(mShaderProgram, i, 256, &length, &a.size, &a.type, buf);
+ if (strncmp("gl_", buf, 3) != 0)
+ {
+ a.index = glGetAttribLocation(mShaderProgram, buf);
+ mAttributes[buf] = a;
+ }
+ else
+ {
+ if (strncmp("gl_Vertex", buf, 9) == 0)
+ mGlShaderAttributes |= gl_VERTEX;
+ else if (strncmp("gl_Normal", buf, 9) == 0)
+ mGlShaderAttributes |= gl_NORMAL;
+ else if (strncmp("gl_Color", buf, 8) == 0)
+ mGlShaderAttributes |= gl_COLOR;
+ else if (strncmp("gl_MultiTexCoord0", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else if (strncmp("gl_MultiTexCoord1", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else if (strncmp("gl_MultiTexCoord2", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else if (strncmp("gl_MultiTexCoord3", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else if (strncmp("gl_MultiTexCoord4", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else if (strncmp("gl_MultiTexCoord5", buf, 17) == 0)
+ mGlShaderAttributes |= gl_TEXTURE;
+ else
+ printf("Unknown gl attribute: %s\n", buf);
+ }
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::getCompileError(GLuint shader)
+{
+ int infoLogLength;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ if (infoLogLength > 1)
+ {
+ char* log = (char*)malloc(sizeof(char) * infoLogLength);
+ int slen;
+ glGetShaderInfoLog(shader, infoLogLength, &slen, log);
+
+ const GLubyte* vendor = glGetString(GL_VENDOR);
+ const GLubyte* renderer = glGetString(GL_RENDERER);
+ const GLubyte* version = glGetString(GL_VERSION);
+
+ printf("Compiler error\nVendor: %s\nRenderer: %s\nVersion: %s\nError: %s\n",
+ vendor, renderer, version, log);
+
+ mErrorMessage = "compile error: ";
+ mErrorMessage += std::string(log);
+ free(log);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::getLinkError(GLuint shader)
+{
+ int infoLogLength;
+ glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+ if (infoLogLength > 1)
+ {
+ char* log = (char*)malloc(sizeof(char) * infoLogLength);
+ int slen;
+ glGetProgramInfoLog(shader, infoLogLength, &slen, log);
+
+ //const GLubyte* vendor = glGetString(GL_VENDOR);
+ //const GLubyte* renderer = glGetString(GL_RENDERER);
+ //const GLubyte* version = glGetString(GL_VERSION);
+
+ //printf("Link Error:\nVendor: %s\nRenderer: %s\nVersion: %s\nError:\n%s\n",
+ // vendor, renderer, version, log);
+
+ mErrorMessage = "link error: ";
+ mErrorMessage += std::string(log);
+
+ free(log);
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::activate(const ShaderMaterial &mat)
+{
+ if (mShaderProgram == 0)
+ return;
+
+ glUseProgram(mShaderProgram);
+}
+
+
+// --------------------------------------------------------------------------------------------
+void Shader::activate()
+{
+ if (mShaderProgram == 0)
+ return;
+
+ glUseProgram(mShaderProgram);
+}
+
+// --------------------------------------------------------------------------------------------
+void Shader::deactivate()
+{
+ if (mShaderProgram == 0)
+ return;
+
+ GLint curProg;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &curProg);
+ assert(curProg == mShaderProgram);
+
+ //for (tAttributes::iterator it = mAttributes.begin(); it != mAttributes.end(); ++it)
+ //{
+ // glDisableVertexAttribArray(it->second.index);
+ //}
+ //if (mGlShaderAttributes & gl_VERTEX)
+ // glDisableClientState(GL_VERTEX_ARRAY);
+
+ //if (mGlShaderAttributes & gl_NORMAL)
+ // glDisableClientState(GL_NORMAL_ARRAY);
+
+ //if (mGlShaderAttributes & gl_COLOR)
+ // glDisableClientState(GL_COLOR_ARRAY);
+
+ //if (mGlShaderAttributes & gl_TEXTURE)
+ // glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glUseProgram(0);
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::isValid()
+{
+ return mShaderProgram != 0;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform(const char *name, const PxMat33& value)
+{
+ GLint uniform = getUniformCommon(name);
+ if (uniform != -1)
+ {
+ float v[9];
+ v[0] = value.column0.x; v[3] = value.column0.y; v[6] = value.column0.z;
+ v[1] = value.column1.x; v[4] = value.column1.y; v[7] = value.column1.z;
+ v[2] = value.column2.x; v[5] = value.column2.y; v[8] = value.column2.z;
+ glUniformMatrix3fv(uniform, 1, false, v);
+
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform(const char *name, const PxTransform& value)
+{
+ GLint uniform = getUniformCommon(name);
+ if (uniform != -1)
+ {
+ float v[16];
+ PxMat44 v44 = value;
+ v[0] = v44.column0.x; v[4] = v44.column0.y; v[8] = v44.column0.z; v[12] = v44.column0.w;
+ v[1] = v44.column1.x; v[5] = v44.column1.y; v[9] = v44.column1.z; v[13] = v44.column1.w;
+ v[2] = v44.column2.x; v[6] = v44.column2.y; v[10] = v44.column2.z; v[14] = v44.column2.w;
+ v[3] = v44.column3.x; v[7] = v44.column3.y; v[11] = v44.column3.z; v[15] = v44.column3.w;
+ glUniformMatrix4fv(uniform, 1, false, v);
+
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform(const char *name, PxU32 size, const PxVec3* value)
+{
+ GLint uniform = getUniformCommon(name);
+ if (uniform != -1)
+ {
+ glUniform3fv(uniform, size, (const GLfloat*)value);
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform1(const char* name, const float value)
+{
+ GLint loc = glGetUniformLocation(mShaderProgram, name);
+ if (loc >= 0) {
+ glUniform1f(loc, value);
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform2(const char* name, float val0, float val1)
+{
+ GLint loc = glGetUniformLocation(mShaderProgram, name);
+ if (loc >= 0) {
+ glUniform2f(loc, val0, val1);
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform3(const char* name, float val0, float val1, float val2)
+{
+ GLint loc = glGetUniformLocation(mShaderProgram, name);
+ if (loc >= 0) {
+ glUniform3f(loc, val0, val1, val2);
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform4(const char* name, float val0, float val1, float val2, float val3)
+{
+ GLint loc = glGetUniformLocation(mShaderProgram, name);
+ if (loc >= 0) {
+ glUniform4f(loc, val0, val1, val2, val3);
+ return true;
+ }
+ return false;
+}
+
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform(const char* name, float value)
+{
+ GLint uniform = getUniformCommon(name);
+ if (uniform != -1)
+ {
+ glUniform1f(uniform, value);
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setUniform(const char* name, int value)
+{
+ GLint uniform = getUniformCommon(name);
+ if (uniform != -1)
+ {
+ glUniform1i(uniform, value);
+ return true;
+ }
+ return false;
+}
+
+
+bool
+Shader::setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count)
+{
+ GLint loc = glGetUniformLocation(mShaderProgram, name);//getUniformCommon( name);
+ if (loc == -1) {
+ return false;
+ }
+ switch (elementSize) {
+ case 1:
+ glUniform1fv(loc, count, v);
+ break;
+ case 2:
+ glUniform2fv(loc, count, v);
+ break;
+ case 3:
+ glUniform3fv(loc, count, v);
+ break;
+ case 4:
+ glUniform4fv(loc, count, v);
+ break;
+ }
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::setAttribute(const char* name, PxU32 size, PxU32 stride, GLenum type, void* data)
+{
+ GLint activeProgram;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
+ tAttributes::iterator it = mAttributes.find(name);
+ if (it != mAttributes.end())
+ {
+ PxI32 index = it->second.index;
+ glEnableVertexAttribArray(index);
+ glVertexAttribPointer(index, size, type, GL_FALSE, stride, data);
+
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------------------------
+GLint Shader::getUniformCommon(const char* name)
+{
+ GLint activeProgram;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
+ if (activeProgram == 0) return -1;
+ tUniforms::iterator it = mUniforms.find(name);
+ if (it != mUniforms.end())
+ {
+ assert(it->second.index != -1);
+ return it->second.index;
+ }
+ return -1;
+}
+
+// --------------------------------------------------------------------------------------------
+bool Shader::loadFile(const char* filename, char*& destination, int& destinationLength)
+{
+ if (destination != NULL)
+ {
+ assert(destinationLength != 0);
+ free(destination);
+ destination = NULL;
+ destinationLength = 0;
+ }
+ assert(destinationLength == 0);
+
+ FILE* file = NULL;
+ file = fopen(filename, "rb");
+ if (file == NULL)
+ {
+ mErrorMessage = "Shader file " + std::string(filename) + "not found\n";
+ return false;
+ }
+ // find length
+ fseek(file, 0, SEEK_END);
+ destinationLength = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ if (destinationLength > 0)
+ {
+ destination = (char*)malloc(destinationLength * sizeof(char) + 1);
+
+ fread(destination, 1, destinationLength, file);
+ destination[destinationLength] = 0;
+ }
+ fclose(file);
+ return true;
+}
+
+void
+Shader::bindTexture(const char *name, GLuint tex, GLenum target, GLint unit)
+{
+ GLint loc = getUniformCommon(name);
+ if (loc >= 0) {
+ glActiveTexture(GL_TEXTURE0 + unit);
+ glBindTexture(target, tex);
+ glUseProgram(mShaderProgram);
+ glUniform1i(loc, unit);
+ glActiveTexture(GL_TEXTURE0);
+ } else {
+#if _DEBUG
+ fprintf(stderr, "Error binding texture '%s'\n", name);
+#endif
+ }
+}
+
+bool
+Shader::setUniformMatrix4fv(const GLchar *name, const GLfloat *m, bool transpose)
+{
+ GLint loc = getUniformCommon(name);
+ if (loc >= 0) {
+ glUniformMatrix4fv(loc, 1, transpose, m);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/Shader.h b/KaplaDemo/samples/sampleViewer3/Shader.h
new file mode 100644
index 00000000..a61ccc41
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Shader.h
@@ -0,0 +1,146 @@
+#ifndef SHADER_H
+#define SHADER_H
+
+#include "foundation/PxVec3.h"
+#include "foundation/PxMat33.h"
+#include "foundation/PxTransform.h"
+
+#include <GL/glew.h>
+#include <map>
+#include <vector>
+#include <string>
+
+using namespace physx;
+
+#define STRINGIFY(A) #A
+
+// ----------------------------------------------------------------------------------
+struct ShaderMaterial
+{
+ void init(unsigned int texId = 0) {
+ this->texId = texId;
+ ambientCoeff = 0.0f;
+ diffuseCoeff = 1.0f;
+ specularCoeff = 0.0f;
+ reflectionCoeff = 0.0f;
+ refractionCoeff = 0.0f;
+ shadowCoeff = 0.0f;
+ color[0] = 1.0f; color[1] = 1.0f; color[2] = 1.0f; color[3] = 1.0f;
+ }
+ void setColor(float r, float g, float b, float a = 1.0f) {
+ color[0] = r; color[1] = g; color[2] = b; color[3] = a;
+ }
+ bool operator == (const ShaderMaterial &m) const {
+ if (texId != m.texId) return false;
+ if (color[0] != m.color[0] || color[1] != m.color[1] || color[2] != m.color[2] || color[3] != m.color[3]) return false;
+ return true;
+ }
+ unsigned int texId;
+ float color[4];
+ float ambientCoeff;
+ float diffuseCoeff;
+ float specularCoeff;
+ float reflectionCoeff;
+ float refractionCoeff;
+ float shadowCoeff;
+
+};
+
+// ----------------------------------------------------------------------------------
+class Shader
+{
+public:
+ Shader();
+ virtual ~Shader();
+
+ bool isValid();
+ virtual void activate();
+ virtual void activate(const ShaderMaterial &mat);
+ virtual void deactivate();
+ operator GLuint ()
+ {
+ return mShaderProgram;
+ }
+
+ const std::string &getErrorMessage() { return mErrorMessage; }
+ GLuint getShaderProgram() {return mShaderProgram;}
+
+//protected:
+ bool loadShaders(const char* vertexShaderFile, const char* fragmentShaderFile);
+ bool loadShaders(const char* vertexShaderFile, const char* geometryShaderFile, const char* fragmentShaderFile);
+ bool loadShaderCode(const char* vertexShaderCode, const char* fragmentShaderCode);
+ bool loadShaderCode(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode);
+ void deleteShaders();
+
+ bool compileShaders();
+ void getCompileError(GLuint shader);
+ void getLinkError(GLuint shader);
+ void findVariables();
+ void bindTexture(const char *name, GLuint tex, GLenum target, GLint unit);
+
+ GLuint mShaderProgram;
+ GLuint mVertexShader;
+ GLuint mGeometryShader;
+ GLuint mFragmentShader;
+ GLuint mGlShaderAttributes;
+
+ char* mVertexShaderSource;
+ int mVertexShaderSourceLength;
+
+ char* mGeometryShaderSource;
+ int mGeometryShaderSourceLength;
+
+ char* mFragmentShaderSource;
+ int mFragmentShaderSourceLength;
+
+ struct UniformVariable
+ {
+ GLint size;
+ GLenum type;
+ GLint index;
+ };
+
+ struct AttributeVariable
+ {
+ GLint size;
+ GLenum type;
+ GLint index;
+ };
+
+ enum glShaderAttribute
+ {
+ gl_VERTEX = (1 << 0),
+ gl_NORMAL = (1 << 1),
+ gl_COLOR = (1 << 2),
+ gl_TEXTURE = (1 << 3),
+ };
+
+ typedef std::map<std::string, UniformVariable> tUniforms;
+ tUniforms mUniforms;
+ typedef std::map<std::string, AttributeVariable> tAttributes;
+ tAttributes mAttributes;
+
+ std::string mErrorMessage;
+
+public:
+ virtual bool setUniform(const char* name, const PxMat33& value);
+ virtual bool setUniform(const char* name, const PxTransform& value);
+ virtual bool setUniform(const char *name, PxU32 size, const PxVec3* value);
+
+ virtual bool setUniform1(const char* name, float val);
+ virtual bool setUniform2(const char* name, float val0, float val1);
+ virtual bool setUniform3(const char* name, float val0, float val1, float val2);
+ virtual bool setUniform4(const char* name, float val0, float val1, float val2, float val3);
+ virtual bool setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count=1);
+
+ virtual bool setUniform(const char* name, float value);
+ virtual bool setUniform(const char* name, int value);
+ virtual bool setUniformMatrix4fv(const GLchar *name, const GLfloat *m, bool transpose);
+
+ virtual GLint getUniformCommon(const char* name);
+
+ virtual bool setAttribute(const char* name, PxU32 size, PxU32 stride, GLenum type, void* data);
+ bool loadFile(const char* filename, char*& destination, int& destinationLength);
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/ShaderShadow.cpp b/KaplaDemo/samples/sampleViewer3/ShaderShadow.cpp
new file mode 100644
index 00000000..6224e420
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/ShaderShadow.cpp
@@ -0,0 +1,2883 @@
+#include "ShaderShadow.h"
+//#define NOMINMAX
+#include <windows.h>
+#include "ShadowMap.h"
+#include "foundation/PxMat44.h"
+#include "Compound.h"
+
+ShaderShadow::RenderMode ShaderShadow::renderMode = ShaderShadow::RENDER_COLOR;
+float ShaderShadow::hdrScale = 1.f;
+GLuint ShaderShadow::skyBoxTex = 0;
+//float g_shadowAdd = -0.00001f;
+//float g_shadowAdd = -0.003349f;
+float g_shadowAdd = -0.00001f;
+// --------------------------------------------------------------------------------------------
+const char *crossHairVertexProgram = STRINGIFY(
+void main()
+{
+ gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+}
+);
+const char *crossHairFragmentProgram = STRINGIFY(
+uniform sampler2D texture;
+void main()
+{
+ vec4 color = texture2D(texture, gl_TexCoord[0]);
+ gl_FragColor = vec4(1.0,1.0,1.0, 1.0f-color.x);
+
+}
+);
+
+// --------------------------------------------------------------------------------------------
+const char *shadowDiffuseVertexProgramTexInstance = STRINGIFY(
+
+uniform float uvScale = 1.0f;
+uniform sampler2D transTex;
+uniform int transTexSize;
+uniform float iTransTexSize;
+uniform float bumpTextureUVScale;
+//attribute mat4 transformmatrix;
+void main()
+{
+
+ int ti = (int)(gl_MultiTexCoord0.w);
+ //int ti = tq;
+ int tpr = transTexSize / 4;
+ int row = ti / tpr;
+ int col = (ti - row*tpr)*4;
+
+ float fx = (col+0.5f)*iTransTexSize;
+ float fy = (row+0.5f)*iTransTexSize;
+
+
+ vec4 r0 = texture2D(transTex, vec2(fx,fy));
+ vec4 r1 = texture2D(transTex, vec2(fx+iTransTexSize,fy));
+ vec4 r2 = texture2D(transTex, vec2(fx+iTransTexSize*2.0f,fy));
+ vec4 r3 = texture2D(transTex, vec2(fx+iTransTexSize*3.0f,fy));
+// vec4 r3 = vec4(0,0,0,1);
+
+ vec3 offset = vec3(r0.w, r1.w, r2.w);
+ r0.w = 0.0f;
+ r1.w = 0.0f;
+ r2.w = 0.0f;
+
+ float material = r3.w;
+ r3.w = 1.0f;
+ mat4 transformmatrix = mat4(r0,r1,r2,r3);
+
+
+
+
+ mat4 mvp = gl_ModelViewMatrix * transformmatrix;
+ mat4 mvpt = gl_ModelViewMatrixInverseTranspose * transformmatrix;
+ vec4 t0 = vec4(gl_MultiTexCoord0.xyz, 0.0f);
+
+ vec4 t1 = vec4(cross(gl_Normal.xyz, t0.xyz), 0.0f);
+
+// mat4 mvp = gl_ModelViewMatrix;
+// mat4 mvpt = gl_ModelViewMatrixInverseTranspose;
+
+
+ vec4 eyeSpacePos = mvp * gl_Vertex;
+ //eyeSpacePos.y += gl_InstanceID * 0.2f;
+ //gl_TexCoord[0].xyz = gl_MultiTexCoord0.xyz*uvScale;
+ vec3 coord3d = gl_Vertex.xyz + offset;
+ gl_TexCoord[0].xyz = (coord3d)*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ gl_TexCoord[2] = mvpt * vec4(gl_Normal.xyz,0.0);
+
+ gl_TexCoord[3] = mvpt * t0;
+ gl_TexCoord[4].xyz = mvpt * t1;
+
+ gl_TexCoord[5].xy = vec2(dot(coord3d, t0.xyz), dot(coord3d, t1.xyz))*bumpTextureUVScale*2;
+
+ gl_TexCoord[6].xyz = vec3(gl_MultiTexCoord1.xy, material);
+ gl_TexCoord[6].y = 1.0 - gl_TexCoord[6].y;
+
+ float MAX_3D_TEX = 8.0;
+ if (gl_TexCoord[6].x >= 5.0f) {
+ // 2D Tex
+ gl_TexCoord[6].x -= 5.0f;
+ gl_TexCoord[6].z = floor(gl_TexCoord[6].z / MAX_3D_TEX);
+ } else {
+ gl_TexCoord[6].z -= floor(gl_TexCoord[6].z / MAX_3D_TEX)*MAX_3D_TEX;
+ gl_TexCoord[6].z -= 100.0f;
+
+ }
+ gl_TexCoord[6].w = floor(fract(material / MAX_3D_TEX)*MAX_3D_TEX + 0.5f);
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+}
+);
+
+// --------------------------------------------------------------------------------------------
+const char *shadowDiffuseVertexProgramInstance = STRINGIFY(
+
+uniform float uvScale = 1.0f;
+attribute mat4 transformmatrix;
+uniform float bumpTextureUVScale;
+
+void main()
+{
+ mat4 mvp = gl_ModelViewMatrix * transformmatrix;
+ mat4 mvpt = gl_ModelViewMatrixInverseTranspose * transformmatrix;
+ //mat4 mvp2 = gl_ModelViewMatrix * transformmatrix;
+ //mat4 mvp = gl_ModelViewMatrix;
+ //mat4 mvpt = gl_ModelViewMatrixInverseTranspose;
+
+ vec4 eyeSpacePos = mvp * gl_Vertex;
+
+ vec4 t0 = vec4(gl_MultiTexCoord0.xyz, 0.0f);
+ vec4 t1 = vec4(cross(gl_Normal.xyz, t0.xyz), 0.0f);
+
+
+ vec3 coord3d = gl_Vertex.xyz;
+ gl_TexCoord[0].xyz = (coord3d)*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ gl_TexCoord[2] = mvpt * vec4(gl_Normal.xyz,0.0);
+
+ gl_TexCoord[3] = mvpt * t0;
+ gl_TexCoord[4] = mvpt * t1;
+
+ gl_TexCoord[5].xy = vec2(dot(coord3d, t0.xyz), dot(coord3d, t1.xyz))*bumpTextureUVScale*2;
+
+ gl_TexCoord[6].xyz = vec3(0,0,-100); // TODO: 2D UV are 0 and material id is -100 (first 3D texture)
+
+ /*
+ //vec4 eyeSpacePos2 = mvp2 * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ //gl_FrontColor.x += eyeSpacePos2.x;
+
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ gl_TexCoord[2] = mvpt * vec4(gl_Normal.xyz,0.0);
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+ */
+}
+);
+
+
+// --------------------------------------------------------------------------------------------
+const char *shadowDiffuseVertexProgramFor3DTex = STRINGIFY(
+ uniform float uvScale = 1.0f;
+ uniform float bumpTextureUVScale;
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0.0);
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+
+ vec3 coord3d = gl_Vertex.xyz;
+
+ vec4 t0 = vec4(normalize(cross(vec3(1,0,0),gl_Normal.xyz)) ,0.0f);
+ vec4 t1 = vec4(normalize(cross(t0.xyz,gl_Normal.xyz)), 0.0f);
+
+ gl_TexCoord[0].xyz = coord3d*uvScale;
+ gl_TexCoord[3] = gl_ModelViewMatrixInverseTranspose * t0;
+ gl_TexCoord[4] = gl_ModelViewMatrixInverseTranspose * t1;
+ gl_FrontColor = gl_Color;
+
+ gl_TexCoord[5].xy = vec2(dot(coord3d, t0.xyz), dot(coord3d, t1.xyz))*bumpTextureUVScale*2;
+ gl_TexCoord[6].xyz = vec3(0,0,-100);
+
+}
+);
+
+// --------------------------------------------------------------------------------------------
+const char *shadowDiffuseVertexProgram = STRINGIFY(
+uniform float uvScale = 1.0f;
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0.0);
+ gl_TexCoord[3].xyz = gl_Vertex.xyz;
+ gl_TexCoord[4].xyz = gl_Normal.xyz;
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+}
+);
+
+// --------------------------------------------------------------------------------------------
+const char *shadowDiffuseVertexProgram4Bones = STRINGIFY(
+uniform float uvScale = 1.0f;
+uniform sampler2D transTex;
+uniform float transvOffset;
+uniform float texelSpacing;
+
+void getPosNormal(vec2 uv, vec4 vertex, vec4 normal,
+ out vec4 posOut, out vec4 normalOut) {
+ vec4 f0;
+ vec4 f1;
+ vec4 f2;
+ f0 = texture2D(transTex, uv);
+ f1 = texture2D(transTex, vec2(uv.x + texelSpacing, uv.y));
+ f2 = texture2D(transTex, vec2(uv.x + 2.0f*texelSpacing, uv.y));
+
+ posOut = vec4(dot(f0, vertex), dot(f1, vertex), dot(f2, vertex), 1.0f);
+
+ normalOut = vec4(dot(f0, normal), dot(f1, normal), dot(f2, normal), 0.0f);
+
+}
+void main()
+{
+
+ vec2 t0uv = vec2(gl_MultiTexCoord1.x, gl_MultiTexCoord1.y + transvOffset);
+ vec2 t1uv = vec2(gl_MultiTexCoord1.z, gl_MultiTexCoord1.w + transvOffset);
+ vec2 t2uv = vec2(gl_MultiTexCoord2.x, gl_MultiTexCoord2.y + transvOffset);
+ vec2 t3uv = vec2(gl_MultiTexCoord2.z, gl_MultiTexCoord2.w + transvOffset);
+ float t0w = gl_MultiTexCoord3.x;
+ float t1w = gl_MultiTexCoord3.y;
+ float t2w = gl_MultiTexCoord3.z;
+ float t3w = gl_MultiTexCoord3.w;
+
+ vec4 vert;
+ vec4 norm;
+ vec4 vert0;
+ vec4 norm0;
+ vec4 vert1;
+ vec4 norm1;
+ vec4 vert2;
+ vec4 norm2;
+ vec4 vert3;
+ vec4 norm3;
+
+ getPosNormal(t0uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert0, norm0);
+ getPosNormal(t1uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert1, norm1);
+ getPosNormal(t2uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert2, norm2);
+ getPosNormal(t3uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert3, norm3);
+
+ float sum = max(t0w+t1w+t2w+t3w, 0.001f);
+ vert = (t0w*vert0 + t1w*vert1 + t2w*vert2 + t3w*vert3)/sum;
+ norm = t0w*norm0 + t1w*norm1 + t2w*norm2 + t3w*norm3;
+ norm = vec4(normalize(norm.xyz), 0.0f);
+ //vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ vec4 eyeSpacePos = gl_ModelViewMatrix * vert;
+ gl_TexCoord[0] = gl_MultiTexCoord0*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ //gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * norm;
+ gl_TexCoord[3] = gl_MultiTexCoord4;
+ gl_TexCoord[4] = gl_MultiTexCoord5;
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+}
+);
+
+// --------------------------------------------------------------------------------------------
+
+const char *shadowDiffuseVertexProgram8BonesTangent = STRINGIFY(
+ uniform float uvScale = 1.0f;
+uniform sampler2D transTex;
+uniform float transvOffset;
+uniform float texelSpacing;
+/*
+void getPosNormalTangent(vec2 uv, vec4 vertex, vec4 normal, vec4 tangent,
+ out vec4 posOut, out vec4 normalOut, out vec4 tangentOut) {
+ vec4 f0;
+ vec4 f1;
+ vec4 f2;
+ f0 = texture2D(transTex, uv);
+ f1 = texture2D(transTex, vec2(uv.x + texelSpacing, uv.y));
+ f2 = texture2D(transTex, vec2(uv.x + 2.0f*texelSpacing, uv.y));
+
+ posOut = vec4(dot(f0, vertex), dot(f1, vertex), dot(f2, vertex), 1.0f);
+
+ normalOut = vec4(dot(f0, normal), dot(f1, normal), dot(f2, normal), 0.0f);
+
+ tangentOut = vec4(dot(f0, tangent), dot(f1, tangent), dot(f2, tangent), 0.0f);
+
+}
+*/
+void getPosNormal(vec2 uv, vec4 vertex, vec4 normal,
+ out vec4 posOut, out vec4 normalOut) {
+ vec4 f0;
+ vec4 f1;
+ vec4 f2;
+ f0 = texture2D(transTex, uv);
+ f1 = texture2D(transTex, vec2(uv.x + texelSpacing, uv.y));
+ f2 = texture2D(transTex, vec2(uv.x + 2.0f*texelSpacing, uv.y));
+
+ posOut = vec4(dot(f0, vertex), dot(f1, vertex), dot(f2, vertex), 1.0f);
+
+ normalOut = vec4(dot(f0, normal), dot(f1, normal), dot(f2, normal), 0.0f);
+
+}
+void main()
+{
+
+ vec2 t0uv = vec2(gl_MultiTexCoord1.x, gl_MultiTexCoord1.y + transvOffset);
+ vec2 t1uv = vec2(gl_MultiTexCoord1.z, gl_MultiTexCoord1.w + transvOffset);
+ vec2 t2uv = vec2(gl_MultiTexCoord2.x, gl_MultiTexCoord2.y + transvOffset);
+ vec2 t3uv = vec2(gl_MultiTexCoord2.z, gl_MultiTexCoord2.w + transvOffset);
+ vec2 t4uv = vec2(gl_MultiTexCoord3.x, gl_MultiTexCoord3.y + transvOffset);
+ vec2 t5uv = vec2(gl_MultiTexCoord3.z, gl_MultiTexCoord3.w + transvOffset);
+ vec2 t6uv = vec2(gl_MultiTexCoord4.x, gl_MultiTexCoord4.y + transvOffset);
+ vec2 t7uv = vec2(gl_MultiTexCoord4.z, gl_MultiTexCoord4.w + transvOffset);
+
+ float t0w = gl_MultiTexCoord5.x;
+ float t1w = gl_MultiTexCoord5.y;
+ float t2w = gl_MultiTexCoord5.z;
+ float t3w = gl_MultiTexCoord5.w;
+ float t4w = gl_MultiTexCoord6.x;
+ float t5w = gl_MultiTexCoord6.y;
+ float t6w = gl_MultiTexCoord6.z;
+ float t7w = gl_MultiTexCoord6.w;
+
+ vec4 vert;
+ vec4 norm;
+ vec4 vert0;
+ vec4 norm0;
+ vec4 vert1;
+ vec4 norm1;
+ vec4 vert2;
+ vec4 norm2;
+ vec4 vert3;
+ vec4 norm3;
+
+ vec4 vert4;
+ vec4 norm4;
+ vec4 vert5;
+ vec4 norm5;
+ vec4 vert6;
+ vec4 norm6;
+ vec4 vert7;
+ vec4 norm7;
+
+ /*
+ vec4 tangent0;
+ vec4 tangent1;
+ vec4 tangent2;
+ vec4 tangent3;
+ vec4 tangent4;
+ vec4 tangent5;
+ vec4 tangent6;
+ vec4 tangent7;
+ */
+ getPosNormal(t0uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert0, norm0);
+ getPosNormal(t1uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert1, norm1);
+ getPosNormal(t2uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert2, norm2);
+ getPosNormal(t3uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert3, norm3);
+
+ getPosNormal(t4uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert4, norm4);
+ getPosNormal(t5uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert5, norm5);
+ getPosNormal(t6uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert6, norm6);
+ getPosNormal(t7uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert7, norm7);
+
+ /*
+ getPosNormalTangent(t0uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert0, norm0, tangent0);
+ getPosNormalTangent(t1uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert1, norm1, tangent1);
+ getPosNormalTangent(t2uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert2, norm2, tangent2);
+ getPosNormalTangent(t3uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert3, norm3, tangent3);
+
+ getPosNormalTangent(t4uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert4, norm4, tangent4);
+ getPosNormalTangent(t5uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert5, norm5, tangent5);
+ getPosNormalTangent(t6uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert6, norm6, tangent6);
+ getPosNormalTangent(t7uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vec4(gl_MultiTexCoord7.xyz, 0.0), vert7, norm7, tangent7);
+*/
+ float sum = max(t0w+t1w+t2w+t3w+t4w+t5w+t6w+t7w, 0.001f);
+ vert = (t0w*vert0 + t1w*vert1 + t2w*vert2 + t3w*vert3 + t4w*vert4 + t5w*vert5 + t6w*vert6 + t7w*vert7)/sum;
+ norm = t0w*norm0 + t1w*norm1 + t2w*norm2 + t3w*norm3 + t4w*norm4 + t5w*norm5 + t6w*norm6 + t7w*norm7;
+ norm = vec4(normalize(norm.xyz), 0.0);
+
+ /*
+ vec4 tangent = t0w*tangent0 + t1w*tangent1 + t2w*tangent2 + t3w*tangent3 + t4w*tangent4 + t5w*tangent5 + t6w*tangent6 + t7w*tangent7;
+ tangent = vec4(normalize(tangent.xyz), 0.0);
+
+ vec3 bitangent = normalize(cross(norm.xyz, tangent.xyz));
+ tangent.xyz = cross(bitangent, norm.xyz);
+ */
+
+ //vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ vec4 eyeSpacePos = gl_ModelViewMatrix * vert;
+ gl_TexCoord[0] = gl_MultiTexCoord0*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ //gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * norm;
+ //gl_TexCoord[3] = gl_ModelViewMatrixInverseTranspose * tangent;
+ //gl_TexCoord[4] = gl_ModelViewMatrixInverseTranspose * vec4(bitangent, 0.0);
+ //gl_TexCoord[4] = gl_MultiTexCoord8;
+
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+}
+);
+
+
+const char *shadowDiffuseVertexProgram8Bones = STRINGIFY(
+ uniform float uvScale = 1.0f;
+uniform sampler2D transTex;
+uniform float transvOffset;
+uniform float texelSpacing;
+
+void getPosNormal(vec2 uv, vec4 vertex, vec4 normal,
+ out vec4 posOut, out vec4 normalOut) {
+ vec4 f0;
+ vec4 f1;
+ vec4 f2;
+ f0 = texture2D(transTex, uv);
+ f1 = texture2D(transTex, vec2(uv.x + texelSpacing, uv.y));
+ f2 = texture2D(transTex, vec2(uv.x + 2.0f*texelSpacing, uv.y));
+
+ posOut = vec4(dot(f0, vertex), dot(f1, vertex), dot(f2, vertex), 1.0f);
+
+ normalOut = vec4(dot(f0, normal), dot(f1, normal), dot(f2, normal), 0.0f);
+
+}
+void main()
+{
+
+ vec2 t0uv = vec2(gl_MultiTexCoord1.x, gl_MultiTexCoord1.y + transvOffset);
+ vec2 t1uv = vec2(gl_MultiTexCoord1.z, gl_MultiTexCoord1.w + transvOffset);
+ vec2 t2uv = vec2(gl_MultiTexCoord2.x, gl_MultiTexCoord2.y + transvOffset);
+ vec2 t3uv = vec2(gl_MultiTexCoord2.z, gl_MultiTexCoord2.w + transvOffset);
+ vec2 t4uv = vec2(gl_MultiTexCoord3.x, gl_MultiTexCoord3.y + transvOffset);
+ vec2 t5uv = vec2(gl_MultiTexCoord3.z, gl_MultiTexCoord3.w + transvOffset);
+ vec2 t6uv = vec2(gl_MultiTexCoord4.x, gl_MultiTexCoord4.y + transvOffset);
+ vec2 t7uv = vec2(gl_MultiTexCoord4.z, gl_MultiTexCoord4.w + transvOffset);
+
+ float t0w = gl_MultiTexCoord5.x;
+ float t1w = gl_MultiTexCoord5.y;
+ float t2w = gl_MultiTexCoord5.z;
+ float t3w = gl_MultiTexCoord5.w;
+ float t4w = gl_MultiTexCoord6.x;
+ float t5w = gl_MultiTexCoord6.y;
+ float t6w = gl_MultiTexCoord6.z;
+ float t7w = gl_MultiTexCoord6.w;
+
+ vec4 vert;
+ vec4 norm;
+ vec4 vert0;
+ vec4 norm0;
+ vec4 vert1;
+ vec4 norm1;
+ vec4 vert2;
+ vec4 norm2;
+ vec4 vert3;
+ vec4 norm3;
+
+ vec4 vert4;
+ vec4 norm4;
+ vec4 vert5;
+ vec4 norm5;
+ vec4 vert6;
+ vec4 norm6;
+ vec4 vert7;
+ vec4 norm7;
+
+ getPosNormal(t0uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert0, norm0);
+ getPosNormal(t1uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert1, norm1);
+ getPosNormal(t2uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert2, norm2);
+ getPosNormal(t3uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert3, norm3);
+
+ getPosNormal(t4uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert4, norm4);
+ getPosNormal(t5uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert5, norm5);
+ getPosNormal(t6uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert6, norm6);
+ getPosNormal(t7uv, gl_Vertex, vec4(gl_Normal.xyz,0.0), vert7, norm7);
+
+ float sum = max(t0w+t1w+t2w+t3w+t4w+t5w+t6w+t7w, 0.001f);
+ vert = (t0w*vert0 + t1w*vert1 + t2w*vert2 + t3w*vert3 + t4w*vert4 + t5w*vert5 + t6w*vert6 + t7w*vert7)/sum;
+ norm = t0w*norm0 + t1w*norm1 + t2w*norm2 + t3w*norm3 + t4w*norm4 + t5w*norm5 + t6w*norm6 + t7w*norm7;
+ norm = vec4(normalize(norm.xyz), 0.0f);
+ //vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ vec4 eyeSpacePos = gl_ModelViewMatrix * vert;
+ gl_TexCoord[0] = gl_MultiTexCoord0*uvScale;
+ gl_TexCoord[1] = eyeSpacePos;
+ gl_FrontColor = gl_Color;
+ gl_Position = gl_ProjectionMatrix*eyeSpacePos;
+ //gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * norm;
+ gl_TexCoord[3] = gl_MultiTexCoord7;
+ //gl_TexCoord[4] = gl_MultiTexCoord8;
+
+ gl_ClipVertex = vec4(eyeSpacePos.xyz, 1.0f);
+}
+);
+
+// --------------------------------------------------------------------------------------------
+
+const char *shadowDiffuseFragmentProgram = STRINGIFY(
+
+ // scene reflection
+ uniform float reflectionCoeff = 0.0f;
+uniform float specularCoeff = 0.0f;
+
+uniform sampler2DRect reflectionTex;
+
+// Shadow map
+uniform float shadowAmbient = 0.0;
+uniform sampler2D texture;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DArrayShadow stex2;
+uniform sampler2DArrayShadow stex3;
+uniform samplerCube skyboxTex;
+
+uniform float hdrScale = 5.0;
+
+uniform vec2 texSize; // x - size, y - 1/size
+uniform vec4 far_d;
+
+// Spot lights
+uniform vec3 spotLightDir;
+uniform vec3 spotLightPos;
+uniform float spotLightCosineDecayBegin;
+uniform float spotLightCosineDecayEnd;
+
+uniform vec3 spotLightDir2;
+uniform vec3 spotLightPos2;
+uniform float spotLightCosineDecayBegin2;
+uniform float spotLightCosineDecayEnd2;
+
+uniform vec3 spotLightDir3;
+uniform vec3 spotLightPos3;
+uniform float spotLightCosineDecayBegin3;
+uniform float spotLightCosineDecayEnd3;
+
+uniform vec3 parallelLightDir;
+uniform float shadowAdd;
+uniform int useTexture;
+uniform int numShadows;
+uniform vec3 ambientColor;
+uniform vec2 shadowTaps[12];
+float shadowCoeff1()
+{
+ //const int index = 0;
+
+ int index = 3;
+
+ if (gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if (gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if (gl_FragCoord.z < far_d.z)
+ index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ // return shadow2DArray(stex, shadow_coord).x;
+ /*
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;*/
+ const int numTaps = 4;
+ float radius = 0.0005f / pow(2, index);
+ float s = 0.0f;
+ for (int i = 0; i < numTaps; i++)
+ {
+ s += shadow2DArray(stex, shadow_coord + vec4(shadowTaps[i] * radius, 0.0f, 0.0f)).r;
+ }
+ s /= numTaps;
+ return s;
+}
+float shadowCoeff2()
+{
+ const int index = 1;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+ // return shadow2DArray(stex, shadow_coord).x;
+ /*
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex2, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;*/
+ const int numTaps = 12;
+ float radius = 1.0f;
+ float s = 0.0f;
+ for (int i = 0; i < numTaps; i++)
+ {
+ s += shadow2DArray(stex, shadow_coord + vec4(shadowTaps[i] * radius, 0.0f, 0.0f)).r;
+ }
+ s /= numTaps;
+ return s;
+}
+float shadowCoeff3()
+{
+ const int index = 2;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+
+ // return shadow2DArray(stex, shadow_coord).x;
+ /*
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex3, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;*/
+ const int numTaps = 12;
+ float radius = 0.02f;
+ float s = 0.0f;
+ for (int i = 0; i < numTaps; i++)
+ {
+ s += shadow2DArray(stex, shadow_coord + vec4(shadowTaps[i] * radius, 0.0f, 0.0f)).r;
+ }
+ s /= numTaps;
+ return s;
+}
+
+float filterwidth(float2 v)
+{
+ float2 fw = max(abs(ddx(v)), abs(ddy(v)));
+ return max(fw.x, fw.y);
+}
+
+float2 bump(float2 x)
+{
+ return (floor((x) / 2) + 2.f * max(((x) / 2) - floor((x) / 2) - .5f, 0.f));
+}
+
+float checker(float2 uv)
+{
+ float width = filterwidth(uv);
+ float2 p0 = uv - 0.5 * width;
+ float2 p1 = uv + 0.5 * width;
+
+ float2 i = (bump(p1) - bump(p0)) / width;
+ return i.x * i.y + (1 - i.x) * (1 - i.y);
+}
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 3.0; // 5.0 is physically correct
+
+uniform float RollOff = 0.5f;
+void main()
+{
+
+ //// TODO, expose this as user parameter
+ const float skyLightIntensity = 0.2;
+ const float rimLightIntensity = 0.3;
+
+
+ vec3 diffuseMat;
+ vec3 specularMat;
+ vec3 emissiveReflectSpecPow;
+
+ specularMat = vec3(1.0);
+ emissiveReflectSpecPow = vec3(0.0, 0.0, 0.0);
+
+ vec3 normal = normalize(gl_TexCoord[2].xyz);
+ vec3 wnormal = normalize(gl_TexCoord[4].xyz);
+ // read in material color for diffuse, specular, bump, emmisive
+
+ // 3D texture
+ vec4 colorx;
+ if (useTexture > 0)
+ colorx = texture2D(texture, gl_TexCoord[0]);
+ else {
+ colorx = gl_Color;
+ if ((wnormal.y >0.9))
+ {
+ colorx *= 1.0 - 0.25*checker(float2(gl_TexCoord[3].x, gl_TexCoord[3].z));
+ }
+ else if (abs(wnormal.z) > 0.9)
+ {
+ colorx *= 1.0 - 0.25*checker(float2(gl_TexCoord[3].y, gl_TexCoord[3].x));
+ }
+ }
+ diffuseMat = colorx.xyz*0.4;
+ //diffuseMat = myTexture3D(gl_TexCoord[0].xyz);//texture3D(ttt3D, gl_TexCoord[0].xyz);
+ //diffuseMat = texture3D(ttt3D, gl_TexCoord[0].xyz);
+
+ if (dot(normal, gl_TexCoord[1].xyz) > 0) {
+ normal.xyz *= -1;
+ }
+
+ //gl_FragColor.xyz = normal*0.5 + vec3(0.5,0.5,0.5);
+ //gl_FragColor.w = 1;
+ //return;
+ vec3 eyeVec = normalize(gl_TexCoord[1].xyz);
+
+ // apply gamma correction for diffuse textures
+ //diffuseMat = pow(diffuseMat, 0.45);
+
+ float specularPower = emissiveReflectSpecPow.b*255.0f + 1.0f;
+
+ // TODO - fix this
+ specularPower = 10.0f;
+
+ float emissive = 0.0f;
+ float reflectivity = emissiveReflectSpecPow.b;
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(normal, eyeVec)), fresnelPower);
+ float specular = 0.0f;
+
+ vec3 skyNormal = reflect(eyeVec, normal);
+ vec3 skyColor = skyLightIntensity * textureCube(skyboxTex, skyNormal).rgb;
+ vec3 ambientSkyColor = diffuseMat * skyColor;
+
+ vec3 diffuseColor = vec3(0.0, 0.0, 0.0);
+
+ if (numShadows >= 1) {
+
+ vec3 lightColor = hdrScale * vec3(1.0, 1.0, 1.0);
+ vec3 shadowColor = vec3(0.4, 0.4, 0.7); // colored shadow
+ //vec3 lvec = normalize(spotLightDir);
+ vec3 lvec = normalize(spotLightPos - gl_TexCoord[1].xyz);
+ float cosine = dot(lvec, spotLightDir);
+ float intensity = smoothstep(spotLightCosineDecayBegin, spotLightCosineDecayEnd, cosine);
+
+ float ldn = max(0.0f, dot(normal, lvec));
+ float shadowC = shadowCoeff1();
+ //gl_FragColor = vec4(shadowC,shadowC,shadowC,1.0f);
+ //return;
+ vec3 irradiance = shadowC * ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance*intensity;
+
+ // add colored shadow
+ diffuseColor += (1.0 - shadowC) * shadowAmbient * shadowColor * diffuseMat*intensity;
+
+ vec3 r = reflect(lvec, normal);
+ specular += pow(max(0.0, dot(r, eyeVec)), specularPower)*shadowC*intensity;
+ }
+
+ // add rim light
+ if (numShadows >= 2) {
+ vec3 lightColor = hdrScale * vec3(1.0, 1.0, 1.0);
+ vec3 lvec = normalize(spotLightDir2);
+ float ldn = max(0.0f, dot(normal, lvec));
+ vec3 irradiance = ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance;
+ }
+
+ vec3 color = vec3(0.0, 0.0, 0.0);
+
+ color += diffuseColor;
+ color += ambientSkyColor;
+ color += specular*specularMat;
+ color += hdrScale * emissive * diffuseMat;
+
+ //vec3 reflectColor = diffuseMat * texture2DRect(reflectionTex, gl_FragCoord.xy).rgb;
+ //color = reflectionCoeff * reflectColor + (1.0f - reflectionCoeff) * color;
+ color = (fresnel * skyColor + (1.0 - fresnel) * color) * reflectivity + (1.0 - reflectivity) * color;
+
+ gl_FragColor.rgb = color;
+ gl_FragColor.w = gl_Color.w;
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[1].z), 0.0, 1.0);
+ //vec4 fogCol = gl_Fog.color;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end + gl_TexCoord[1].z), 0.0, 1.0);
+ vec4 fogCol = gl_Fog.color;
+ gl_FragColor = mix(fogCol, gl_FragColor, fog);
+
+}
+);
+
+#if TECHNICAL_MODE
+const char *grayVeinMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+ float noise3D(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+ }
+
+ float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+ }
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+
+
+ float noiseScale = 0.05f * extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 2.0f, 0.5f);
+
+ noise = spike(0.35f, 0.05f, noise);
+ noise = noise;
+
+ vec3 base = lerp(vec3(1.0f,1.0f,1.0f), vec3(0.9f,0.9f,0.9f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ vec3 b2 = lerp(base, vec3(0.8f, 0.8f, 0.8f), noise);
+ /*
+ return lerp(b2, vec3(0.5f,0.5f,0.5f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.4f, 3, 5.0f, 0.5f))
+ );
+ */
+ return 0.6*lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+ }
+);
+
+#else
+const char *grayVeinMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+ float noise3D(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+ }
+
+ float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+ }
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+
+
+ float noiseScale = 0.05f * extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 2.0f, 0.5f);
+
+ noise = spike(0.35f, 0.05f, noise);
+ noise = noise;
+
+ vec3 base = lerp(vec3(1.0f,1.0f,1.0f), vec3(0.9f,0.9f,0.9f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ vec3 b2 = lerp(base, vec3(0.8f, 0.8f, 0.8f), noise);
+ /*
+ return lerp(b2, vec3(0.5f,0.5f,0.5f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.4f, 3, 5.0f, 0.5f))
+ );
+ */
+ return lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+ }
+);
+
+#endif
+const char *sandStoneTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+float noise3D(vec3 p)
+{
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+}
+
+float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+}
+
+float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+}
+
+vec3 myTexture3DCom(vec3 p, float mat)
+{
+
+
+ float noiseScale = 0.1f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 3, 3.0f, 0.5f);
+ //noise = turbulence(p*noiseScale + vec3(noise, noise, noise*0.3)*0.01f, 8, 3.0f, 0.5f);
+
+ //noise = spike(0.35f, 0.05f, noise);
+ //noise = noise;
+
+ vec3 base = lerp(vec3(164,148,108)*1.63/255, vec3(178,156,126)*1.73/255, spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f + vec3(noise*0.5, noise, noise)*0.011f, 2, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(173, 160, 121)*1.73/255, noise);
+
+
+
+ return b2;
+
+
+
+
+
+}
+);
+const char *whiteMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+ float noise3D(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+ }
+
+ float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+ }
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+ float noiseScale = 0.05f * extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 2.0f, 0.5f);
+
+ noise = spike(0.35f, 0.05f, noise);
+ noise = noise;
+
+ vec3 base = lerp(vec3(1.0f,1.0f,1.0f), vec3(0.99f,0.99f,0.99f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ vec3 b2 = lerp(base, vec3(0.97f, 0.97f, 0.97f), noise);
+ /*
+ return lerp(b2, vec3(0.5f,0.5f,0.5f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.4f, 3, 5.0f, 0.5f))
+ );
+ */
+ return lerp(b2, vec3(0.95f,0.95f,0.95f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+ }
+);
+
+const char *blueVeinMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+
+ float noise3D(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+ }
+
+ float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+ }
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+
+
+ float noiseScale = 0.05f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 2.0f, 0.5f);
+
+ noise = spike(0.35f, 0.05f, noise);
+ noise = noise;
+
+ vec3 base = lerp(vec3(1.0f,1.0f,1.0f), vec3(0.9f,0.9f,0.9f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ vec3 b2 = lerp(base, vec3(0.7f, 0.7f, 0.9f), noise);
+
+ return lerp(b2, vec3(0.6f, 0.6f, 0.8f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.4f, 3, 5.0f, 0.5f))
+ );
+
+ // return lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+ }
+);
+
+const char *greenMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+float noise3D(vec3 p)
+{
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+}
+
+float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+}
+
+float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+}
+
+vec3 myTexture3DCom(vec3 p, float mat)
+{
+
+
+ float noiseScale = 0.05f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 2.0f, 0.5f);
+
+ noise = spike(0.35f, 0.05f, noise);
+ noise = noise;
+
+ vec3 base = lerp(vec3(0.2f,0.4f,0.2f), vec3(0.05f,0.3f,0.1f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(0.5f, 0.5f, 0.5f), noise);
+
+ //return lerp(b2, vec3(0.1f, 0.05f, 0.05f),
+ return lerp(b2, vec3(0.2f, 0.3f, 0.2f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4.3, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.5f, 3, 5.0f, 0.5f))
+ )*1.3f;
+
+ // return lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+}
+);
+
+const char *redGraniteTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+float noise3D(vec3 p)
+{
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+}
+
+float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+}
+
+float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+}
+
+vec3 myTexture3DCom(vec3 p, float mat)
+{
+
+
+ float noiseScale = 0.3f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 3.0f, 0.5f);
+
+ //noise = spike(0.35f, 0.05f, noise);
+ //noise = noise;
+
+ vec3 base = lerp(vec3(0.75,0.3f,0.25f), vec3(0.1f,0.1f,0.1f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f, 4, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(0.7f, 0.7f, 0.7f), noise);
+
+ return b2;
+ //return lerp(b2, vec3(0.1f, 0.05f, 0.05f),
+/* return lerp(b2, vec3(0.2f, 0.3f, 0.2f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4.3, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.5f, 3, 5.0f, 0.5f))
+ )*1.3f;
+ */
+
+ // return lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+}
+);
+
+const char *grayMarbleTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+float noise3D(vec3 p)
+{
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+}
+
+float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+}
+
+float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+}
+
+vec3 myTexture3DCom(vec3 p, float mat)
+{
+
+
+ float noiseScale = 0.05f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 3.0f, 0.5f);
+ noise = turbulence(p*noiseScale + vec3(noise, noise, noise)*0.015f, 8, 3.0f, 0.5f);
+
+ //noise = spike(0.35f, 0.05f, noise);
+ //noise = noise;
+
+ vec3 base = lerp(vec3(0.85,0.85f,0.85f), vec3(0.65f,0.65f,0.65f), spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f + vec3(noise,2*noise, 0)*0.01f, 4, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(0.3f, 0.3f, 0.3f), noise);
+
+ return b2;
+ //return lerp(b2, vec3(0.1f, 0.05f, 0.05f),
+/* return lerp(b2, vec3(0.2f, 0.3f, 0.2f),
+ spike(0.4f, 0.05f, turbulence(p*noiseScale, 4.3, 3.0f, 0.35f)) +
+ spike(0.3f, 0.05f, turbulence(p*noiseScale*0.5f, 3, 5.0f, 0.5f))
+ )*1.3f;
+ */
+
+ // return lerp(b2, vec3(0.7f,0.7f,0.7f), spike(0.35f, 0.05f, turbulence(p*noiseScale, 4, 3.0f, 0.35f)));
+ //return lerp(b2, vec3(0.5f,0.5f,0.5f), turbulence(p*noiseScale, 4, 3.0f, 0.35f));
+
+ //return lerp(base, vec3(0.1f, 0.1f, 0.4f), noise);
+ //return vec3(1.0f,1.0f,noise);
+ //return lerp(vec3(1.0f,1.0f,0.7f), vec3(0.1f,0.1f,0.4f), noise);
+}
+);
+
+const char *yellowGraniteTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ uniform float extraNoiseScale = 1.0f;
+float noise3D(vec3 p)
+{
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+}
+
+float turbulence(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for(int i=0; i<octaves; i++) {
+ sum += abs(noise3D(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+}
+
+float spike(float c, float w, float x) {
+ return smoothstep(c-w, c, x) * smoothstep(c+w, c, x);
+}
+
+vec3 myTexture3DCom(vec3 p, float mat)
+{
+
+
+ float noiseScale = 0.3f*extraNoiseScale;
+ float noise = turbulence(p*noiseScale, 8, 3.0f, 0.5f);
+ noise = turbulence(p*noiseScale + vec3(noise, noise, noise*0.3)*0.01f, 8, 3.0f, 0.5f);
+
+ //noise = spike(0.35f, 0.05f, noise);
+ //noise = noise;
+
+ vec3 base = lerp(vec3(236,219,151)/255, vec3(179,145,28)/255, spike(0.5f, 0.3f, turbulence(p*noiseScale*0.7f + vec3(noise*0.5, noise, noise)*0.011f, 4, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(0.1f, 0.1f, 0.1f), noise);
+
+ return b2;
+
+}
+);
+/*
+const char *woodTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+ float noise3D(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ uniform vec3 woodColor1 = vec3(0.5,0.3, 0.1);
+ uniform vec3 woodColor2 = vec3(0.25,0.15, 0.05);
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+
+ float noiseScale = 0.02f;
+ float ampScale = 3.0f;
+ float ringScale = 2.0f;
+
+ p.z *= 0.01f;
+ vec3 sp = p*noiseScale;
+ vec3 noise3 = vec3(noise3D(sp), noise3D(sp+vec3(0.1,0.5,-0.2)), noise3D(sp+vec3(0.2,1.5,-0.3)));
+
+ vec3 pwood = p + noise3*ampScale;
+ vec3 r = ringScale * sqrt(dot(pwood.xz, pwood.xz));
+ r = r + noise3D(sp+vec3(0.1,-1,2));
+ r = r - floor(r);
+ r = smoothstep(0.0, 0.8, r) - smoothstep(0.83,1,r);
+ vec3 col = lerp(woodColor1, woodColor2, r);
+ return col;
+ }
+);
+*/
+const char *woodTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+
+ uniform float extraNoiseScale = 1.0f;
+ uniform float noiseScale = 0.03f;
+ float noise(float p) {
+ return texture3D(ttt3D, vec3(p*noiseScale*extraNoiseScale,0.5,0.5)).x;
+ }
+
+ float noise(float p, float q) {
+ return texture3D(ttt3D, vec3(p*noiseScale*extraNoiseScale,q*noiseScale*extraNoiseScale,0.5)).x;
+ }
+
+ float snoise(float p) {
+ return noise(p)*2.0f - 1.0f;
+ }
+ float snoise(float p, float q) {
+ return noise(p,q)*2.0f - 1.0f;
+ }
+ float boxstep(float a, float b, float x) {
+ return (clamp(((x)-(a))/((b)-(a)),0,1));
+
+ }
+
+ uniform float Ka = 1;
+ uniform float Kd = 0.75;
+ uniform float Ks = 0.15;
+ uniform float roughness = 0.025;
+ uniform vec3 specularcolor = vec3(1,1,1);
+ uniform float ringscale = 0;
+ uniform float grainscale = 0;
+ uniform float txtscale = 1;
+ uniform float plankspertile = 4;
+ uniform vec3 lightwood = vec3(0.57, 0.292, 0.125);
+ uniform vec3 darkwood = vec3(0.275, 0.15, 0.06);
+ uniform vec3 groovecolor = vec3 (.05, .04, .015);
+ //uniform float plankwidth = .05;
+ uniform float plankwidth = .2;
+ uniform float groovewidth = 0.001;
+ uniform float plankvary = 0.8;
+ uniform float grainy = 1;
+ uniform float wavy = 0.08;
+ uniform float MINFILTERWIDTH = 1.0e-7;
+
+ vec3 myTexture3DCom(vec3 p, float mat)
+ {
+
+ float r;
+ float r2;
+ float whichrow;
+ float whichplank;
+ float swidth;
+ float twidth;
+ float fwidth;
+ float ss;
+ float tt;
+ float w;
+ float h;
+ float fade;
+ float ttt;
+ vec3 Ct;
+ vec3 woodcolor;
+ float groovy;
+ float PGWIDTH;
+ float PGHEIGHT;
+ float GWF;
+ float GHF;
+ float tilewidth;
+ float whichtile;
+ float tmp;
+ float planklength;
+
+
+ PGWIDTH = plankwidth+groovewidth;
+ planklength = PGWIDTH * plankspertile - groovewidth;
+
+ PGHEIGHT = planklength+groovewidth;
+ GWF = groovewidth*0.5/PGWIDTH;
+ GHF = groovewidth*0.5/PGHEIGHT;
+
+ // Determine how wide in s-t space one pixel projects to
+ float s = p.x;
+ float t = p.y;
+ float du = 1.0;
+ float dv = 1.0;
+
+ swidth = (max (abs(dFdx(s)*du) + abs(dFdy(s)*dv), MINFILTERWIDTH) /
+ PGWIDTH) * txtscale;
+ twidth = (max (abs(dFdx(t)*du) + abs(dFdy(t)*dv), MINFILTERWIDTH) /
+ PGHEIGHT) * txtscale;
+ fwidth = max(swidth,twidth);
+
+ ss = (txtscale * s) / PGWIDTH;
+ whichrow = floor (ss);
+ tt = (txtscale * t) / PGHEIGHT;
+ whichplank = floor(tt);
+
+ if (mod (whichrow/plankspertile + whichplank, 2) >= 1) {
+ ss = txtscale * t / PGWIDTH;
+ whichrow = floor (ss);
+ tt = txtscale * s / PGHEIGHT;
+ whichplank = floor(tt);
+ tmp = swidth; swidth = twidth; twidth = tmp;
+ }
+ ss -= whichrow;
+ tt -= whichplank;
+ whichplank += 20*(whichrow+10);
+
+ if (swidth >= 1)
+ w = 1 - 2*GWF;
+ else w = clamp (boxstep(GWF-swidth,GWF,ss), max(1-GWF/swidth,0), 1)
+ - clamp (boxstep(1-GWF-swidth,1-GWF,ss), 0, 2*GWF/swidth);
+ if (twidth >= 1)
+ h = 1 - 2*GHF;
+ else h = clamp (boxstep(GHF-twidth,GHF,tt), max(1-GHF/twidth,0),1)
+ - clamp (boxstep(1-GHF-twidth,1-GHF,tt), 0, 2*GHF/twidth);
+ // This would be the non-antialiased version:
+ //w = step (GWF,ss) - step(1-GWF,ss);
+ //h = step (GHF,tt) - step(1-GHF,tt);
+
+ groovy = w*h;
+
+
+
+ // Add the ring patterns
+ fade = smoothstep (1/ringscale, 8/ringscale, fwidth);
+ if (fade < 0.999) {
+
+ ttt = tt/4+whichplank/28.38 + wavy * noise (8*ss, tt/4);
+ r = ringscale * noise (ss-whichplank, ttt);
+ r -= floor (r);
+ r = 0.3+0.7*smoothstep(0.2,0.55,r)*(1-smoothstep(0.75,0.8, r));
+ r = (1-fade)*r + 0.65*fade;
+
+ // Multiply the ring pattern by the fine grain
+
+ fade = smoothstep (2/grainscale, 8/grainscale, fwidth);
+ if (fade < 0.999) {
+ r2 = 1.3 - noise (ss*grainscale, (tt*grainscale/4));
+ r2 = grainy * r2*r2 + (1-grainy);
+ r *= (1-fade)*r2 + (0.75*fade);
+
+ }
+ else r *= 0.75;
+
+ }
+ else r = 0.4875;
+
+
+ // Mix the light and dark wood according to the grain pattern
+ woodcolor = lerp (lightwood, darkwood, r);
+
+ // Add plank-to-plank variation in overall color
+ woodcolor *= (1-plankvary/2 + plankvary * noise (whichplank+0.5));
+
+ Ct = lerp (groovecolor, woodcolor, groovy);
+ return Ct;
+
+ }
+);
+
+const char *combineTexture = STRINGIFY(
+ uniform sampler3D ttt3D;
+
+ uniform float extraNoiseScale = 1.0f;
+ uniform float noiseScale = 0.03f;
+ float noise(float p) {
+ return texture3D(ttt3D, vec3(p*noiseScale*extraNoiseScale, 0.5, 0.5)).x;
+ }
+
+ float noise(float p, float q) {
+ return texture3D(ttt3D, vec3(p*noiseScale*extraNoiseScale, q*noiseScale*extraNoiseScale, 0.5)).x;
+ }
+
+ float snoise(float p) {
+ return noise(p)*2.0f - 1.0f;
+ }
+ float snoise(float p, float q) {
+ return noise(p, q)*2.0f - 1.0f;
+ }
+ float boxstep(float a, float b, float x) {
+ return (clamp(((x)-(a)) / ((b)-(a)), 0, 1));
+
+ }
+
+ uniform float Ka = 1;
+ uniform float Kd = 0.75;
+ uniform float Ks = 0.15;
+ uniform float roughness = 0.025;
+ uniform vec3 specularcolor = vec3(1, 1, 1);
+ uniform float ringscale = 0;
+ uniform float grainscale = 0;
+ uniform float txtscale = 1;
+ uniform float plankspertile = 4;
+ uniform vec3 lightwood = vec3(0.57, 0.292, 0.125);
+ uniform vec3 darkwood = vec3(0.275, 0.15, 0.06);
+ uniform vec3 groovecolor = vec3(.05, .04, .015);
+ //uniform float plankwidth = .05;
+ uniform float plankwidth = .2;
+ uniform float groovewidth = 0.001;
+ uniform float plankvary = 0.8;
+ uniform float grainy = 1;
+ uniform float wavy = 0.08;
+ uniform float MINFILTERWIDTH = 1.0e-7;
+
+ vec3 myTexture3D_0(vec3 p)
+ {
+ float r;
+ float r2;
+ float whichrow;
+ float whichplank;
+ float swidth;
+ float twidth;
+ float fwidth;
+ float ss;
+ float tt;
+ float w;
+ float h;
+ float fade;
+ float ttt;
+ vec3 Ct;
+ vec3 woodcolor;
+ float groovy;
+ float PGWIDTH;
+ float PGHEIGHT;
+ float GWF;
+ float GHF;
+ float tilewidth;
+ float whichtile;
+ float tmp;
+ float planklength;
+
+
+ PGWIDTH = plankwidth + groovewidth;
+ planklength = PGWIDTH * plankspertile - groovewidth;
+
+ PGHEIGHT = planklength + groovewidth;
+ GWF = groovewidth*0.5 / PGWIDTH;
+ GHF = groovewidth*0.5 / PGHEIGHT;
+
+ // Determine how wide in s-t space one pixel projects to
+ float s = p.x;
+ float t = p.y;
+ float du = 1.0;
+ float dv = 1.0;
+
+ swidth = (max(abs(dFdx(s)*du) + abs(dFdy(s)*dv), MINFILTERWIDTH) /
+ PGWIDTH) * txtscale;
+ twidth = (max(abs(dFdx(t)*du) + abs(dFdy(t)*dv), MINFILTERWIDTH) /
+ PGHEIGHT) * txtscale;
+ fwidth = max(swidth, twidth);
+
+ ss = (txtscale * s) / PGWIDTH;
+ whichrow = floor(ss);
+ tt = (txtscale * t) / PGHEIGHT;
+ whichplank = floor(tt);
+
+ if (mod(whichrow / plankspertile + whichplank, 2) >= 1) {
+ ss = txtscale * t / PGWIDTH;
+ whichrow = floor(ss);
+ tt = txtscale * s / PGHEIGHT;
+ whichplank = floor(tt);
+ tmp = swidth; swidth = twidth; twidth = tmp;
+ }
+ ss -= whichrow;
+ tt -= whichplank;
+ whichplank += 20 * (whichrow + 10);
+
+ if (swidth >= 1)
+ w = 1 - 2 * GWF;
+ else w = clamp(boxstep(GWF - swidth, GWF, ss), max(1 - GWF / swidth, 0), 1)
+ - clamp(boxstep(1 - GWF - swidth, 1 - GWF, ss), 0, 2 * GWF / swidth);
+ if (twidth >= 1)
+ h = 1 - 2 * GHF;
+ else h = clamp(boxstep(GHF - twidth, GHF, tt), max(1 - GHF / twidth, 0), 1)
+ - clamp(boxstep(1 - GHF - twidth, 1 - GHF, tt), 0, 2 * GHF / twidth);
+ // This would be the non-antialiased version:
+ //w = step (GWF,ss) - step(1-GWF,ss);
+ //h = step (GHF,tt) - step(1-GHF,tt);
+
+ groovy = w*h;
+
+
+
+ // Add the ring patterns
+ fade = smoothstep(1 / ringscale, 8 / ringscale, fwidth);
+ if (fade < 0.999) {
+
+ ttt = tt / 4 + whichplank / 28.38 + wavy * noise(8 * ss, tt / 4);
+ r = ringscale * noise(ss - whichplank, ttt);
+ r -= floor(r);
+ r = 0.3 + 0.7*smoothstep(0.2, 0.55, r)*(1 - smoothstep(0.75, 0.8, r));
+ r = (1 - fade)*r + 0.65*fade;
+
+ // Multiply the ring pattern by the fine grain
+
+ fade = smoothstep(2 / grainscale, 8 / grainscale, fwidth);
+ if (fade < 0.999) {
+ r2 = 1.3 - noise(ss*grainscale, (tt*grainscale / 4));
+ r2 = grainy * r2*r2 + (1 - grainy);
+ r *= (1 - fade)*r2 + (0.75*fade);
+
+ }
+ else r *= 0.75;
+
+ }
+ else r = 0.4875;
+
+
+ // Mix the light and dark wood according to the grain pattern
+ woodcolor = lerp(lightwood, darkwood, r);
+
+ // Add plank-to-plank variation in overall color
+ woodcolor *= (1 - plankvary / 2 + plankvary * noise(whichplank + 0.5));
+
+ Ct = lerp(groovecolor, woodcolor, groovy);
+ return Ct;
+
+ }
+
+ float noise3D_1(vec3 p)
+ {
+ return texture3D(ttt3D, p).x*2.0f - 1.0f;
+ }
+
+ float turbulence_1(vec3 p, int octaves, float lacunarity, float gain) {
+
+ float freq = 1.0f;
+ float amp = 0.8f;
+ float sum = 0.0f;
+
+ for (int i = 0; i<octaves; i++) {
+ sum += abs(noise3D_1(p*freq))*amp;
+ freq *= lacunarity;
+ amp *= gain;
+ }
+ return sum;
+ }
+
+ float spike_1(float c, float w, float x) {
+ return smoothstep(c - w, c, x) * smoothstep(c + w, c, x);
+ }
+
+ vec3 myTexture3D_1(vec3 p)
+ {
+
+
+ float noiseScale = 0.1f*extraNoiseScale;
+ float noise = turbulence_1(p*noiseScale, 3, 3.0f, 0.5f);
+ //noise = turbulence(p*noiseScale + vec3(noise, noise, noise*0.3)*0.01f, 8, 3.0f, 0.5f);
+
+ //noise = spike(0.35f, 0.05f, noise);
+ //noise = noise;
+
+ vec3 base = lerp(vec3(164, 148, 108)*1.63 / 255, vec3(178, 156, 126)*1.73 / 255, spike_1(0.5f, 0.3f, turbulence_1(p*noiseScale*0.7f + vec3(noise*0.5, noise, noise)*0.011f, 2, 2.0f, 0.5f)));
+ //vec3 b2 = lerp(base, vec3(0.0f, 0.0f, 0.0f), noise);
+ vec3 b2 = lerp(base, vec3(173, 160, 121)*1.73 / 255, noise);
+
+
+
+ return b2*0.75f;
+
+ }
+
+ vec3 myTexture3DCom(vec3 p, float mat) {
+ // Depend on material ID
+ if (mat < 0.5f) {
+ return vec3(173, 160, 151) *0.85 / 255;
+ //return darkwood;
+ //return vec3(0.75f, 0.75f, 0.75f);
+ }
+ else
+ if (mat < 1.5f) {
+ //return vec3(173, 160, 121)*1.73 / 255;
+ return vec3(173, 100, 21)*1.73 / 255;
+ }
+ else {
+ return vec3(1.0f, 0.0f, 0.0f);
+
+ }
+ /*
+ if (mat < 0.5f) {
+ return myTexture3D_0(p);
+ }
+ else
+ if (mat < 1.5f) {
+ return myTexture3D_1(p);
+ } else {
+ return vec3(1.0f, 0.0f, 0.0f);
+
+ }
+ */
+ }
+
+);
+
+#if TECHNICAL_MODE
+const char *shadowDiffuse3DFragmentProgram = STRINGIFY(
+ // scene reflection
+ uniform float reflectionCoeff = 0.0f;
+uniform float specularCoeff = 0.0f;
+
+uniform sampler2DRect reflectionTex;
+
+// Shadow map
+uniform float shadowAmbient = 0.0;
+uniform float hdrScale = 5.0;
+uniform sampler2D texture;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DArrayShadow stex2;
+uniform sampler2DArrayShadow stex3;
+uniform samplerCube skyboxTex;
+uniform vec2 texSize; // x - size, y - 1/size
+uniform vec4 far_d;
+
+// Spot lights
+uniform vec3 spotLightDir;
+uniform vec3 spotLightPos;
+uniform float spotLightCosineDecayBegin;
+uniform float spotLightCosineDecayEnd;
+
+uniform vec3 spotLightDir2;
+uniform vec3 spotLightPos2;
+uniform float spotLightCosineDecayBegin2;
+uniform float spotLightCosineDecayEnd2;
+
+uniform vec3 spotLightDir3;
+uniform vec3 spotLightPos3;
+uniform float spotLightCosineDecayBegin3;
+uniform float spotLightCosineDecayEnd3;
+
+uniform vec3 parallelLightDir;
+uniform float shadowAdd;
+uniform int useTexture;
+uniform int numShadows;
+
+
+uniform float roughnessScale;
+uniform vec3 ambientColor;
+
+uniform sampler2DArray diffuseTexArray;
+uniform sampler2DArray bumpTexArray;
+uniform sampler2DArray specularTexArray;
+uniform sampler2DArray emissiveReflectSpecPowerTexArray;
+
+uniform vec2 shadowTaps[12];
+
+
+float shadowCoeff1()
+{
+
+ int index = 3;
+
+ if (gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if (gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if (gl_FragCoord.z < far_d.z)
+ index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ // return shadow2DArray(stex, shadow_coord).x;
+ /*
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;*/
+ const int numTaps = 4;
+ float radius = 0.0005f / pow(2, index);
+ float s = 0.0f;
+ for (int i = 0; i < numTaps; i++)
+ {
+ s += shadow2DArray(stex, shadow_coord + vec4(shadowTaps[i] * radius, 0.0f, 0.0f)).r;
+ }
+ s /= numTaps;
+ return s;
+}
+float shadowCoeff2()
+{
+ const int index = 1;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+ // return shadow2DArray(stex, shadow_coord).x;
+
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex2, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(-X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(-X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(-X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2(X, X)).x * 0.0625;
+ return ret;
+}
+float shadowCoeff3()
+{
+ const int index = 2;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index] * vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+
+ // return shadow2DArray(stex, shadow_coord).x;
+
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex3, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(-X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(-X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(-X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2(X, X)).x * 0.0625;
+ return ret;
+}
+
+
+
+uniform float RollOff = 0.5f;
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 3.0; // 5.0 is physically correct
+void main()
+{
+
+ /*
+ int index = 3;
+
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ if (index == 3) gl_FragColor = vec4(1,0,0,1);
+ if (index == 2) gl_FragColor = vec4(0,1,0,1);
+ if (index == 1) gl_FragColor = vec4(0,0,1,1);
+ if (index == 0) gl_FragColor = vec4(1,1,0,1);
+ return;*/
+ /*
+ int index = 3;
+
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index)*0.33333333f;
+ gl_FragColor = vec4(shadow_coord.xyz,1.0f);
+ return;
+ */
+ //// TODO, expose this as user parameter
+ const float skyLightIntensity = 0.2;
+ const float rimLightIntensity = 0.3;
+
+ vec3 normal = normalize(gl_TexCoord[2].xyz);
+ vec3 t0 = gl_TexCoord[3].xyz;
+ vec3 t1 = gl_TexCoord[4].xyz;
+
+ vec3 diffuseMat;
+ vec3 specularMat;
+ vec3 bump;
+ vec3 emissiveReflectSpecPow;
+
+ // read in material color for diffuse, specular, bump, emmisive
+
+ // 3D texture
+ diffuseMat = myTexture3DCom(gl_TexCoord[0].xyz, gl_TexCoord[6].w);
+ //diffuseMat = myTexture3D(gl_TexCoord[0].xyz);//texture3D(ttt3D, gl_TexCoord[0].xyz);
+ //diffuseMat = texture3D(ttt3D, gl_TexCoord[0].xyz);
+
+ specularMat = vec3(1.0);
+ bump = texture2D(texture, gl_TexCoord[5].xy).xyz;
+ if (dot(bump, bump) < 0.01) bump = vec3(0.5, 0.5, 1);
+ emissiveReflectSpecPow = vec3(0.0, 0.0, 0.0);
+
+
+ // apply bump to the normal
+ bump = (bump - vec3(0.5, 0.5, 0.5)) * 2.0f;
+ bump.xy *= roughnessScale*0.1;
+
+ float sc = 1.0f;
+ normal = normalize(t0*bump.x + t1*bump.y + sc*normal * bump.z);
+
+ //gl_FragColor.xyz = normal*0.5 + vec3(0.5,0.5,0.5);
+ //gl_FragColor.w = 1;
+ //return;
+ vec3 eyeVec = normalize(gl_TexCoord[1].xyz);
+
+ // apply gamma correction for diffuse textures
+ //diffuseMat = pow(diffuseMat, 0.45);
+
+ float specularPower = emissiveReflectSpecPow.b*255.0f + 1.0f;
+
+ // TODO - fix this
+ specularPower = 10.0f;
+
+ float emissive = 0.0f;
+ float reflectivity = emissiveReflectSpecPow.b;
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(normal, eyeVec)), fresnelPower);
+ float specular = 0.0f;
+
+ vec3 skyNormal = reflect(eyeVec, normal);
+ vec3 skyColor = skyLightIntensity * textureCube(skyboxTex, skyNormal).rgb;
+ vec3 ambientSkyColor = diffuseMat * skyColor;
+
+ vec3 diffuseColor = vec3(0.0, 0.0, 0.0);
+
+ if (numShadows >= 1) {
+
+ vec3 lightColor = hdrScale * vec3(1.0, 1.0, 1.0);
+ vec3 shadowColor = vec3(0.4, 0.4, 0.7); // colored shadow
+ //vec3 lvec = normalize(spotLightDir);
+ vec3 lvec = normalize(spotLightPos - gl_TexCoord[1].xyz);
+ float cosine = dot(lvec, spotLightDir);
+ float intensity = smoothstep(spotLightCosineDecayBegin, spotLightCosineDecayEnd, cosine);
+
+ float ldn = max(0.0f, dot(normal, lvec));
+ float shadowC = shadowCoeff1();
+ //gl_FragColor = vec4(shadowC,shadowC,shadowC,1.0f);
+ //return;
+ vec3 irradiance = shadowC * ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance*intensity;
+
+ // add colored shadow
+ diffuseColor += (1.0 - shadowC) * shadowAmbient * shadowColor * diffuseMat*intensity;
+
+ vec3 r = reflect(lvec, normal);
+ specular += pow(max(0.0, dot(r, eyeVec)), specularPower)*shadowC*intensity;
+ }
+
+ // add rim light
+ if (numShadows >= 2) {
+ vec3 lightColor = hdrScale * vec3(1.0, 1.0, 1.0);
+ vec3 lvec = normalize(spotLightDir2);
+ float ldn = max(0.0f, dot(normal, lvec));
+ vec3 irradiance = ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance;
+ }
+
+ vec3 color = vec3(0.0, 0.0, 0.0);
+
+ color += diffuseColor;
+ color += ambientSkyColor;
+ color += specular*specularMat;
+ color += hdrScale * emissive * diffuseMat;
+
+ //vec3 reflectColor = diffuseMat * texture2DRect(reflectionTex, gl_FragCoord.xy).rgb;
+ //color = reflectionCoeff * reflectColor + (1.0f - reflectionCoeff) * color;
+ color = (fresnel * skyColor + (1.0 - fresnel) * color) * reflectivity + (1.0 - reflectivity) * color;
+
+ gl_FragColor.rgb = color;
+ gl_FragColor.w = gl_Color.w;
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[1].z), 0.0, 1.0);
+ vec4 fogCol = gl_Fog.color;
+ gl_FragColor = mix(fogCol, gl_FragColor, fog);
+}
+);
+#else
+const char *shadowDiffuse3DFragmentProgram = STRINGIFY(
+ // scene reflection
+ uniform float reflectionCoeff = 0.0f;
+uniform float specularCoeff = 0.0f;
+
+uniform sampler2DRect reflectionTex;
+
+// Shadow map
+uniform float shadowAmbient = 0.0;
+uniform float hdrScale = 5.0;
+uniform sampler2D texture;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DArrayShadow stex2;
+uniform sampler2DArrayShadow stex3;
+uniform samplerCube skyboxTex;
+uniform vec2 texSize; // x - size, y - 1/size
+uniform vec4 far_d;
+
+// Spot lights
+uniform vec3 spotLightDir;
+uniform vec3 spotLightPos;
+uniform float spotLightCosineDecayBegin;
+uniform float spotLightCosineDecayEnd;
+
+uniform vec3 spotLightDir2;
+uniform vec3 spotLightPos2;
+uniform float spotLightCosineDecayBegin2;
+uniform float spotLightCosineDecayEnd2;
+
+uniform vec3 spotLightDir3;
+uniform vec3 spotLightPos3;
+uniform float spotLightCosineDecayBegin3;
+uniform float spotLightCosineDecayEnd3;
+
+uniform vec3 parallelLightDir;
+uniform float shadowAdd;
+uniform int useTexture;
+uniform int numShadows;
+
+
+uniform float roughnessScale;
+uniform vec3 ambientColor;
+
+uniform sampler2DArray diffuseTexArray;
+uniform sampler2DArray bumpTexArray;
+uniform sampler2DArray specularTexArray;
+uniform sampler2DArray emissiveReflectSpecPowerTexArray;
+
+
+
+float shadowCoeff1()
+{
+ const int index = 0;
+
+ //int index = 3;
+ //
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ // return shadow2DArray(stex, shadow_coord).x;
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;
+}
+float shadowCoeff2()
+{
+ const int index = 1;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+ // return shadow2DArray(stex, shadow_coord).x;
+
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex2, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex2, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;
+}
+float shadowCoeff3()
+{
+ const int index = 2;
+
+ //int index = 3;
+ //if(gl_FragCoord.z < far_d.x)
+ // index = 0;
+ //else if(gl_FragCoord.z < far_d.y)
+ // index = 1;
+ //else if(gl_FragCoord.z < far_d.z)
+ // index = 2;
+
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[1].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z + shadowAdd;
+ shadow_coord.z = float(0);
+
+ // return shadow2DArray(stex, shadow_coord).x;
+
+ const float X = 1.0f;
+ float ret = shadow2DArray(stex3, shadow_coord).x * 0.25;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( -X, X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( 0, -X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( 0, X)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, -X)).x * 0.0625;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, 0)).x * 0.125;
+ ret += shadow2DArrayOffset(stex3, shadow_coord, ivec2( X, X)).x * 0.0625;
+ return ret;
+}
+
+
+
+uniform float RollOff = 0.5f;
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 3.0; // 5.0 is physically correct
+void main()
+{
+ //// TODO, expose this as user parameter
+ const float skyLightIntensity = 0.2;
+ const float rimLightIntensity = 0.3;
+
+ vec3 normal = normalize(gl_TexCoord[2].xyz);
+ vec3 t0 = gl_TexCoord[3].xyz;
+ vec3 t1 = gl_TexCoord[4].xyz;
+
+ vec3 diffuseMat;
+ vec3 specularMat;
+ vec3 bump;
+ vec3 emissiveReflectSpecPow;
+
+ // read in material color for diffuse, specular, bump, emmisive
+ if (gl_TexCoord[6].z >= 0.0f) {
+ // 2D texture
+ diffuseMat = texture2DArray(diffuseTexArray, gl_TexCoord[6].xyz).rgb;
+ //specularMat = texture2DArray(specularTexArray, gl_TexCoord[6].xyz).rgb; // TODO Does not seem to work
+ specularMat = vec3(1.0f);
+ bump = texture2DArray(bumpTexArray, gl_TexCoord[6].xyz).xyz;
+ if (dot(bump,bump) < 0.01) bump = vec3(0.5,0.5,1);
+ emissiveReflectSpecPow = texture2DArray(emissiveReflectSpecPowerTexArray, gl_TexCoord[6].xyz).xyz;
+
+ } else {
+ // 3D texture
+ diffuseMat = myTexture3DCom(gl_TexCoord[0].xyz,0.0f) * vec3(0.5,0.5,0.5);//texture3D(ttt3D, gl_TexCoord[0].xyz);
+ specularMat = vec3(1.0);
+ bump = texture2D(texture, gl_TexCoord[5].xy).xyz;
+ if (dot(bump,bump) < 0.01) bump = vec3(0.5,0.5,1);
+ emissiveReflectSpecPow = vec3(0.0,0.0,0.0);
+ }
+
+ // apply bump to the normal
+ bump = (bump - vec3(0.5,0.5,0.5)) * 2.0f;
+ bump.xy *= roughnessScale*2;
+
+ float sc = 1.0f;
+ normal = normalize(t0*bump.x + t1*bump.y + sc*normal * bump.z);
+
+ //gl_FragColor.xyz = normal*0.5 + vec3(0.5,0.5,0.5);
+ //gl_FragColor.w = 1;
+ //return;
+ vec3 eyeVec = normalize(gl_TexCoord[1].xyz);
+
+ // apply gamma correction for diffuse textures
+ diffuseMat.x = pow(diffuseMat.x, 0.45);
+ diffuseMat.y = pow(diffuseMat.y, 0.45);
+ diffuseMat.z = pow(diffuseMat.z, 0.45);
+
+ float specularPower = emissiveReflectSpecPow.b*255.0f + 1.0f;
+
+ // TODO - fix this
+ specularPower = 10.0f;
+
+ float emissive = emissiveReflectSpecPow.r*10.0f;
+ float reflectivity = emissiveReflectSpecPow.b;
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(normal, eyeVec)), fresnelPower);
+ float specular = 0.0f;
+
+ vec3 skyNormal = reflect(eyeVec, normal);
+ vec3 skyColor = skyLightIntensity * textureCube(skyboxTex, skyNormal).rgb;
+ vec3 ambientSkyColor = diffuseMat * skyColor;
+
+ vec3 diffuseColor = vec3(0.0, 0.0, 0.0);
+
+ if (numShadows >= 1) {
+ vec3 lightColor = hdrScale * vec3(1.0, 0.9, 0.9);
+ vec3 shadowColor = vec3(0.4, 0.4, 0.9); // colored shadow
+ vec3 lvec = normalize(spotLightDir);
+ float ldn = max(0.0f, dot(normal, lvec));
+ float shadowC = shadowCoeff1();
+ vec3 irradiance = shadowC * ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance;
+
+ // add colored shadow
+ diffuseColor += (1.0 - shadowC) * shadowAmbient * shadowColor * diffuseMat;
+
+ vec3 r = reflect(lvec, normal);
+ specular += pow(max(0.0, dot(r,eyeVec)), specularPower)*shadowC;
+ }
+
+ // add rim light
+ if (numShadows >= 2) {
+ vec3 lightColor = rimLightIntensity * vec3(1.0, 0.9, 0.9);
+ vec3 lvec = normalize(spotLightDir2);
+ float ldn = max(0.0f, dot(normal, lvec));
+ vec3 irradiance = ldn * lightColor;
+
+ // diffuse irradiance
+ diffuseColor += diffuseMat * irradiance;
+ }
+
+ vec3 color = vec3(0.0, 0.0, 0.0);
+
+ color += diffuseColor;
+ color += ambientSkyColor;
+ color += specular*specularMat;
+ color += hdrScale * emissive * diffuseMat;
+
+ //vec3 reflectColor = diffuseMat * texture2DRect(reflectionTex, gl_FragCoord.xy).rgb;
+ //color = reflectionCoeff * reflectColor + (1.0f - reflectionCoeff) * color;
+ color = (fresnel * skyColor + (1.0 - fresnel) * color) * reflectivity + (1.0 - reflectivity) * color;
+
+ gl_FragColor.rgb = color;
+ gl_FragColor.w = gl_Color.w;
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[1].z), 0.0, 1.0);
+ vec4 fogCol = gl_Fog.color;
+ gl_FragColor = mix(fogCol, gl_FragColor, fog);
+}
+);
+#endif
+// --------------------------------------------------------------------------------------------
+
+
+// --------------------------------------------------------------------------------------------
+const char *whiteFragmentProgram = STRINGIFY(
+void main()
+{
+ gl_FragColor = vec4(1.0,1.0,1.0,1.0);
+}
+);
+
+const char *normalFragmentProgram = STRINGIFY(
+void main()
+{
+ gl_FragColor = vec4(normalize(gl_TexCoord[2].xyz) * 0.5 + 0.5, 1.0);
+}
+);
+
+ShaderShadow::ShaderShadow(VS_MODE vsMode, PS_MODE psMode, SHADER3D_CHOICES shade3D) : vsMode(vsMode), psMode(psMode), myShade3DChoice(shade3D)
+{
+ for (int i = 0; i < mNumLights; i++)
+ mShadowMaps[i] = NULL;
+ mReflectionTexId = 0;
+
+ for (int i = 0; i < 16; i++) {
+ mCamModelView[i] = i%5 == 0 ? 1.0f : 0.0f;
+ mCamProj[i] = i%5 == 0 ? 1.0f : 0.0f;
+ }
+ mNumShadows = mNumLights;
+ mShowReflection = false;
+ shadowAmbient = 0.2f;
+ //ambientColor = 0.2f;
+ ambientColor = PxVec3(0.1f, 0.1f, 0.2f);
+
+ switch (shade3D) {
+ case SAND_STONE: fragmentShader3DComposite = std::string(sandStoneTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(195,179,146)*1.23f/255.0f; break;
+ case GRAYVEIN_MARBLE: fragmentShader3DComposite = std::string(grayVeinMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(1.0f,1.0f,1.0f); break;
+ case WHITE_MARBLE: fragmentShader3DComposite = std::string(whiteMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(1.0f,1.0f,1.0f); break;
+ case BLUEVEIN_MARBLE: fragmentShader3DComposite = std::string(blueVeinMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(1.0f,1.0f,1.0f); break;
+ case GREEN_MARBLE: fragmentShader3DComposite = std::string(greenMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(0.3f,0.5f,0.3f); break;
+ case GRAY_MARBLE: fragmentShader3DComposite = std::string(grayMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(1.0f,1.0f,1.0f); break;
+ case RED_GRANITE: fragmentShader3DComposite = std::string(redGraniteTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(0.7f,0.45f,0.4f); break;
+ case YELLOW_GRANITE: fragmentShader3DComposite = std::string(yellowGraniteTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(236,219,151)/255.0f; break;
+ case WOOD: fragmentShader3DComposite = std::string(woodTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(156,90,60)/255.0f; break;
+ case COMBINE: fragmentShader3DComposite = std::string(combineTexture) + std::string(shadowDiffuse3DFragmentProgram); dustColor = PxVec3(156, 90, 60) / 255.0f; break;
+ }
+
+ whiteShader = NULL;
+ normalShader = NULL;
+ if ((psMode != PS_WHITE) && (psMode != PS_NORMAL)) {
+ whiteShader = new ShaderShadow(vsMode, PS_WHITE, shade3D);
+ normalShader = new ShaderShadow(vsMode, PS_NORMAL, shade3D);
+ }
+
+
+
+
+ /*
+ if (shade3D == GRAY_MARBLE) {
+ fragmentShader3DComposite = std::string(grayMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram);
+ } else
+ if (shade3D == BLUE_MARBLE) {
+ fragmentShader3DComposite = std::string(blueMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram);
+ } else {
+ fragmentShader3DComposite = std::string(grayMarbleTexture) + std::string(shadowDiffuse3DFragmentProgram);
+ }
+*/
+//
+ //fragmentShader3DComposite = std::string(yellowGraniteTexture) + std::string(shadowDiffuse3DFragmentProgram);
+
+}
+
+// --------------------------------------------------------------------------------------------
+bool ShaderShadow::init()
+{
+ for (int i = 0; i < mNumLights; i++)
+ mShadowMaps[i] = NULL;
+
+ // some defaults
+ for (int i = 0; i < mNumLights; i++) {
+ mSpotLightCosineDecayBegin[i] = 0.98f;
+ mSpotLightCosineDecayEnd[i] = 0.997f;
+ mSpotLightPos[i] = PxVec3(10.0f, 10.0f, 10.0f);
+ mSpotLightDir[i] = PxVec3(0.0f, 0.0f, 0.0f) - mSpotLightPos[i];
+ mSpotLightDir[i].normalize();
+ }
+
+ mBackLightDir = PxVec3(0, 20.0f, 20.0f);
+ const char* vsProg = 0;
+ const char* psProg = 0;
+ if (vsMode == VS_DEFAULT) vsProg = shadowDiffuseVertexProgram;
+ if (vsMode == VS_4BONES) vsProg = shadowDiffuseVertexProgram4Bones;
+ if (vsMode == VS_8BONES) vsProg = shadowDiffuseVertexProgram8Bones;
+ if (vsMode == VS_INSTANCE) vsProg = shadowDiffuseVertexProgramInstance;
+ if (vsMode == VS_TEXINSTANCE) vsProg = shadowDiffuseVertexProgramTexInstance;
+ if (vsMode == VS_DEFAULT_FOR_3D_TEX) vsProg = shadowDiffuseVertexProgramFor3DTex;
+ if (vsMode == VS_CROSSHAIR) vsProg = crossHairVertexProgram;
+
+
+ if (psMode == PS_SHADE3D) psProg = fragmentShader3DComposite.c_str();
+ if (psMode == PS_SHADE) psProg = shadowDiffuseFragmentProgram;
+ if (psMode == PS_WHITE) psProg = whiteFragmentProgram;
+ if (psMode == PS_NORMAL) psProg = normalFragmentProgram;
+ if (psMode == PS_CROSSHAIR) psProg = crossHairFragmentProgram;
+
+
+/* if (vsMode == VS_4BONES) {
+ if (!loadShaderCode(shadowDiffuseVertexProgram4Bones, shadowDiffuseFragmentProgram))
+ return false;
+
+ } else {
+ if (!loadShaderCode(shadowDiffuseVertexProgram, shadowDiffuseFragmentProgram))
+ return false;
+ }*/
+ if (!loadShaderCode(vsProg, psProg))
+ return false;
+
+ if ((psMode != PS_WHITE) && (psMode != PS_NORMAL)) {
+ whiteShader->init();
+ normalShader->init();
+ }
+
+ return true;
+}
+
+// --------------------------------------------------------------------------------------------
+void ShaderShadow::setSpotLight(int nr, const PxVec3 &pos, PxVec3 &dir, float decayBegin, float decayEnd)
+{
+ if (nr < 0 || nr >= mNumLights)
+ return;
+
+ mSpotLightPos[nr] = pos;
+ mSpotLightDir[nr] = dir;
+
+ mSpotLightCosineDecayBegin[nr] = decayBegin;
+ mSpotLightCosineDecayEnd[nr] = decayEnd;
+}
+
+// --------------------------------------------------------------------------------------------
+void ShaderShadow::updateCamera(float* modelView, float* proj)
+{
+ for (int i = 0; i < 16; i++) {
+ mCamModelView[i] = modelView[i];
+ mCamProj[i] = proj[i];
+ }
+}
+
+// --------------------------------------------------------------------------------------------
+void ShaderShadow::setShadowAmbient(float sa) {
+ shadowAmbient = sa;
+}
+
+// --------------------------------------------------------------------------------------------
+void ShaderShadow::activate(const ShaderMaterial &mat)
+{
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ whiteShader->activate(mat);
+ return;
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ normalShader->activate(mat);
+ return;
+ }
+ Shader::activate(mat);
+ if ((psMode == PS_WHITE) || (psMode == PS_NORMAL)) return;
+
+ for (int i = 0; i < mNumShadows; i++) {
+ if (mShadowMaps[i] == NULL)
+ return;
+ }
+
+ // surface texture
+ setUniform("texture", 0);
+ if (mat.texId > 0) {
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, mat.texId);
+ setUniform("useTexture", 1);
+ }
+ else
+ setUniform("useTexture", 0);
+
+ setUniform("numShadows", mNumShadows);
+
+ glColor4fv(mat.color);
+
+ // the three shadow maps
+ if (mShadowMaps[0] != NULL) {
+ glActiveTexture(GL_TEXTURE2);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mShadowMaps[0]->getDepthTexArray());
+ glTexParameteri( GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+
+ int size = mShadowMaps[0]->getTextureSize();
+ setUniform2("texSize", (float)size, 1.0f /size);
+ setUniform1("specularCoeff", mat.specularCoeff);
+ }
+ setUniform("stex", 2);
+
+ if (mNumLights > 1) {
+ if (mShadowMaps[1] != NULL) {
+ glActiveTexture(GL_TEXTURE3);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mShadowMaps[1]->getDepthTexArray());
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ }
+ setUniform("stex2", 3);
+ }
+
+ if (mNumLights > 2) {
+ if (mShadowMaps[2] != NULL) {
+ glActiveTexture(GL_TEXTURE4);
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, mShadowMaps[2]->getDepthTexArray());
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ }
+ setUniform("stex3", 4);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+ setUniform1("shadowAdd", g_shadowAdd);
+
+ glActiveTexture(GL_TEXTURE5);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mReflectionTexId);
+ setUniform("reflectionTex", 5);
+ if (mShowReflection)
+ setUniform1("reflectionCoeff", mat.reflectionCoeff);
+ else
+ setUniform1("reflectionCoeff", 0.0f);
+
+ if (ShaderShadow::skyBoxTex > 0)
+ {
+ glActiveTexture(GL_TEXTURE6);
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, ShaderShadow::skyBoxTex);
+ setUniform("skyboxTex", 6);
+ }
+
+ PxMat44 camTrans(mCamModelView);
+ PxVec3 eyePos, eyeDir;
+
+ eyePos = camTrans.transform(mSpotLightPos[0]);
+ eyeDir = camTrans.rotate(mSpotLightDir[0]); eyeDir.normalize();
+ setUniform3("spotLightDir", eyeDir.x, eyeDir.y, eyeDir.z);
+ setUniform3("spotLightPos", eyePos.x, eyePos.y, eyePos.z);
+ setUniform1("spotLightCosineDecayBegin", mSpotLightCosineDecayBegin[0]);
+ setUniform1("spotLightCosineDecayEnd", mSpotLightCosineDecayEnd[0]);
+
+ eyePos = camTrans.transform(mSpotLightPos[1]);
+ eyeDir = camTrans.rotate(mSpotLightDir[1]); eyeDir.normalize();
+ setUniform3("spotLightDir2", eyeDir.x, eyeDir.y, eyeDir.z);
+ setUniform3("spotLightPos2", eyePos.x, eyePos.y, eyePos.z);
+ setUniform1("spotLightCosineDecayBegin2", mSpotLightCosineDecayBegin[1]);
+ setUniform1("spotLightCosineDecayEnd2", mSpotLightCosineDecayEnd[1]);
+
+ eyePos = camTrans.transform(mSpotLightPos[2]);
+ eyeDir = camTrans.rotate(mSpotLightDir[2]); eyeDir.normalize();
+ setUniform3("spotLightDir3", eyeDir.x, eyeDir.y, eyeDir.z);
+ setUniform3("spotLightPos3", eyePos.x, eyePos.y, eyePos.z);
+ setUniform1("spotLightCosineDecayBegin3", mSpotLightCosineDecayBegin[2]);
+ setUniform1("spotLightCosineDecayEnd3", mSpotLightCosineDecayEnd[2]);
+
+ eyeDir = camTrans.rotate(mBackLightDir); eyeDir.normalize();
+ setUniform3("parallelLightDir", eyeDir.x, eyeDir.y, eyeDir.z);
+
+ if (mShadowMaps[0] != NULL) {
+ setUniform4("far_d",
+ mShadowMaps[0]->getFarBound(0),
+ mShadowMaps[0]->getFarBound(1),
+ mShadowMaps[0]->getFarBound(2),
+ mShadowMaps[0]->getFarBound(3));
+ }
+
+ for (int i = 0; i < mNumLights; i++) {
+ if (mShadowMaps[i] != NULL)
+ mShadowMaps[i]->prepareForRender(mCamModelView, mCamProj);
+ }
+ setUniform1("shadowAmbient", shadowAmbient);
+ setUniform1("hdrScale", hdrScale);
+ setUniform3("ambientColor", ambientColor.x, ambientColor.y, ambientColor.z);
+
+ float taps[] =
+ {
+ -0.326212f, -0.40581f, -0.840144f, -0.07358f,
+ -0.695914f, 0.457137f, -0.203345f, 0.620716f,
+ 0.96234f, -0.194983f, 0.473434f, -0.480026f,
+ 0.519456f, 0.767022f, 0.185461f, -0.893124f,
+ 0.507431f, 0.064425f, 0.89642f, 0.412458f,
+ -0.32194f, -0.932615f, -0.791559f, -0.59771f
+ };
+ setUniformfv("shadowTaps", &taps[0], 2, 12);
+
+}
+
+
+// --------------------------------------------------------------------------------------------
+void ShaderShadow::deactivate()
+{
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ whiteShader->deactivate();
+ return;
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ normalShader->deactivate();
+ return;
+ }
+ Shader::deactivate();
+ if ((psMode == PS_WHITE) || (psMode == PS_NORMAL)) return;
+
+ for (int i = 0; i < mNumLights; i++) {
+ if (mShadowMaps[i] != NULL)
+ mShadowMaps[i]->doneRender();
+ }
+
+
+ //glDisableClientState(GL_VERTEX_ARRAY);
+ //glDisableClientState(GL_NORMAL_ARRAY);
+ //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glActiveTexture(GL_TEXTURE0);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glActiveTexture(GL_TEXTURE2);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glActiveTexture(GL_TEXTURE3);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glActiveTexture(GL_TEXTURE4);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glActiveTexture(GL_TEXTURE0);
+}
+
+#include <fstream>
+#include <string>
+using namespace std;
+static std::string LoadStringFromFile(const char* fname) {
+ ifstream fin(fname);
+ string line;
+ string sss = "";
+ while (getline(fin, line)) {
+ sss += line;
+ sss += "\n";
+ }
+ fin.close();
+ return sss;
+}
+
+#include <direct.h>
+#include <direct.h>
+#define GetCurrentDir _getcwd
+
+
+// --------------------------------------------------------------------------------------------
+//bool ShaderShadow::forceLoadShaderFromFile() {
+bool ShaderShadow::forceLoadShaderFromFile(VS_MODE vsMode, PS_MODE psMode, const char* vsName, const char* psName) {
+
+ const char* vsProg = 0;
+ const char* psProg = 0;
+ if (vsMode == VS_DEFAULT) vsProg = shadowDiffuseVertexProgram;
+ if (vsMode == VS_4BONES) vsProg = shadowDiffuseVertexProgram4Bones;
+ if (vsMode == VS_8BONES) vsProg = shadowDiffuseVertexProgram8Bones;
+ if (vsMode == VS_INSTANCE) vsProg = shadowDiffuseVertexProgramInstance;
+ if (vsMode == VS_TEXINSTANCE) vsProg = shadowDiffuseVertexProgramTexInstance;
+
+
+ if (psMode == PS_SHADE) psProg = shadowDiffuseFragmentProgram;
+ if (psMode == PS_SHADE3D) psProg = fragmentShader3DComposite.c_str();
+ if (psMode == PS_WHITE) psProg = whiteFragmentProgram;
+ if (psMode == PS_NORMAL) psProg = normalFragmentProgram;
+
+ std::string vsF;
+ std::string psF;
+
+ if (vsMode == VS_FILE) {
+ vsF = LoadStringFromFile(vsName);
+ vsProg = vsF.c_str();
+ }
+
+ if (psMode == PS_FILE) {
+ psF = LoadStringFromFile(psName);
+ psProg = psF.c_str();
+ }
+ if (!loadShaderCode(vsProg, psProg)) {
+ vsMode = this->vsMode;
+ psMode = this->psMode;
+
+ if (vsMode == VS_DEFAULT) vsProg = shadowDiffuseVertexProgram;
+ if (vsMode == VS_4BONES) vsProg = shadowDiffuseVertexProgram4Bones;
+ if (vsMode == VS_8BONES) vsProg = shadowDiffuseVertexProgram8Bones;
+ if (vsMode == VS_INSTANCE) vsProg = shadowDiffuseVertexProgramInstance;
+ if (vsMode == VS_TEXINSTANCE) vsProg = shadowDiffuseVertexProgramTexInstance;
+
+
+ if (psMode == PS_SHADE) psProg = shadowDiffuseFragmentProgram;
+ if (psMode == PS_SHADE3D) psProg = fragmentShader3DComposite.c_str();
+ if (psMode == PS_WHITE) psProg = whiteFragmentProgram;
+ if (psMode == PS_NORMAL) psProg = normalFragmentProgram;
+ loadShaderCode(vsProg, psProg);
+ }
+
+ /*
+ char cCurrentPath[FILENAME_MAX];
+
+ if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
+ {
+ return true;
+ }
+
+
+ std::string ps = LoadStringFromFile("kuluPS.cpp");
+ if (!loadShaderCode(shadowDiffuseVertexProgram4Bones, ps.c_str())) {
+ loadShaderCode(shadowDiffuseVertexProgram4Bones, shadowDiffuseFragmentProgram);
+ }*/
+ return true;
+}
+
+
+
+
+bool ShaderShadow::setUniform(const char* name, const PxMat33& value) {
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform(name, value);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform(name, value);
+ }
+ return Shader::setUniform(name, value);
+}
+bool ShaderShadow::setUniform(const char* name, const PxTransform& value) {
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform(name, value);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform(name, value);
+
+ }
+ return Shader::setUniform(name, value);
+}
+bool ShaderShadow::setUniform(const char *name, PxU32 size, const PxVec3* value) {
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform(name, size, value);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform(name, size, value);
+
+ }
+ return Shader::setUniform(name, size, value);
+}
+
+bool ShaderShadow::setUniform1(const char* name, float val) {
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform1(name, val);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform1(name, val);
+
+ }
+ return Shader::setUniform1(name, val);
+
+}
+bool ShaderShadow::setUniform2(const char* name, float val0, float val1){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform2(name, val0, val1);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform2(name, val0, val1);
+
+ }
+ return Shader::setUniform2(name, val0, val1);
+}
+bool ShaderShadow::setUniform3(const char* name, float val0, float val1, float val2){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform3(name, val0, val1, val2);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform3(name, val0, val1, val2);
+
+ }
+ return Shader::setUniform3(name, val0, val1, val2);
+}
+bool ShaderShadow::setUniform4(const char* name, float val0, float val1, float val2, float val3){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform4(name, val0, val1, val2, val3);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform4(name, val0, val1, val2, val3);
+
+ }
+ return Shader::setUniform4(name, val0, val1, val2, val3);
+}
+bool ShaderShadow::setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniformfv(name, v, elementSize, count);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniformfv(name, v, elementSize, count);
+
+ }
+ return Shader::setUniformfv(name, v, elementSize, count);
+}
+
+bool ShaderShadow::setUniform(const char* name, float value){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform(name, value);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform(name, value);
+
+ }
+ return Shader::setUniform(name, value);
+}
+bool ShaderShadow::setUniform(const char* name, int value){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniform(name, value);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniform(name, value);
+
+ }
+ return Shader::setUniform(name, value);
+}
+bool ShaderShadow::setUniformMatrix4fv(const GLchar *name, const GLfloat *m, bool transpose){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setUniformMatrix4fv(name, m, transpose);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setUniformMatrix4fv(name, m, transpose);
+
+ }
+ return Shader::setUniformMatrix4fv(name, m, transpose);
+}
+
+GLint ShaderShadow::getUniformCommon(const char* name){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->getUniformCommon(name);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->getUniformCommon(name);
+ }
+ return Shader::getUniformCommon(name);
+}
+
+bool ShaderShadow::setAttribute(const char* name, PxU32 size, PxU32 stride, GLenum type, void* data){
+ if ((renderMode == RENDER_DEPTH) && (psMode != PS_WHITE)) {
+ return whiteShader->setAttribute(name, size, stride, type, data);
+
+ }
+ if ((renderMode == RENDER_DEPTH_NORMAL) && (psMode != PS_NORMAL)) {
+ return normalShader->setAttribute(name, size, stride, type, data);
+
+ }
+ return Shader::setAttribute(name, size, stride, type, data);
+}
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/ShaderShadow.h b/KaplaDemo/samples/sampleViewer3/ShaderShadow.h
new file mode 100644
index 00000000..2156c0d7
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/ShaderShadow.h
@@ -0,0 +1,105 @@
+#ifndef SHADER_SHADOW_DIFFUSE_H
+#define SHADER_SHADOW_DIFFUSE_H
+
+//#define USE_OPTIX 1
+#include "Shader.h"
+#include <string>
+class ShadowMap;
+
+class ShaderShadow;
+class ShaderShadow : public Shader
+{
+public:
+ // RENDER_DEPTH is for shadow map computation
+ // RENDER_COLOR is for the usual rendering
+ // RENDER_DEPTH_NORMAL is for SSAO
+ enum RenderMode{RENDER_DEPTH, RENDER_COLOR, RENDER_DEPTH_NORMAL};
+ static RenderMode renderMode;
+ static float hdrScale;
+ static GLuint skyBoxTex;
+
+ enum VS_MODE{VS_DEFAULT, VS_4BONES, VS_8BONES, VS_INSTANCE, VS_TEXINSTANCE, VS_DEFAULT_FOR_3D_TEX, VS_FILE,VS_CROSSHAIR};
+ enum PS_MODE{PS_WHITE, PS_SHADE, PS_SHADE3D, PS_FILE, PS_NORMAL, PS_CROSSHAIR};
+ enum SHADER3D_CHOICES{SAND_STONE, WHITE_MARBLE, GRAYVEIN_MARBLE, BLUEVEIN_MARBLE, GREEN_MARBLE, GRAY_MARBLE, RED_GRANITE, YELLOW_GRANITE, WOOD, COMBINE};
+
+ ShaderShadow(VS_MODE vsMode = VS_DEFAULT, PS_MODE psMode = PS_SHADE, SHADER3D_CHOICES shade3D = GRAY_MARBLE);
+ ~ShaderShadow() {};
+
+ bool init();
+
+ void setSpotLight(int nr, const PxVec3 &pos, PxVec3 &dir, float decayBegin = 0.98f, float decayEnd = 0.997f);
+ void setBackLightDir(const PxVec3 &dir) { mBackLightDir = dir; }
+
+ void updateCamera(float* modelView, float* proj);
+
+ void setShadowMap(int nr, ShadowMap *shadowMap) { mShadowMaps[nr] = shadowMap; }
+ void setNumShadows(int num) { mNumShadows = num; }
+ void setShowReflection(bool show) { mShowReflection = show; }
+ bool getShowReflection() const {return mShowReflection;}
+
+ void setReflectionTexId(unsigned int texId) { mReflectionTexId = texId; }
+
+ virtual void activate(const ShaderMaterial &mat);
+ virtual void deactivate();
+
+ void setShadowAmbient(float sa);
+
+ // For fast shader debugging
+ bool forceLoadShaderFromFile(VS_MODE vsm, PS_MODE psm, const char* vsName = NULL, const char* psName = NULL);
+
+ SHADER3D_CHOICES getMyShade3DChoice() {return myShade3DChoice;}
+
+ PxVec3 getDustColor() { return dustColor; }
+
+ virtual bool setUniform(const char* name, const PxMat33& value);
+ virtual bool setUniform(const char* name, const PxTransform& value);
+ virtual bool setUniform(const char *name, PxU32 size, const PxVec3* value);
+
+ virtual bool setUniform1(const char* name, float val);
+ virtual bool setUniform2(const char* name, float val0, float val1);
+ virtual bool setUniform3(const char* name, float val0, float val1, float val2);
+ virtual bool setUniform4(const char* name, float val0, float val1, float val2, float val3);
+ virtual bool setUniformfv(const GLchar *name, GLfloat *v, int elementSize, int count=1);
+
+ virtual bool setUniform(const char* name, float value);
+ virtual bool setUniform(const char* name, int value);
+ virtual bool setUniformMatrix4fv(const GLchar *name, const GLfloat *m, bool transpose);
+
+ virtual GLint getUniformCommon(const char* name);
+
+ virtual bool setAttribute(const char* name, PxU32 size, PxU32 stride, GLenum type, void* data);
+
+private:
+ static const int mNumLights = 1;
+
+ ShadowMap *mShadowMaps[mNumLights];
+
+ PxVec3 mSpotLightPos[mNumLights];
+ PxVec3 mSpotLightDir[mNumLights];
+
+ float mSpotLightCosineDecayBegin[mNumLights];
+ float mSpotLightCosineDecayEnd[mNumLights];
+
+ GLuint mReflectionTexId;
+
+ PxVec3 mBackLightDir;
+ int mNumShadows;
+ bool mShowReflection;
+
+ float mCamModelView[16];
+ float mCamProj[16];
+ float shadowAmbient;
+ PxVec3 ambientColor;
+ VS_MODE vsMode;
+ PS_MODE psMode;
+
+ std::string fragmentShader3DComposite;
+ SHADER3D_CHOICES myShade3DChoice;
+ PxVec3 dustColor;
+
+ // For shadow map and SSAO
+ ShaderShadow* whiteShader;
+ ShaderShadow* normalShader;
+};
+
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp b/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp
new file mode 100644
index 00000000..cf9caea3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/ShadowMap.cpp
@@ -0,0 +1,383 @@
+//----------------------------------------------------------------------------------
+// File: ShadowMapping.cpp
+// Original Author: Rouslan Dimitrov
+// Modified by: Nuttapong Chentanez and Matthias M�ller-Fischer
+//
+// Copyright (c) 2007 NVIDIA Corporation. All rights reserved.
+//
+// TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
+// *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
+// OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
+// BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
+// WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
+// BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
+// ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
+// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+//
+//----------------------------------------------------------------------------------
+
+#include "ShadowMap.h"
+#include <GL/glew.h>
+
+//----------------------------------------------------------------------------------
+struct ShadowMap::Vec4 {
+ Vec4() {}
+ Vec4(const PxVec3 &v, float vw = 1.0f) { x = v.x; y = v.y; z = v.z; w = vw; }
+ float x,y,z,w;
+};
+
+//----------------------------------------------------------------------------------
+struct ShadowMap::Matrix44 {
+ Vec4 operator*(const Vec4& v) const {
+ Vec4 res;
+ res.x = elems[0] * v.x + elems[4] * v.y + elems[8] * v.z + elems[12] * v.w;
+ res.y = elems[1] * v.x + elems[5] * v.y + elems[9] * v.z + elems[13] * v.w;
+ res.z = elems[2] * v.x + elems[6] * v.y + elems[10] * v.z + elems[14] * v.w;
+ res.w = elems[3] * v.x + elems[7] * v.y + elems[11] * v.z + elems[15] * v.w;
+ return res;
+ }
+ float &element(int i, int j) { return elems[i + 4*j]; }
+ void zero() { for (int i = 0; i < 16; i++) elems[i] = 0.0f; }
+ void id() { zero(); elems[0] = 1.0f; elems[5] = 1.0f; elems[10] = 1.0f; elems[15] = 1.0f; }
+
+ float elems[16];
+};
+
+//----------------------------------------------------------------------------------
+ShadowMap::ShadowMap( int w, int h, float fovi, int matOffseti, int resolution)
+{
+ shadowOff = 1.0f;
+ shadowOff2 = 2048.0f;
+ fov = fovi;
+ cur_num_splits = 1;
+ //cur_num_splits = 3;
+
+ width = w;
+ height = h;
+ depth_size = resolution;
+ split_weight = 0.75;
+ matOffset = matOffseti;
+
+ minZAdd = 0;
+ maxZAdd = 30.0f;
+
+ init();
+}
+
+//----------------------------------------------------------------------------------
+void ShadowMap::updateFrustumPoints(Frustum &f, const PxVec3 &center, const PxVec3 &view_dir)
+{
+ PxVec3 up(0.0, 1.0, 0.0);
+ PxVec3 right = view_dir.cross(up);
+
+ PxVec3 fc = center + view_dir*f.fard;
+ PxVec3 nc = center + view_dir*f.neard;
+
+ right.normalize();
+ up = right.cross(view_dir);
+ up.normalize();
+
+ // these heights and widths are half the heights and widths of
+ // the near and far plane rectangles
+ float near_height = tanf(f.fov/2.0f) * f.neard;
+ float near_width = near_height * f.ratio;
+ float far_height = tanf(f.fov/2.0f) * f.fard;
+ float far_width = far_height * f.ratio;
+
+ f.point[0] = nc - up*near_height - right*near_width;
+ f.point[1] = nc + up*near_height - right*near_width;
+ f.point[2] = nc + up*near_height + right*near_width;
+ f.point[3] = nc - up*near_height + right*near_width;
+
+ f.point[4] = fc - up*far_height - right*far_width;
+ f.point[5] = fc + up*far_height - right*far_width;
+ f.point[6] = fc + up*far_height + right*far_width;
+ f.point[7] = fc - up*far_height + right*far_width;
+}
+
+//----------------------------------------------------------------------------------
+// updateSplitDist computes the near and far distances for every frustum slice
+// in camera eye space - that is, at what distance does a slice start and end
+void ShadowMap::updateSplitDist(Frustum f[MAX_SPLITS], float nd, float fd)
+{
+ float lambda = split_weight;
+ float ratio = fd/nd;
+ f[0].neard = nd;
+
+ for(int i=1; i<cur_num_splits; i++)
+ {
+ float si = i / (float)cur_num_splits;
+
+ f[i].neard = lambda*(nd*powf(ratio, si)) + (1-lambda)*(nd + (fd - nd)*si);
+ f[i-1].fard = f[i].neard * 1.005f;
+ }
+ f[cur_num_splits-1].fard = fd;
+}
+
+//----------------------------------------------------------------------------------
+// this function builds a projection matrix for rendering from the shadow's POV.
+// First, it computes the appropriate z-range and sets an orthogonal projection.
+// Then, it translates and scales it, so that it exactly captures the bounding box
+// of the current frustum slice
+float ShadowMap::applyCropMatrix(Frustum &f)
+{
+ float shad_proj[16];
+ float maxX = -1000.0;
+ float maxY = -1000.0;
+ float maxZ;
+ float minX = 1000.0;
+ float minY = 1000.0;
+ float minZ;
+
+ Matrix44 nv_mvp;
+ Vec4 transf;
+
+ // find the z-range of the current frustum as seen from the light
+ // in order to increase precision
+ glGetFloatv(GL_MODELVIEW_MATRIX, nv_mvp.elems);
+
+ // note that only the z-component is need and thus
+ // the multiplication can be simplified
+ // transf.z = shad_modelview[2] * f.point[0].x + shad_modelview[6] * f.point[0].y + shad_modelview[10] * f.point[0].z + shad_modelview[14];
+ transf = nv_mvp * Vec4(f.point[0]);
+ minZ = transf.z;
+ maxZ = transf.z;
+ for(int i=1; i<8; i++)
+ {
+ transf = nv_mvp * Vec4(f.point[i]);
+ if(transf.z > maxZ) maxZ = transf.z;
+ if(transf.z < minZ) minZ = transf.z;
+ }
+
+ minZ += minZAdd;
+ maxZ += maxZAdd;
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ // set the projection matrix with the new z-bounds
+ // note the inversion because the light looks at the neg. z axis
+ // gluPerspective(LIGHT_FOV, 1.0, maxZ, minZ); // for point lights
+ glOrtho(-1.0, 1.0, -1.0, 1.0, -maxZ, -minZ);
+ glGetFloatv(GL_PROJECTION_MATRIX, shad_proj);
+ glPushMatrix();
+ glMultMatrixf(nv_mvp.elems);
+ glGetFloatv(GL_PROJECTION_MATRIX, nv_mvp.elems);
+ glPopMatrix();
+
+ // find the extends of the frustum slice as projected in light's homogeneous coordinates
+ for(int i=0; i<8; i++)
+ {
+ transf = nv_mvp * Vec4(f.point[i]);
+
+ transf.x /= transf.w;
+ transf.y /= transf.w;
+
+ if(transf.x > maxX) maxX = transf.x;
+ if(transf.x < minX) minX = transf.x;
+ if(transf.y > maxY) maxY = transf.y;
+ if(transf.y < minY) minY = transf.y;
+ }
+
+ float scaleX = 2.0f/(maxX - minX);
+ float scaleY = 2.0f/(maxY - minY);
+ float offsetX = -0.5f*(maxX + minX)*scaleX;
+ float offsetY = -0.5f*(maxY + minY)*scaleY;
+
+ // apply a crop matrix to modify the projection matrix we got from glOrtho.
+ nv_mvp.id();
+ nv_mvp.element(0,0) = scaleX;
+ nv_mvp.element(1,1) = scaleY;
+ nv_mvp.element(0,3) = offsetX;
+ nv_mvp.element(1,3) = offsetY;
+ glLoadMatrixf(nv_mvp.elems);
+ glMultMatrixf(shad_proj);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ return minZ;
+}
+
+//----------------------------------------------------------------------------------
+// here all shadow map textures and their corresponding matrices are created
+void ShadowMap::makeShadowMap(const PxVec3 &cameraPos, const PxVec3 &cameraDir, const PxVec3 &lightDir, float znear, float zfar,
+ void (*renderShadowCasters)())
+{
+ float shad_modelview[16];
+ glDisable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ gluLookAt(
+ cameraPos.x, cameraPos.y, cameraPos.z,
+ cameraPos.x-lightDir.x, cameraPos.y-lightDir.y, cameraPos.z-lightDir.z,
+ -1.0, 0.0, 0.0);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX, shad_modelview);
+
+ // redirect rendering to the depth texture
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fb);
+ // store the screen viewport
+ glPushAttrib(GL_VIEWPORT_BIT);
+ // and render only to the shadowmap
+ glViewport(0, 0, depth_size, depth_size);
+ // offset the geometry slightly to prevent z-fighting
+ // note that this introduces some light-leakage artifacts
+ glPolygonOffset(shadowOff, shadowOff2);
+// cout<<"shadowOff = "<<shadowOff<<endl;
+// cout<<"shadowOff2 = "<<shadowOff2<<endl;
+ glEnable(GL_POLYGON_OFFSET_FILL);
+
+ // compute the z-distances for each split as seen in camera space
+ updateSplitDist(f, znear, zfar);
+
+ // for all shadow maps:
+ for(int i=0; i<cur_num_splits; i++)
+ {
+ // compute the camera frustum slice boundary points in world space
+ updateFrustumPoints(f[i], cameraPos, cameraDir);
+ // adjust the view frustum of the light, so that it encloses the camera frustum slice fully.
+ // note that this function sets the projection matrix as it sees best fit
+ // minZ is just for optimization to cull trees that do not affect the shadows
+ float minZ = applyCropMatrix(f[i]);
+ // make the current depth map a rendering target
+ glFramebufferTextureLayerEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depth_tex_ar, 0, i);
+
+ // clear the depth texture from last time
+ glClear(GL_DEPTH_BUFFER_BIT);
+
+ // draw the scene
+ (*renderShadowCasters)();
+
+ glMatrixMode(GL_PROJECTION);
+ // store the product of all shadow matries for later
+ glMultMatrixf(shad_modelview);
+ glGetFloatv(GL_PROJECTION_MATRIX, shad_cpm[i]);
+ }
+
+ glDisable(GL_POLYGON_OFFSET_FILL);
+ glPopAttrib();
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ glEnable(GL_TEXTURE_2D);
+
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+}
+
+//----------------------------------------------------------------------------------
+void ShadowMap::cameraInverse(float dst[16], float src[16])
+{
+ dst[0] = src[0];
+ dst[1] = src[4];
+ dst[2] = src[8];
+ dst[3] = 0.0;
+ dst[4] = src[1];
+ dst[5] = src[5];
+ dst[6] = src[9];
+ dst[7] = 0.0;
+ dst[8] = src[2];
+ dst[9] = src[6];
+ dst[10] = src[10];
+ dst[11] = 0.0;
+ dst[12] = -(src[12] * src[0]) - (src[13] * src[1]) - (src[14] * src[2]);
+ dst[13] = -(src[12] * src[4]) - (src[13] * src[5]) - (src[14] * src[6]);
+ dst[14] = -(src[12] * src[8]) - (src[13] * src[9]) - (src[14] * src[10]);
+ dst[15] = 1.0;
+}
+
+//----------------------------------------------------------------------------------
+void ShadowMap::doneRender()
+{
+ // Unbind texture
+ for (int i = 0; i < 8; i++) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ }
+ glActiveTexture(GL_TEXTURE0);
+}
+
+//----------------------------------------------------------------------------------
+void ShadowMap::prepareForRender(float* cam_modelview, float* cam_proj)
+{
+ float cam_inverse_modelview[16];
+ const float bias[16] = { 0.5, 0.0, 0.0, 0.0,
+ 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0,
+ 0.5, 0.5f, 0.5, 1.0 };
+
+ // update the camera, so that the user can have a free look
+ cameraInverse(cam_inverse_modelview, cam_modelview);
+
+ glActiveTexture(GL_TEXTURE0);
+
+ for(int i=cur_num_splits; i<MAX_SPLITS; i++)
+ far_bound[i] = 0;
+
+ // for every active split
+ for(int i=0; i<cur_num_splits; i++)
+ {
+ // f[i].fard is originally in eye space - tell's us how far we can see.
+ // Here we compute it in camera homogeneous coordinates. Basically, we calculate
+ // cam_proj * (0, 0, f[i].fard, 1)^t and then normalize to [0; 1]
+ far_bound[i] = 0.5f*(-f[i].fard*cam_proj[10]+cam_proj[14])/f[i].fard + 0.5f;
+
+ // compute a matrix that transforms from camera eye space to light clip space
+ // and pass it to the shader through the OpenGL texture matrices, since we
+ // don't use them now
+ glActiveTexture(GL_TEXTURE0 + (GLenum)i + matOffset);
+ glMatrixMode(GL_TEXTURE);
+ glLoadMatrixf(bias);
+ glMultMatrixf(shad_cpm[i]);
+ // multiply the light's (bias*crop*proj*modelview) by the inverse camera modelview
+ // so that we can transform a pixel as seen from the camera
+ glMultMatrixf(cam_inverse_modelview);
+ }
+
+ glActiveTexture(GL_TEXTURE0);
+}
+
+//----------------------------------------------------------------------------------
+void ShadowMap::init()
+{
+ //glClearColor(0.8f, 0.8f , 0.9f, 1.0);
+ //glEnable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+
+
+ glGenFramebuffersEXT(1, &depth_fb);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, depth_fb);
+ glDrawBuffer(GL_NONE);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ glGenTextures(1, &depth_tex_ar);
+
+ glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, depth_tex_ar);
+ glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_DEPTH_COMPONENT32, depth_size, depth_size, MAX_SPLITS, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+
+ for(int i=0; i<MAX_SPLITS; i++)
+ {
+ // note that fov is in radians here and in OpenGL it is in degrees.
+ // the 0.2f factor is important because we might get artifacts at
+ // the screen borders.
+ f[i].fov = fov/57.2957795f + 0.2f;
+ f[i].ratio = (float)width/(float)height;
+ }
+
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/ShadowMap.h b/KaplaDemo/samples/sampleViewer3/ShadowMap.h
new file mode 100644
index 00000000..63407270
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/ShadowMap.h
@@ -0,0 +1,95 @@
+//----------------------------------------------------------------------------------
+// File: ShadowMapping.cpp
+// Original Author: Rouslan Dimitrov
+// Modified by: Nuttapong Chentanez and Matthias M�ller-Fischer
+//
+// Copyright (c) 2007 NVIDIA Corporation. All rights reserved.
+//
+// TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED
+// *AS IS* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS
+// OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS
+// BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES
+// WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
+// BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS)
+// ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS
+// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+//
+//----------------------------------------------------------------------------------
+
+
+#ifndef SHADOWMAP_H
+#define SHADOWMAP_H
+
+#include "foundation/PxVec3.h"
+#include <GL/glew.h>
+
+using namespace physx;
+
+#define FAR_DIST 200.0
+#define MAX_SPLITS 1
+#define LIGHT_FOV 45.0
+
+//--------------------------------------------------------------------------
+class ShadowMap
+{
+public:
+ ShadowMap( int w, int h, float fovi, int matOffseti, int resolution = 4096);
+
+ void makeShadowMap(const PxVec3 &cameraPos, const PxVec3 &cameraDir, const PxVec3 &lightDir, float znear, float zfar,
+ void (*renderShadowCasters)());
+
+ // call before the map is used for rendering
+ void prepareForRender(float* cam_modelview, float* cam_proj);
+ // call when rendering is done
+ void doneRender();
+
+ int getTextureSize() { return depth_size; }
+ GLuint getDepthTexArray() { return depth_tex_ar; }
+ float getFarBound(int i) { return far_bound[i]; }
+ int getNumSplits() { return cur_num_splits; }
+
+private:
+ struct Frustum {
+ float neard;
+ float fard;
+ float fov;
+ float ratio;
+ PxVec3 point[8];
+ };
+
+ struct Vec4;
+ struct Matrix44;
+
+ void updateFrustumPoints(Frustum &f, const PxVec3 &center, const PxVec3 &view_dir);
+ void updateSplitDist(Frustum f[MAX_SPLITS], float nd, float fd);
+ float applyCropMatrix(Frustum &f);
+
+ void cameraInverse(float dst[16], float src[16]);
+ void init();
+
+ float far_bound[MAX_SPLITS];
+
+ float minZAdd;
+ float maxZAdd;
+
+ float shadowOff;
+ float shadowOff2;
+ float fov;
+
+ int cur_num_splits;
+ int width;
+ int height;
+ int depth_size ;
+
+ GLuint depth_fb;
+ GLuint depth_tex_ar;
+
+ Frustum f[MAX_SPLITS];
+ float shad_cpm[MAX_SPLITS][16];
+
+ float split_weight;
+ int matOffset;
+};
+#endif \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp b/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp
new file mode 100644
index 00000000..e35dd319
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TerrainMesh.cpp
@@ -0,0 +1,367 @@
+#include <algorithm>
+#include "TerrainMesh.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+#include "PxScene.h"
+#include "Shader.h"
+#include "geometry/PxHeightFieldSample.h"
+#include "geometry/PxHeightFieldDesc.h"
+#include "geometry/PxHeightFieldGeometry.h"
+#include "PxRigidStatic.h"
+#include "Texture.h"
+#include "TerrainMesh.h"
+
+#include "PhysXMacros.h"
+#include "SceneVehicleSceneQuery.h"
+#include "VehicleManager.h"
+#include "PxDefaultStreams.h"
+
+#define USE_HEIGHTFIELD 1
+
+
+TerrainMesh::~TerrainMesh() {
+ //myScene->removeActor(*hfActor);
+ hfActor->release();
+ if (mMesh) delete mMesh;
+}
+
+TerrainMesh::TerrainMesh(PxPhysics& physics, PxCooking& cooking, PxScene& scene, PxMaterial& material, PxVec3 midPoint, const char* heightMapName, const char* textureName, float hfScale, float maxHeight, Shader* shader,
+ bool invert) {
+ mShader = shader;
+ mMesh = 0;
+ myScene = &scene;
+ BmpLoaderBuffer heightMapFile;
+ if (!heightMapFile.loadFile(heightMapName)) {
+ fprintf(stderr, "Error loading bmp '%s'\n");
+ return;
+ }
+
+ const PxReal heightScale = 0.005f;
+ //const PxReal heightScale = 0.01f;
+
+ unsigned int hfWidth = heightMapFile.mWidth;
+ unsigned int hfHeight = heightMapFile.mHeight;
+ unsigned char* heightmap = heightMapFile.mRGB;
+ const double i255 = 1.0/255.0;
+
+ PxTransform pose = PX_TRANSFORM_ID;
+ pose.p = midPoint + PxVec3(-((hfWidth - 1)*0.5f*hfScale), 0, -((hfHeight - 1)*0.5f*hfScale));
+ mHFPose = pose;
+
+
+ PxU32 hfNumVerts = hfWidth*hfHeight;
+
+ PxHeightFieldSample* samples = new PxHeightFieldSample[hfNumVerts];
+ memset(samples,0,hfNumVerts*sizeof(PxHeightFieldSample));
+
+
+ PxFilterData simulationFilterData;
+ simulationFilterData.word0 = COLLISION_FLAG_GROUND;
+ simulationFilterData.word1 = COLLISION_FLAG_GROUND_AGAINST;
+ PxFilterData queryFilterData;
+ VehicleSetupDrivableShapeQueryFilterData(&queryFilterData);
+ static PxI32 maxH = -2000000;
+ static PxI32 minH = 20000000;
+ for(PxU32 y = 0; y < hfHeight; y++)
+ {
+ for(PxU32 x = 0; x < hfWidth; x++)
+ {
+
+ PxU8 heightVal = heightmap[(y + x*hfWidth) * 3];
+ if (invert)
+ heightVal = 255 - heightVal;
+ PxI32 h = PxI32((maxHeight*heightVal*i255) / heightScale);
+ //Do a snap-to-grid...
+
+ h = ((h >> 4) << 4);
+
+ maxH = PxMax(h, maxH);
+ minH = PxMin(h, minH);
+
+ //h = h & (~0x7f);
+
+ //printf("%d ", h);
+ PX_ASSERT(h<=0xffff);
+
+ const PxU32 Index = x + y*hfWidth;
+ samples[Index].height = (PxI16)(h);
+ samples[Index].materialIndex0 = 0;
+ samples[Index].materialIndex1 = 0;
+ samples[Index].clearTessFlag();
+ }
+ }
+
+
+
+
+
+ // texture
+ if (strcmp(textureName, "") == 0) hfTexture = 0; else
+ hfTexture = loadImgTexture(textureName);
+ mMesh = new GLMesh(GL_TRIANGLES);
+ mMesh->vertices.resize(hfNumVerts);
+ mMesh->normals.resize(hfNumVerts);
+ mMesh->texCoords.resize(hfNumVerts*2);
+ mMesh->indices.clear();
+ float us = 1.0f / hfWidth;
+ float vs = 1.0f / hfHeight;
+ terrainHeights.clear();
+ terrainNormals.clear();
+ for (int i = 0; i < hfHeight; i++)
+ {
+ for (int j = 0; j < hfWidth; j++)
+ {
+ PxReal height = PxReal(samples[i + j*hfWidth].height) * heightScale;
+
+ mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, height, hfScale*i) + pose.p;
+ terrainHeights.push_back(mMesh->vertices[i*hfWidth+j].y);
+ mMesh->texCoords[(i*hfWidth + j)*2] = j*us;
+ mMesh->texCoords[(i*hfWidth + j)*2+1] = i*vs;
+ }
+ }
+
+ xStart = pose.p.x;
+ zStart = pose.p.z;
+ dx = hfScale;
+
+ for (int i = 0; i < hfHeight-1; i++) {
+ for (int j = 0; j < hfWidth-1; j++) {
+ //mMesh->vertices[i*hfWidth + j] = PxVec3(hfScale*j, maxHeight*heightmap[(j+i*hfWidth)*3]*i255, hfScale*i);
+
+
+ mMesh->indices.push_back(j + i*hfWidth);
+ mMesh->indices.push_back(j + (i + 1)*hfWidth);
+ mMesh->indices.push_back((j + 1) + i*hfWidth);
+
+ mMesh->indices.push_back((j + 1) + i*hfWidth);
+ mMesh->indices.push_back(j + (i + 1)*hfWidth);
+ mMesh->indices.push_back((j + 1) + (i + 1)*hfWidth);
+
+ }
+ }
+ mMesh->normals.resize(hfNumVerts);
+ for (int i = 0; i < hfNumVerts; i++) {
+ mMesh->normals[i] = PxVec3(0.0f, 0.0f, 0.0f);
+ }
+
+ int numTris = mMesh->indices.size() / 3;
+ for (int i = 0; i < numTris; i++) {
+ int i0 = mMesh->indices[i*3];
+ int i1 = mMesh->indices[i*3+1];
+ int i2 = mMesh->indices[i*3+2];
+ PxVec3 p0 = mMesh->vertices[i0];
+ PxVec3 p1 = mMesh->vertices[i1];
+ PxVec3 p2 = mMesh->vertices[i2];
+
+ PxVec3 normal = (p1-p0).cross(p2-p0);
+ mMesh->normals[i0] += normal;
+ mMesh->normals[i1] += normal;
+ mMesh->normals[i2] += normal;
+ }
+ for (int i = 0; i < hfNumVerts; i++) {
+ mMesh->normals[i].normalize();
+ }
+ mMesh->genVBOIBO();
+ mMesh->updateVBOIBO(false);
+ mMaterial.init();
+ mMaterial.texId = hfTexture;
+
+ terrainNormals = mMesh->normals;
+
+ width = hfWidth;
+ height = hfHeight;
+ idx = 1.0f/dx;
+
+
+#if USE_HEIGHTFIELD
+
+ PxHeightFieldDesc hfDesc;
+ //hfDesc.format = PxHeightFieldFormat::eS16_TM;
+ hfDesc.nbColumns = hfWidth;
+ hfDesc.nbRows = hfHeight;
+ hfDesc.samples.data = samples;
+ hfDesc.samples.stride = sizeof(PxHeightFieldSample);
+
+ PxHeightField* heightField = cooking.createHeightField(hfDesc, physics.getPhysicsInsertionCallback());
+
+
+
+ hfActor = physics.createRigidStatic(pose);
+
+ PxHeightFieldGeometry hfGeom(heightField, PxMeshGeometryFlags(), heightScale, hfScale, hfScale);
+ PxShape* hfShape = hfActor->createShape(hfGeom, material);
+
+ hfShape->setQueryFilterData(queryFilterData);
+ hfShape->setSimulationFilterData(simulationFilterData);
+
+ scene.addActor(*hfActor);
+
+ delete[] samples;
+#else
+ PxTriangleMeshDesc meshDesc;
+
+ meshDesc.points.data = &mMesh->vertices[0];
+ meshDesc.points.count = mMesh->vertices.size();
+ meshDesc.points.stride = sizeof(PxVec3);
+
+ meshDesc.triangles.stride = sizeof(PxU32)*3;
+ meshDesc.triangles.count = mMesh->indices.size()/3;
+ meshDesc.triangles.data = &mMesh->indices[0];
+
+ meshDesc.flags = PxMeshFlags();
+
+ PxTriangleMeshGeometry geom;
+
+ PxCookingParams params = cooking.getParams();
+ params.buildGRBData = true;
+
+ cooking.setParams(params);
+
+ PxDefaultMemoryOutputStream writeBuffer;
+ bool status = cooking.cookTriangleMesh(meshDesc, writeBuffer);
+ PX_ASSERT(status);
+ PxDefaultMemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize());
+ PxTriangleMesh* triangleMesh = physics.createTriangleMesh(readBuffer);
+
+ geom.triangleMesh = triangleMesh;
+
+ hfActor = physics.createRigidStatic(PxTransform(PxIdentity));
+
+ PxShape* meshShape = hfActor->createShape(geom, material);
+
+ meshShape->setQueryFilterData(queryFilterData);
+ meshShape->setSimulationFilterData(simulationFilterData);
+
+ scene.addActor(*hfActor);
+
+
+#endif
+
+
+}
+
+void TerrainMesh::draw(bool useShader) {
+ if (useShader) mShader->activate(mMaterial);
+ mMesh->drawVBOIBO();
+ if (useShader) mShader->deactivate();
+}
+
+
+float TerrainMesh::getHeight(float x, float z) {
+
+ float nx = (x-xStart)*idx;
+ float nz = (z-zStart)*idx;
+
+ int ix = floor(nx);
+ int iz = floor(nz);
+ float fx = nx-ix;
+ float fz = nz-iz;
+
+ int ixp1 = ix+1;
+ int izp1 = iz+1;
+ ix = min(max(ix,0), width-1);
+ iz = min(max(iz,0), height-1);
+ ixp1 = min(max(ixp1,0), width-1);
+ izp1 = min(max(izp1,0), height-1);
+
+ int i00 = ix+iz*width;
+ int i10 = ixp1+iz*width;
+ int i01 = ix+izp1*width;
+ int i11 = ixp1+izp1*width;
+
+ float w00 = (1.0f-fx)*(1.0f-fz);
+ float w10 = (fx)*(1.0f-fz);
+ float w01 = (1.0f-fx)*(fz);
+ float w11 = (fx)*(fz);
+
+ return w00*terrainHeights[i00] +
+ w10*terrainHeights[i10] +
+ w01*terrainHeights[i01] +
+ w11*terrainHeights[i11];
+}
+
+
+float TerrainMesh::getHeightNormal(float x, float z, PxVec3& normal) {
+
+ float nx = (x-xStart)*idx;
+ float nz = (z-zStart)*idx;
+
+ int ix = floor(nx);
+ int iz = floor(nz);
+ float fx = nx-ix;
+ float fz = nz-iz;
+
+ int ixp1 = ix+1;
+ int izp1 = iz+1;
+ ix = min(max(ix,0), width-1);
+ iz = min(max(iz,0), height-1);
+ ixp1 = min(max(ixp1,0), width-1);
+ izp1 = min(max(izp1,0), height-1);
+
+ int i00 = ix+iz*width;
+ int i10 = ixp1+iz*width;
+ int i01 = ix+izp1*width;
+ int i11 = ixp1+izp1*width;
+
+ float w00 = (1.0f-fx)*(1.0f-fz);
+ float w10 = (fx)*(1.0f-fz);
+ float w01 = (1.0f-fx)*(fz);
+ float w11 = (fx)*(fz);
+
+ normal = w00*terrainNormals[i00] +
+ w10*terrainNormals[i10] +
+ w01*terrainNormals[i01] +
+ w11*terrainNormals[i11];
+ normal.normalize();
+
+ return w00*terrainHeights[i00] +
+ w10*terrainHeights[i10] +
+ w01*terrainHeights[i01] +
+ w11*terrainHeights[i11];
+
+}
+
+
+float TerrainMesh::getHeightNormalCondition(float x, float y, float z, PxVec3& normal) {
+
+ float nx = (x-xStart)*idx;
+ float nz = (z-zStart)*idx;
+
+ int ix = floor(nx);
+ int iz = floor(nz);
+ float fx = nx-ix;
+ float fz = nz-iz;
+
+ int ixp1 = ix+1;
+ int izp1 = iz+1;
+ ix = min(max(ix,0), width-1);
+ iz = min(max(iz,0), height-1);
+ ixp1 = min(max(ixp1,0), width-1);
+ izp1 = min(max(izp1,0), height-1);
+
+ int i00 = ix+iz*width;
+ int i10 = ixp1+iz*width;
+ int i01 = ix+izp1*width;
+ int i11 = ixp1+izp1*width;
+
+ float w00 = (1.0f-fx)*(1.0f-fz);
+ float w10 = (fx)*(1.0f-fz);
+ float w01 = (1.0f-fx)*(fz);
+ float w11 = (fx)*(fz);
+
+ float h = w00*terrainHeights[i00] +
+ w10*terrainHeights[i10] +
+ w01*terrainHeights[i01] +
+ w11*terrainHeights[i11];
+
+ if (h <= y) {
+ normal = w00*terrainNormals[i00] +
+ w10*terrainNormals[i10] +
+ w01*terrainNormals[i01] +
+ w11*terrainNormals[i11];
+ normal.normalize();
+
+ }
+
+ return h;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/TerrainMesh.h b/KaplaDemo/samples/sampleViewer3/TerrainMesh.h
new file mode 100644
index 00000000..bb5245e7
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TerrainMesh.h
@@ -0,0 +1,40 @@
+
+#pragma once
+
+#include "BmpFile.h"
+#include "glmesh.h"
+#include "Shader.h"
+#include "PxCooking.h"
+#include <vector>
+using namespace std;
+class TerrainMesh{
+public:
+ // Able to render mesh
+ // Able to generate physX
+ PxRigidStatic* hfActor;
+ PxTransform mHFPose;
+ GLuint hfTexture;
+ GLMesh* mMesh;
+ PxScene* myScene;
+ Shader* mShader;
+ ShaderMaterial mMaterial;
+
+ ~TerrainMesh();
+ TerrainMesh(PxPhysics& physics, PxCooking& cooking, PxScene& scene, PxMaterial& material, PxVec3 midPoint, const char* heightMapName, const char* textureName,
+ float hfScale, float maxHeight, Shader* shader, bool invert = false);
+ void draw(bool useShader);
+
+
+ float xStart;
+ float zStart;
+ float dx, idx;
+ vector<float> terrainHeights;
+ vector<PxVec3> terrainNormals;
+
+ int width;
+ int height;
+ float getHeight(float x, float z);
+ float getHeightNormal(float x, float z, PxVec3& normal);
+ float getHeightNormalCondition(float x, float y, float z, PxVec3& normal);
+};
+
diff --git a/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.cpp b/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.cpp
new file mode 100644
index 00000000..76973a0b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.cpp
@@ -0,0 +1,92 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "TerrainRandomSamplePrecompute.h"
+#include "SceneVehicle.h"
+#include "PxTkStream.h"
+#include "MediaPath.h"
+
+using namespace PxToolkit;
+
+#define WRITE_SEQUENCE 0
+
+PX_FORCE_INLINE PxF32 flip(const PxF32* v)
+{
+ const PxU8* b = (const PxU8*)v;
+ PxF32 f;
+ PxU8* bf = (PxU8*)&f;
+ bf[0] = b[3];
+ bf[1] = b[2];
+ bf[2] = b[1];
+ bf[3] = b[0];
+ return f;
+}
+
+TerrainRandomSamplePrecompute::TerrainRandomSamplePrecompute(SceneVehicle& app, const char* resourcePath)
+ : mPrecomputedRandomSequence(NULL),
+ mPrecomputedRandomSequenceCount(0)
+{
+ mPrecomputedRandomSequence = new PxF32[(sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE + 1))];
+
+#if WRITE_SEQUENCE
+ char buffer[256];
+ const char* filename = getSampleOutputDirManager().getFilePath("SampleBaseRandomSequence", buffer, false);
+ const PxF32 denom = (1.0f / float(RAND_MAX));
+ for (PxU32 i = 0; i<PRECOMPUTED_RANDOM_SEQUENCE_SIZE; i++)
+ {
+ mPrecomputedRandomSequence[i] = float(rand()) * denom;
+ }
+ mPrecomputedRandomSequence[PRECOMPUTED_RANDOM_SEQUENCE_SIZE] = 1.0f;
+ PxDefaultFileOutputStream stream(filename);
+ stream.write(mPrecomputedRandomSequence, sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE + 1));
+
+#else
+ const char* filename = FindMediaFile("SampleBaseRandomSequence", resourcePath);
+ PxDefaultFileInputData stream(filename);
+ if (!stream.isValid())
+ printf("SampleBaseRandomSequence file not found");
+ stream.read(mPrecomputedRandomSequence, sizeof(PxF32)*(PRECOMPUTED_RANDOM_SEQUENCE_SIZE + 1));
+
+ const bool mismatch = (1.0f != mPrecomputedRandomSequence[PRECOMPUTED_RANDOM_SEQUENCE_SIZE]);
+ if (mismatch)
+ {
+ for (PxU32 i = 0; i<PRECOMPUTED_RANDOM_SEQUENCE_SIZE; i++)
+ {
+ mPrecomputedRandomSequence[i] = flip(&mPrecomputedRandomSequence[i]);
+ }
+ }
+
+#endif
+}
+
+TerrainRandomSamplePrecompute::~TerrainRandomSamplePrecompute()
+{
+ delete[] mPrecomputedRandomSequence;
+ mPrecomputedRandomSequenceCount = 0;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.h b/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.h
new file mode 100644
index 00000000..615d82ab
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TerrainRandomSamplePrecompute.h
@@ -0,0 +1,64 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H
+#define TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H
+
+#include "common/PxPhysXCommonConfig.h"
+#include "foundation/PxAssert.h"
+
+using namespace physx;
+
+class SceneVehicle;
+
+class TerrainRandomSamplePrecompute
+{
+public:
+
+ TerrainRandomSamplePrecompute(SceneVehicle& app, const char* resourcePath);
+ ~TerrainRandomSamplePrecompute();
+
+ PxF32 getRandom() const { return mPrecomputedRandomSequence[(mPrecomputedRandomSequenceCount++) % PRECOMPUTED_RANDOM_SEQUENCE_SIZE]; }
+ PxF32 getRandomInRange(const PxF32 a, const PxF32 b)
+ {
+ PX_ASSERT(b>a);
+ return a + (b - a)*getRandom();
+ }
+
+private:
+
+ enum
+ {
+ PRECOMPUTED_RANDOM_SEQUENCE_SIZE = 65536
+ };
+ PxF32* mPrecomputedRandomSequence;
+ mutable PxU32 mPrecomputedRandomSequenceCount;
+};
+
+#endif //TERRAIN_RANDOM_SAMPLE_PRECOMPUTED_H
diff --git a/KaplaDemo/samples/sampleViewer3/Texture.cpp b/KaplaDemo/samples/sampleViewer3/Texture.cpp
new file mode 100644
index 00000000..9f99e439
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Texture.cpp
@@ -0,0 +1,283 @@
+#include <stdio.h>
+#include <string.h>
+#include <GL/glew.h>
+#include "BmpFile.h"
+#include <iostream>
+#include "IJGWin32/CPPJPEGWrapper.h"
+#include "TgaFile.h"
+using namespace std;
+// standard cubemap face names
+/*
+const char *faceName[6] = {
+ "negz",
+ "negz",
+ "posy",
+ "negy",
+ "negz",
+ "negz",
+};
+*/
+const char *faceName0[6] = {
+ "posx",
+ "negx",
+ "posy",
+ "negy",
+ "posz",
+ "negz",
+};
+const char *faceName1[6] = {
+ "ft",
+ "bk",
+ "up",
+ "dn",
+ "rt",
+ "lf",
+};
+
+
+void loadImg(GLenum target, const char *filename, char mode = 0, float sr = 0.0f, float sg = 0.0f, float sb = 0.0f, float startGrad = -1.0f, float endGrad = -1.0f, char dir = 1)
+{
+ int len = strlen(filename);
+
+ unsigned char* ptr = 0, *ptrBegin;
+ int w, h;
+
+ BmpLoaderBuffer loader;
+ CPPJPEGWrapper jpg;
+ TGAFILE tgafile;
+ tga_image* image = new tga_image();
+
+ if (strcmp(&filename[len-4], ".jpg") == 0)
+ {
+ // jpg
+ if (!jpg.LoadJPEG(filename, false)) {
+ printf("Error load jpg %s\n", filename);
+ return;
+ }
+ h = jpg.GetHeight();
+ w = jpg.GetWidth();
+ ptrBegin = ptr = jpg.GetData();
+ }
+ else if (strcmp(&filename[len-4], ".bmp") == 0)
+ {
+ // bmp
+ if (!loader.loadFile(filename)) {
+ fprintf(stderr, "Error loading bmp '%s'\n");
+ return;
+ }
+ ptrBegin = ptr = loader.mRGB;
+ h = loader.mHeight;
+ w = loader.mWidth;
+
+ }
+ else
+ {
+ //tga
+
+ FILE *file = fopen(filename, "rb");
+ if (file == NULL)
+ {
+ fprintf(stderr, "Error loading tga '%s'\n");
+ return;
+ }
+ bool ok = (TGA_NOERR == tga_read_from_FILE(image, file));
+
+ //// flip it to make it look correct in the SampleFramework's renderer
+ //tga_flip_vert(image);
+
+ if (!ok)
+ {
+ fprintf(stderr, "Error loading tga '%s'\n");
+ return;
+ }
+
+ /*if (!LoadTGAFile(filename, &tgafile))
+ {
+ fprintf(stderr, "Error loading tga '%s'\n");
+ return;
+ }*/
+
+ ptrBegin = ptr = image->image_data;
+ h = image->height;
+ w = image->width;
+
+ fclose(file);
+
+ }
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ if (mode == 0) {
+ // Nothing
+ }
+ float rf = sr*255.0f;
+ float gf = sg*255.0f;
+ float bf = sb*255.0f;
+ unsigned char r = (unsigned char)(rf+0.5f);
+ unsigned char g = (unsigned char)(gf+0.5f);
+ unsigned char b = (unsigned char)(bf+0.5f);
+
+
+ if (mode == 1) {
+ // Fill all with sky color
+ //printf("Mode is 1\n");
+
+ for (int i = 0; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ *(ptr++) = r;
+ *(ptr++) = g;
+ *(ptr++) = b;
+ }
+ }
+ }
+ if (mode == 2) {
+ // Fill with gradient
+ int sh = startGrad*h + 0.5f;
+ int eh = endGrad*h + 0.5f;
+ if (dir == 1) {
+ for (int i = 0; i < sh; i++) {
+ for (int j = 0; j < w; j++) {
+ *(ptr++) = r;
+ *(ptr++) = g;
+ *(ptr++) = b;
+ }
+ }
+ float grad = 1.0f/(eh - sh);
+ float frac = 0.0f;
+ for (int i = sh; i < eh; i++) {
+ for (int j = 0; j < w; j++) {
+ ptr[0] = (unsigned char)(0.5f + ptr[0]*frac + (1.0f-frac)*rf);
+ ptr[1] = (unsigned char)(0.5f + ptr[1]*frac + (1.0f-frac)*gf);
+ ptr[2] = (unsigned char)(0.5f + ptr[2]*frac + (1.0f-frac)*bf);
+ ptr+=3;
+ }
+ frac+=grad;
+ }
+ } else {
+ ptr+=(w*3*sh);
+ float grad = 1.0f/(eh - sh);
+ float frac = 1.0f;
+ for (int i = sh; i < eh; i++) {
+ for (int j = 0; j < w; j++) {
+ ptr[0] = (unsigned char)(0.5f + ptr[0]*frac + (1.0f-frac)*rf);
+ ptr[1] = (unsigned char)(0.5f + ptr[1]*frac + (1.0f-frac)*gf);
+ ptr[2] = (unsigned char)(0.5f + ptr[2]*frac + (1.0f-frac)*bf);
+ ptr+=3;
+ }
+ frac-=grad;
+ }
+ for (int i = eh; i < h; i++) {
+ for (int j = 0; j < w; j++) {
+ *(ptr++) = r;
+ *(ptr++) = g;
+ *(ptr++) = b;
+ }
+ }
+ }
+ }
+ /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glTexImage2D(target, 0, GL_RGBA8, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, ptrBegin);
+
+ /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ //glGenerateMipmapEXT(target);
+ /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+
+ tga_free_buffers(image);
+ delete image;
+}
+
+GLuint loadImgTexture(const char *filename)
+{
+ GLuint texID;
+ glGenTextures(1, &texID);
+ glBindTexture(GL_TEXTURE_2D, texID);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+ loadImg(GL_TEXTURE_2D, filename);
+
+ return texID;
+}
+
+
+// specify filename in printf format, e.g. "cubemap_%s.png"
+GLuint loadCubeMap(const char *string, char mode, char nameset, float sr, float sg, float sb, float startGrad, float endGrad, char dir)
+{
+ GLuint texID;
+ glGenTextures(1, &texID);
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texID);
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ // load faces
+ if (mode <= 1) {
+ for(int i=0; i<6; i++) {
+ char buff[1024];
+ if (nameset == 0) {
+ sprintf(buff, string, faceName0[i]);
+ } else {
+ sprintf(buff, string, faceName1[i]);
+ }
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, mode, sr, sg, sb, startGrad, endGrad, dir);
+
+
+ }
+ } /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ if (mode == 2) {
+ for(int i=0; i<6; i++) {
+ char buff[1024];
+ if (nameset == 0) {
+ sprintf(buff, string, faceName0[i]);
+ } else {
+ sprintf(buff, string, faceName1[i]);
+ }
+ if (i == 2) {
+ if (dir == -1) {
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, 0);
+ } else {
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, 1, sr, sg, sb);
+ }
+ } else
+ if (i == 3) {
+ if (dir == -1) {
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, 1, sr, sg, sb);
+ } else {
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, 0);
+ }
+ } else {
+ loadImg(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + i, buff, mode, sr, sg, sb, startGrad, endGrad, dir);
+ }
+ }
+ }
+/*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ glGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP);
+ /*{GLenum er = glGetError(); if (er != GL_NO_ERROR) { cout<<"Var name: "<<name<<" OGL Error "<<er<<endl; }}*/
+ return texID;
+}
+
+
+GLuint createTexture(GLenum target, GLint internalformat, int w, int h, GLenum type, GLenum format, void *data)
+{
+ GLuint texid;
+ glGenTextures(1, &texid);
+ glBindTexture(target, texid);
+
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glTexImage2D(target, 0, internalformat, w, h, 0, format, type, data);
+
+ return texid;
+}
diff --git a/KaplaDemo/samples/sampleViewer3/Texture.h b/KaplaDemo/samples/sampleViewer3/Texture.h
new file mode 100644
index 00000000..8fd7e959
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Texture.h
@@ -0,0 +1,13 @@
+#ifndef TEXTURE_H
+#define TEXTURE_H
+
+GLuint loadImgTexture(const char *filename);
+GLuint loadCubeMap(const char *string, char mode = 0, char nameset = 0, float sr = 0.0f, float sg = 0.0f, float sb = 0.0f, float startGrad = -1.0f, float endGrad = -1.0f, char dir = 1);
+GLuint createTexture(GLenum target, GLint internalformat, int w, int h, GLenum type, GLenum format, void *data);
+
+#endif // !TEXTURE_H
+
+
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/TgaFile.cpp b/KaplaDemo/samples/sampleViewer3/TgaFile.cpp
new file mode 100644
index 00000000..f085230b
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TgaFile.cpp
@@ -0,0 +1,1212 @@
+/* ---------------------------------------------------------------------------
+* Truevision Targa Reader/Writer
+* Copyright (C) 2001-2003, Emil Mikulic.
+*
+* Source and binary redistribution of this code, with or without changes, for
+* free or for profit, is allowed as long as this copyright notice is kept
+* intact. Modified versions must be clearly marked as modified.
+*
+* This code is provided without any warranty. The copyright holder is
+* not liable for anything bad that might happen as a result of the
+* code.
+*
+*
+* This version modified by NVIDIA Corporation to prevent compilation on
+* platforms other than Windows.
+* -------------------------------------------------------------------------*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef __GNUC__
+#define UNUSED_VAR __attribute__((unused))
+#else
+#define UNUSED_VAR
+#endif
+
+/*@unused@*/// static const char rcsid[] UNUSED_VAR =
+// "$Id: targa.c,v 1.7 2003/06/21 09:30:53 emikulic Exp $";
+
+#define TGA_KEEP_MACROS /* BIT, htole16, letoh16 */
+
+#include "TgaFile.h"
+
+#define SANE_DEPTH(x) ((x) == 8 || (x) == 16 || (x) == 24 || (x) == 32)
+#define UNMAP_DEPTH(x) ((x) == 16 || (x) == 24 || (x) == 32)
+
+#ifdef _MSC_VER
+#pragma warning(disable:4244)
+#if _MSC_VER >= 1800
+#pragma warning(disable:4388)
+#endif
+#endif
+
+static const char tga_id[] =
+"\0\0\0\0" /* extension area offset */
+"\0\0\0\0" /* developer directory offset */
+"TRUEVISION-XFILE.";
+
+static const size_t tga_id_length = 26; /* tga_id + \0 */
+
+//Some platfroms do not define fopen_s
+#if !defined( __STDC_WANT_SECURE_LIB__ ) && !defined(__ORBIS__)
+static int fopen_s(FILE ** stream, const char * filename, const char * mode)
+{
+ FILE* fp = fopen(filename, mode);
+ return fp ? *stream = fp, 0 : -1;
+}
+#endif
+
+#define TGA_FOPEN_S(fops, stream, filename, mode) (fops ? fops->m_fopen_s(stream, filename, mode) : fopen_s(reinterpret_cast<FILE**>(stream), filename, mode))
+#define TGA_FREAD(fops, ptr, size, count, stream) (fops ? fops->m_fread(ptr, size, count, stream) : fread(ptr, size, count, reinterpret_cast<FILE*>(stream)))
+#define TGA_FWRITE(fops, ptr, size, count, stream) (fops ? fops->m_fwrite(ptr, size ,count, stream) : fwrite(ptr, size, count, reinterpret_cast<FILE*>(stream)))
+#define TGA_FEOF(fops, stream) (fops ? fops->m_feof(stream) : feof(reinterpret_cast<FILE*>(stream)))
+#define TGA_FCLOSE(fops, stream) (fops ? fops->m_fclose(stream) : fclose(reinterpret_cast<FILE*>(stream)))
+
+/* helpers */
+static tga_result tga_read_rle(tga_image *dest, TGA_FP *fp, tgaFileOperations* fops);
+static tga_result tga_write_row_RLE(TGA_FP *fp,
+ const tga_image *src, const uint8_t *row, tgaFileOperations* fops);
+typedef enum { RAW, RLE } packet_type;
+static packet_type rle_packet_type(const uint8_t *row, const uint16_t pos,
+ const uint16_t width, const uint16_t bpp);
+static uint8_t rle_packet_len(const uint8_t *row, const uint16_t pos,
+ const uint16_t width, const uint16_t bpp, const packet_type type);
+
+uint8_t tga_get_attribute_bits(const tga_image *tga)
+{
+ return tga->image_descriptor & TGA_ATTRIB_BITS;
+}
+
+int tga_is_right_to_left(const tga_image *tga)
+{
+ return (tga->image_descriptor & TGA_R_TO_L_BIT) != 0;
+}
+
+int tga_is_top_to_bottom(const tga_image *tga)
+{
+ return (tga->image_descriptor & TGA_T_TO_B_BIT) != 0;
+}
+
+int tga_is_colormapped(const tga_image *tga)
+{
+ return (
+ tga->image_type == TGA_IMAGE_TYPE_COLORMAP ||
+ tga->image_type == TGA_IMAGE_TYPE_COLORMAP_RLE
+ );
+}
+
+int tga_is_rle(const tga_image *tga)
+{
+ return (
+ tga->image_type == TGA_IMAGE_TYPE_COLORMAP_RLE ||
+ tga->image_type == TGA_IMAGE_TYPE_BGR_RLE ||
+ tga->image_type == TGA_IMAGE_TYPE_MONO_RLE
+ );
+}
+
+int tga_is_mono(const tga_image *tga)
+{
+ return (
+ tga->image_type == TGA_IMAGE_TYPE_MONO ||
+ tga->image_type == TGA_IMAGE_TYPE_MONO_RLE
+ );
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Convert the numerical <errcode> into a verbose error string.
+*
+* Returns: an error string
+*/
+const char *tga_error(const tga_result errcode)
+{
+ switch (errcode)
+ {
+ case TGA_NOERR:
+ return "no error";
+ case TGAERR_FOPEN:
+ return "error opening file";
+ case TGAERR_EOF:
+ return "premature end of file";
+ case TGAERR_WRITE:
+ return "error writing to file";
+ case TGAERR_CMAP_TYPE:
+ return "invalid color map type";
+ case TGAERR_IMG_TYPE:
+ return "invalid image type";
+ case TGAERR_NO_IMG:
+ return "no image data included";
+ case TGAERR_CMAP_MISSING:
+ return "color-mapped image without color map";
+ case TGAERR_CMAP_PRESENT:
+ return "non-color-mapped image with extraneous color map";
+ case TGAERR_CMAP_LENGTH:
+ return "color map has zero length";
+ case TGAERR_CMAP_DEPTH:
+ return "invalid color map depth";
+ case TGAERR_ZERO_SIZE:
+ return "the image dimensions are zero";
+ case TGAERR_PIXEL_DEPTH:
+ return "invalid pixel depth";
+ case TGAERR_NO_MEM:
+ return "out of memory";
+ case TGAERR_NOT_CMAP:
+ return "image is not color mapped";
+ case TGAERR_RLE:
+ return "RLE data is corrupt";
+ case TGAERR_INDEX_RANGE:
+ return "color map index out of range";
+ case TGAERR_MONO:
+ return "image is mono";
+ default:
+ return "unknown error code";
+ }
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Read a Targa image from a file named <filename> to <dest>. This is just a
+* wrapper around tga_read_from_FILE().
+*
+* Returns: TGA_NOERR on success, or a matching TGAERR_* code on failure.
+*/
+tga_result tga_read(tga_image *dest, const char *filename, tgaFileOperations* fops)
+{
+ tga_result result;
+
+ TGA_FP *fp = NULL;
+ if (0 != TGA_FOPEN_S(fops, &fp, filename, "rb")) return TGAERR_FOPEN;
+ result = tga_read_from_FILE(dest, fp, fops);
+ TGA_FCLOSE(fops, fp);
+ return result;
+}
+
+/* ---------------------------------------------------------------------------
+* Read a Targa image from <fp> to <dest>.
+*
+* Returns: TGA_NOERR on success, or a TGAERR_* code on failure. In the
+* case of failure, the contents of dest are not guaranteed to be
+* valid.
+*/
+tga_result tga_read_from_FILE(tga_image *dest, TGA_FP *fp, tgaFileOperations* fops)
+{
+#define BARF(errcode) \
+ { tga_free_buffers(dest); return errcode; }
+
+#define READ(destptr, size) \
+ if (TGA_FREAD(fops, destptr, 1, size, fp) != size) BARF(TGAERR_EOF)
+
+#define READ16(dest) \
+ { if (TGA_FREAD(fops, &(dest), 1, 2, fp) != 2) BARF(TGAERR_EOF); \
+ dest = letoh16(dest); }
+
+ dest->image_id = NULL;
+ dest->color_map_data = NULL;
+ dest->image_data = NULL;
+
+ READ(&dest->image_id_length, 1);
+ READ(&dest->color_map_type, 1);
+ if (dest->color_map_type != TGA_COLOR_MAP_ABSENT &&
+ dest->color_map_type != TGA_COLOR_MAP_PRESENT)
+ BARF(TGAERR_CMAP_TYPE);
+
+ READ(&dest->image_type, 1);
+ if (dest->image_type == TGA_IMAGE_TYPE_NONE)
+ BARF(TGAERR_NO_IMG);
+
+ if (dest->image_type != TGA_IMAGE_TYPE_COLORMAP &&
+ dest->image_type != TGA_IMAGE_TYPE_BGR &&
+ dest->image_type != TGA_IMAGE_TYPE_MONO &&
+ dest->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
+ dest->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
+ dest->image_type != TGA_IMAGE_TYPE_MONO_RLE)
+ BARF(TGAERR_IMG_TYPE);
+
+ if (tga_is_colormapped(dest) &&
+ dest->color_map_type == TGA_COLOR_MAP_ABSENT)
+ BARF(TGAERR_CMAP_MISSING);
+
+ if (!tga_is_colormapped(dest) &&
+ dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+ BARF(TGAERR_CMAP_PRESENT);
+
+ READ16(dest->color_map_origin);
+ READ16(dest->color_map_length);
+ READ(&dest->color_map_depth, 1);
+ if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ if (dest->color_map_length == 0)
+ BARF(TGAERR_CMAP_LENGTH);
+
+ if (!UNMAP_DEPTH(dest->color_map_depth))
+ BARF(TGAERR_CMAP_DEPTH);
+ }
+
+ READ16(dest->origin_x);
+ READ16(dest->origin_y);
+ READ16(dest->width);
+ READ16(dest->height);
+
+ if (dest->width == 0 || dest->height == 0)
+ BARF(TGAERR_ZERO_SIZE);
+
+ READ(&dest->pixel_depth, 1);
+ if (!SANE_DEPTH(dest->pixel_depth) ||
+ (dest->pixel_depth != 8 && tga_is_colormapped(dest)))
+ BARF(TGAERR_PIXEL_DEPTH);
+
+ READ(&dest->image_descriptor, 1);
+
+ if (dest->image_id_length > 0)
+ {
+ dest->image_id = reinterpret_cast<uint8_t*>(malloc(dest->image_id_length));
+ if (dest->image_id == NULL) BARF(TGAERR_NO_MEM);
+ READ(dest->image_id, dest->image_id_length);
+ }
+
+ if (dest->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ dest->color_map_data = reinterpret_cast<uint8_t*>(malloc(
+ (dest->color_map_origin + dest->color_map_length) *
+ dest->color_map_depth / 8));
+ if (dest->color_map_data == NULL) BARF(TGAERR_NO_MEM);
+ READ(dest->color_map_data +
+ (dest->color_map_origin * dest->color_map_depth / 8),
+ dest->color_map_length * dest->color_map_depth / 8);
+ }
+
+ dest->image_data = reinterpret_cast<uint8_t*>(malloc(
+ dest->width * dest->height * dest->pixel_depth / 8));
+ if (dest->image_data == NULL)
+ BARF(TGAERR_NO_MEM);
+
+ if (tga_is_rle(dest))
+ {
+ /* read RLE */
+ tga_result result = tga_read_rle(dest, fp, fops);
+ if (result != TGA_NOERR) BARF(result);
+ }
+ else
+ {
+ /* uncompressed */
+ READ(dest->image_data,
+ size_t(dest->width * dest->height * dest->pixel_depth / 8));
+ }
+
+ return TGA_NOERR;
+#undef BARF
+#undef READ
+#undef READ16
+}
+
+static tga_result tga_read_rle(tga_image *dest, TGA_FP *fp, tgaFileOperations* fops)
+{
+#define RLE_BIT BIT(7)
+#define READ(dest, size) \
+ if (TGA_FREAD(fops, dest, 1, size, fp) != size) return TGAERR_EOF
+
+ uint8_t *pos;
+ uint32_t p_loaded = 0,
+ p_expected = dest->width * dest->height;
+ uint8_t bpp = dest->pixel_depth / 8; /* bytes per pixel */
+
+ pos = dest->image_data;
+
+ while ((p_loaded < p_expected) && !TGA_FEOF(fops, fp))
+ {
+ uint8_t b;
+ READ(&b, 1);
+ if (b & RLE_BIT)
+ {
+ /* is an RLE packet */
+ uint8_t count, tmp[4], i;
+
+ count = (b & ~RLE_BIT) + 1;
+ READ(tmp, bpp);
+
+ for (i = 0; i<count; i++)
+ {
+ p_loaded++;
+ if (p_loaded > p_expected) return TGAERR_RLE;
+ memcpy(pos, tmp, bpp);
+ pos += bpp;
+ }
+ }
+ else /* RAW packet */
+ {
+ uint8_t count;
+
+ count = (b & ~RLE_BIT) + 1;
+ if (p_loaded + count > p_expected) return TGAERR_RLE;
+
+ p_loaded += count;
+ READ(pos, bpp*count);
+ pos += count * bpp;
+ }
+ }
+ return TGA_NOERR;
+#undef RLE_BIT
+#undef READ
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Write a Targa image to a file named <filename> from <src>. This is just a
+* wrapper around tga_write_to_FILE().
+*
+* Returns: TGA_NOERR on success, or a matching TGAERR_* code on failure.
+*/
+tga_result tga_write(const char *filename, const tga_image *src, tgaFileOperations* fops)
+{
+ tga_result result;
+ TGA_FP *fp = NULL;
+ if (0 != TGA_FOPEN_S(fops, &fp, filename, "rb")) return TGAERR_FOPEN;
+
+ result = tga_write_to_FILE(fp, src, fops);
+ TGA_FCLOSE(fops, fp);
+ return result;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Write one row of an image to <fp> using RLE. This is a helper function
+* called from tga_write_to_FILE(). It assumes that <src> has its header
+* fields set up correctly.
+*/
+#define PIXEL(ofs) ( row + (ofs)*bpp )
+static tga_result tga_write_row_RLE(TGA_FP *fp,
+ const tga_image *src, const uint8_t *row, tgaFileOperations* fops)
+{
+#define WRITE(src, size) \
+ if (TGA_FWRITE(fops, src, 1, size, fp) != size) return TGAERR_WRITE
+
+ uint16_t pos = 0;
+ uint16_t bpp = src->pixel_depth / 8;
+
+ while (pos < src->width)
+ {
+ packet_type type = rle_packet_type(row, pos, src->width, bpp);
+ uint8_t len = rle_packet_len(row, pos, src->width, bpp, type);
+ uint8_t packet_header;
+
+ packet_header = len - 1;
+ if (type == RLE) packet_header |= BIT(7);
+
+ WRITE(&packet_header, 1);
+ if (type == RLE)
+ {
+ WRITE(PIXEL(pos), bpp);
+ }
+ else /* type == RAW */
+ {
+ WRITE(PIXEL(pos), bpp*len);
+ }
+
+ pos += len;
+ }
+
+ return TGA_NOERR;
+#undef WRITE
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Determine whether the next packet should be RAW or RLE for maximum
+* efficiency. This is a helper function called from rle_packet_len() and
+* tga_write_row_RLE().
+*/
+#define SAME(ofs1, ofs2) (memcmp(PIXEL(ofs1), PIXEL(ofs2), bpp) == 0)
+
+static packet_type rle_packet_type(const uint8_t *row, const uint16_t pos,
+ const uint16_t width, const uint16_t bpp)
+{
+ if (pos == width - 1) return RAW; /* one pixel */
+ if (SAME(pos, pos + 1)) /* dupe pixel */
+ {
+ if (bpp > 1) return RLE; /* inefficient for bpp=1 */
+
+ /* three repeats makes the bpp=1 case efficient enough */
+ if ((pos < width - 2) && SAME(pos + 1, pos + 2)) return RLE;
+ }
+ return RAW;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Find the length of the current RLE packet. This is a helper function
+* called from tga_write_row_RLE().
+*/
+static uint8_t rle_packet_len(const uint8_t *row, const uint16_t pos,
+ const uint16_t width, const uint16_t bpp, const packet_type type)
+{
+ uint8_t len = 2;
+
+ if (pos == width - 1) return 1;
+ if (pos == width - 2) return 2;
+
+ if (type == RLE)
+ {
+ while (pos + len < width)
+ {
+ if (SAME(pos, pos + len))
+ len++;
+ else
+ return len;
+
+ if (len == 128) return 128;
+ }
+ }
+ else /* type == RAW */
+ {
+ while (pos + len < width)
+ {
+ if (rle_packet_type(row, pos + len, width, bpp) == RAW)
+ len++;
+ else
+ return len;
+ if (len == 128) return 128;
+ }
+ }
+ return len; /* hit end of row (width) */
+}
+#undef SAME
+#undef PIXEL
+
+
+
+/* ---------------------------------------------------------------------------
+* Writes a Targa image to <fp> from <src>.
+*
+* Returns: TGA_NOERR on success, or a TGAERR_* code on failure.
+* On failure, the contents of the file are not guaranteed
+* to be valid.
+*/
+tga_result tga_write_to_FILE(TGA_FP *fp, const tga_image *src, tgaFileOperations* fops)
+{
+#define WRITE(srcptr, size) \
+ if (TGA_FWRITE(fops, srcptr, 1, size, fp) != size) return TGAERR_WRITE
+
+#define WRITE16(src) \
+ { uint16_t _temp = htole16(src); \
+ if (TGA_FWRITE(fops, &_temp, 1, 2, fp) != 2) return TGAERR_WRITE; }
+
+ WRITE(&src->image_id_length, 1);
+
+ if (src->color_map_type != TGA_COLOR_MAP_ABSENT &&
+ src->color_map_type != TGA_COLOR_MAP_PRESENT)
+ return TGAERR_CMAP_TYPE;
+ WRITE(&src->color_map_type, 1);
+
+ if (src->image_type == TGA_IMAGE_TYPE_NONE)
+ return TGAERR_NO_IMG;
+ if (src->image_type != TGA_IMAGE_TYPE_COLORMAP &&
+ src->image_type != TGA_IMAGE_TYPE_BGR &&
+ src->image_type != TGA_IMAGE_TYPE_MONO &&
+ src->image_type != TGA_IMAGE_TYPE_COLORMAP_RLE &&
+ src->image_type != TGA_IMAGE_TYPE_BGR_RLE &&
+ src->image_type != TGA_IMAGE_TYPE_MONO_RLE)
+ return TGAERR_IMG_TYPE;
+ WRITE(&src->image_type, 1);
+
+ if (tga_is_colormapped(src) &&
+ src->color_map_type == TGA_COLOR_MAP_ABSENT)
+ return TGAERR_CMAP_MISSING;
+ if (!tga_is_colormapped(src) &&
+ src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ return TGAERR_CMAP_PRESENT;
+ if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ {
+ if (src->color_map_length == 0)
+ return TGAERR_CMAP_LENGTH;
+
+ if (!UNMAP_DEPTH(src->color_map_depth))
+ return TGAERR_CMAP_DEPTH;
+ }
+ WRITE16(src->color_map_origin);
+ WRITE16(src->color_map_length);
+ WRITE(&src->color_map_depth, 1);
+
+ WRITE16(src->origin_x);
+ WRITE16(src->origin_y);
+
+ if (src->width == 0 || src->height == 0)
+ return TGAERR_ZERO_SIZE;
+ WRITE16(src->width);
+ WRITE16(src->height);
+
+ if (!SANE_DEPTH(src->pixel_depth) ||
+ (src->pixel_depth != 8 && tga_is_colormapped(src)))
+ return TGAERR_PIXEL_DEPTH;
+ WRITE(&src->pixel_depth, 1);
+
+ WRITE(&src->image_descriptor, 1);
+
+ if (src->image_id_length > 0)
+ WRITE(&src->image_id, src->image_id_length);
+
+ if (src->color_map_type == TGA_COLOR_MAP_PRESENT)
+ WRITE(src->color_map_data +
+ (src->color_map_origin * src->color_map_depth / 8),
+ src->color_map_length * src->color_map_depth / 8);
+
+ if (tga_is_rle(src))
+ {
+ uint16_t row;
+ for (row = 0; row<src->height; row++)
+ {
+ tga_result result = tga_write_row_RLE(fp, src,
+ src->image_data + row*src->width*src->pixel_depth / 8, fops);
+ if (result != TGA_NOERR) return result;
+ }
+ }
+ else
+ {
+ /* uncompressed */
+ WRITE(src->image_data,
+ size_t(src->width * src->height * src->pixel_depth / 8));
+ }
+
+ WRITE(tga_id, tga_id_length);
+
+ return TGA_NOERR;
+#undef WRITE
+#undef WRITE16
+}
+
+
+
+/* Convenient writing functions --------------------------------------------*/
+
+/*
+* This is just a helper function to initialise the header fields in a
+* tga_image struct.
+*/
+static void init_tga_image(tga_image *img, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth)
+{
+ img->image_id_length = 0;
+ img->color_map_type = TGA_COLOR_MAP_ABSENT;
+ img->image_type = TGA_IMAGE_TYPE_NONE; /* override this below! */
+ img->color_map_origin = 0;
+ img->color_map_length = 0;
+ img->color_map_depth = 0;
+ img->origin_x = 0;
+ img->origin_y = 0;
+ img->width = width;
+ img->height = height;
+ img->pixel_depth = depth;
+ img->image_descriptor = TGA_T_TO_B_BIT;
+ img->image_id = NULL;
+ img->color_map_data = NULL;
+ img->image_data = image;
+}
+
+
+
+tga_result tga_write_mono(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, 8);
+ img.image_type = TGA_IMAGE_TYPE_MONO;
+ return tga_write(filename, &img, fops);
+}
+
+
+
+tga_result tga_write_mono_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, 8);
+ img.image_type = TGA_IMAGE_TYPE_MONO_RLE;
+ return tga_write(filename, &img, fops);
+}
+
+
+
+tga_result tga_write_bgr(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, depth);
+ img.image_type = TGA_IMAGE_TYPE_BGR;
+ return tga_write(filename, &img, fops);
+}
+
+
+
+tga_result tga_write_bgr_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, depth);
+ img.image_type = TGA_IMAGE_TYPE_BGR_RLE;
+ return tga_write(filename, &img, fops);
+}
+
+
+
+/* Note: this function will MODIFY <image> */
+tga_result tga_write_rgb(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, depth);
+ img.image_type = TGA_IMAGE_TYPE_BGR;
+ (void)tga_swap_red_blue(&img);
+ return tga_write(filename, &img, fops);
+}
+
+
+
+/* Note: this function will MODIFY <image> */
+tga_result tga_write_rgb_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth, tgaFileOperations* fops)
+{
+ tga_image img;
+ init_tga_image(&img, image, width, height, depth);
+ img.image_type = TGA_IMAGE_TYPE_BGR_RLE;
+ (void)tga_swap_red_blue(&img);
+ return tga_write(filename, &img, fops);
+}
+
+
+
+/* Convenient manipulation functions ---------------------------------------*/
+
+/* ---------------------------------------------------------------------------
+* Horizontally flip the image in place. Reverses the right-to-left bit in
+* the image descriptor.
+*/
+tga_result tga_flip_horiz(tga_image *img)
+{
+ uint16_t row;
+ size_t bpp;
+ uint8_t *left, *right;
+ int r_to_l;
+
+ if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+ bpp = size_t(img->pixel_depth / 8); /* bytes per pixel */
+
+ for (row = 0; row<img->height; row++)
+ {
+ left = img->image_data + row * img->width * bpp;
+ right = left + (img->width - 1) * bpp;
+
+ /* reverse from left to right */
+ while (left < right)
+ {
+ uint8_t buffer[4];
+
+ /* swap */
+ memcpy(buffer, left, bpp);
+ memcpy(left, right, bpp);
+ memcpy(right, buffer, bpp);
+
+ left += bpp;
+ right -= bpp;
+ }
+ }
+
+ /* Correct image_descriptor's left-to-right-ness. */
+ r_to_l = tga_is_right_to_left(img);
+ img->image_descriptor &= ~TGA_R_TO_L_BIT; /* mask out r-to-l bit */
+ if (!r_to_l)
+ /* was l-to-r, need to set r_to_l */
+ img->image_descriptor |= TGA_R_TO_L_BIT;
+ /* else bit is already rubbed out */
+
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Vertically flip the image in place. Reverses the top-to-bottom bit in
+* the image descriptor.
+*/
+tga_result tga_flip_vert(tga_image *img)
+{
+ uint16_t col;
+ uint16_t row;
+ size_t bpp, line;
+ uint8_t *top, *bottom;
+ int t_to_b;
+
+ if (!SANE_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+ bpp = size_t(img->pixel_depth / 8); /* bytes per pixel */
+ line = bpp * img->width; /* bytes per line */
+
+ for (col = 0; col < img->width; col++)
+ {
+ for (row = 0; row < img->height; row++)
+ {
+ uint8_t* pixel = &img->image_data[(col*img->height + row)*bpp];
+ uint8_t tmp = pixel[0];
+ pixel[0] = pixel[2];
+ pixel[2] = tmp;
+ }
+ }
+
+ for (col = 0; col<img->width; col++)
+ {
+ top = img->image_data + col * bpp;
+ bottom = top + (img->height - 1) * line;
+
+ /* reverse from top to bottom */
+ while (top < bottom)
+ {
+ uint8_t buffer[4];
+
+ /* swap */
+ memcpy(buffer, top, bpp);
+ memcpy(top, bottom, bpp);
+ memcpy(bottom, buffer, bpp);
+
+ top += line;
+ bottom -= line;
+ }
+ }
+
+ /* Correct image_descriptor's top-to-bottom-ness. */
+ t_to_b = tga_is_top_to_bottom(img);
+ img->image_descriptor &= ~TGA_T_TO_B_BIT; /* mask out t-to-b bit */
+ if (!t_to_b)
+ /* was b-to-t, need to set t_to_b */
+ img->image_descriptor |= TGA_T_TO_B_BIT;
+ /* else bit is already rubbed out */
+
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Convert a color-mapped image to unmapped BGR. Reallocates image_data to a
+* bigger size, then converts the image backwards to avoid using a secondary
+* buffer. Alters the necessary header fields and deallocates the color map.
+*/
+tga_result tga_color_unmap(tga_image *img)
+{
+ uint8_t bpp = img->color_map_depth / 8; /* bytes per pixel */
+ int pos;
+ void *tmp;
+
+ if (!tga_is_colormapped(img)) return TGAERR_NOT_CMAP;
+ if (img->pixel_depth != 8) return TGAERR_PIXEL_DEPTH;
+ if (!SANE_DEPTH(img->color_map_depth)) return TGAERR_CMAP_DEPTH;
+
+ tmp = realloc(img->image_data, img->width * img->height * bpp);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = reinterpret_cast<uint8_t*>(tmp);
+
+ for (pos = img->width * img->height - 1; pos >= 0; pos--)
+ {
+ uint8_t c_index = img->image_data[pos];
+ uint8_t *c_bgr = img->color_map_data + (c_index * bpp);
+
+ if (c_index >= img->color_map_origin + img->color_map_length)
+ return TGAERR_INDEX_RANGE;
+
+ memcpy(img->image_data + (pos*bpp), c_bgr, size_t(bpp));
+ }
+
+ /* clean up */
+ img->image_type = TGA_IMAGE_TYPE_BGR;
+ img->pixel_depth = img->color_map_depth;
+
+ free(img->color_map_data);
+ img->color_map_data = NULL;
+ img->color_map_type = TGA_COLOR_MAP_ABSENT;
+ img->color_map_origin = 0;
+ img->color_map_length = 0;
+ img->color_map_depth = 0;
+
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Return a pointer to a given pixel. Accounts for image orientation (T_TO_B,
+* R_TO_L, etc). Returns NULL if the pixel is out of range.
+*/
+uint8_t *tga_find_pixel(const tga_image *img, uint16_t x, uint16_t y)
+{
+ if (x >= img->width || y >= img->height)
+ return NULL;
+
+ if (!tga_is_top_to_bottom(img)) y = img->height - 1 - y;
+ if (tga_is_right_to_left(img)) x = img->width - 1 - x;
+ return img->image_data + (x + y * img->width) * img->pixel_depth / 8;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Unpack the pixel at the src pointer according to bits. Any of b,g,r,a can
+* be set to NULL if not wanted. Returns TGAERR_PIXEL_DEPTH if a bad
+* number of bits is given.
+*/
+tga_result tga_unpack_pixel(const uint8_t *src, const uint8_t bits,
+ uint8_t *b, uint8_t *g, uint8_t *r, uint8_t *a)
+{
+ switch (bits)
+ {
+ case 32:
+ if (b) *b = src[0];
+ if (g) *g = src[1];
+ if (r) *r = src[2];
+ if (a) *a = src[3];
+ break;
+
+ case 24:
+ if (b) *b = src[0];
+ if (g) *g = src[1];
+ if (r) *r = src[2];
+ if (a) *a = 0;
+ break;
+
+ case 16:
+ {
+ uint16_t src16 = uint16_t(src[1] << 8) | uint16_t(src[0]);
+
+#define FIVE_BITS (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4))
+ if (b) *b = uint8_t(((src16)& FIVE_BITS) << 3);
+ if (g) *g = uint8_t(((src16 >> 5) & FIVE_BITS) << 3);
+ if (r) *r = uint8_t(((src16 >> 10) & FIVE_BITS) << 3);
+ if (a) *a = uint8_t((src16 & BIT(15)) ? 255 : 0);
+#undef FIVE_BITS
+ break;
+ }
+
+ case 8:
+ if (b) *b = *src;
+ if (g) *g = *src;
+ if (r) *r = *src;
+ if (a) *a = 0;
+ break;
+
+ default:
+ return TGAERR_PIXEL_DEPTH;
+ }
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Pack the pixel at the dest pointer according to bits. Returns
+* TGAERR_PIXEL_DEPTH if a bad number of bits is given.
+*/
+tga_result tga_pack_pixel(uint8_t *dest, const uint8_t bits,
+ const uint8_t b, const uint8_t g, const uint8_t r, const uint8_t a)
+{
+ switch (bits)
+ {
+ case 32:
+ dest[0] = b;
+ dest[1] = g;
+ dest[2] = r;
+ dest[3] = a;
+ break;
+
+ case 24:
+ dest[0] = b;
+ dest[1] = g;
+ dest[2] = r;
+ break;
+
+ case 16:
+ {
+ uint16_t tmp;
+
+#define FIVE_BITS (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4))
+ tmp = uint16_t((b >> 3) & FIVE_BITS);
+ tmp |= ((g >> 3) & FIVE_BITS) << 5;
+ tmp |= ((r >> 3) & FIVE_BITS) << 10;
+ if (a > 127) tmp |= BIT(15);
+#undef FIVE_BITS
+
+ dest[0] = uint8_t(tmp & 0x00FF);
+ dest[1] = uint8_t((tmp & 0xFF00) >> 8);
+ break;
+ }
+
+ default:
+ return TGAERR_PIXEL_DEPTH;
+ }
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Desaturate the specified Targa using the specified coefficients:
+* output = ( red * cr + green * cg + blue * cb ) / dv
+*/
+tga_result tga_desaturate(tga_image *img, const int cr, const int cg,
+ const int cb, const int dv)
+{
+ uint8_t bpp = img->pixel_depth / 8; /* bytes per pixel */
+ uint8_t *dest, *src, *tmp;
+
+ if (tga_is_mono(img)) return TGAERR_MONO;
+ if (tga_is_colormapped(img))
+ {
+ tga_result result = tga_color_unmap(img);
+ if (result != TGA_NOERR) return result;
+ }
+ if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+
+ dest = img->image_data;
+ for (src = img->image_data;
+ src < img->image_data + img->width*img->height*bpp;
+ src += bpp)
+ {
+ uint8_t b = 0, g = 0, r = 0;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &b, &g, &r, NULL);
+
+ *dest = uint8_t((int(b) * cb +
+ int(g) * cg +
+ int(r) * cr) / dv);
+ dest++;
+ }
+
+ /* shrink */
+ tmp = reinterpret_cast<uint8_t*>(realloc(img->image_data, img->width * img->height));
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = reinterpret_cast<uint8_t*>(tmp);
+
+ img->pixel_depth = 8;
+ img->image_type = TGA_IMAGE_TYPE_MONO;
+ return TGA_NOERR;
+}
+
+tga_result tga_desaturate_rec_601_1(tga_image *img)
+{
+ return tga_desaturate(img, 2989, 5866, 1145, 10000);
+}
+
+tga_result tga_desaturate_rec_709(tga_image *img)
+{
+ return tga_desaturate(img, 2126, 7152, 722, 10000);
+}
+
+tga_result tga_desaturate_itu(tga_image *img)
+{
+ return tga_desaturate(img, 2220, 7067, 713, 10000);
+}
+
+tga_result tga_desaturate_avg(tga_image *img)
+{
+ return tga_desaturate(img, 1, 1, 1, 3);
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Convert an image to the given pixel depth. (one of 32, 24, 16) Avoids
+* using a secondary buffer to do the conversion.
+*/
+tga_result tga_convert_depth(tga_image *img, const uint8_t bits)
+{
+ size_t src_size, dest_size;
+ uint8_t src_bpp, dest_bpp;
+ uint8_t *src, *dest;
+
+ if (!UNMAP_DEPTH(bits) ||
+ !SANE_DEPTH(img->pixel_depth)
+ ) return TGAERR_PIXEL_DEPTH;
+
+ if (tga_is_colormapped(img))
+ {
+ tga_result result = tga_color_unmap(img);
+ if (result != TGA_NOERR) return result;
+ }
+
+ if (img->pixel_depth == bits) return TGA_NOERR; /* no op, no err */
+
+ src_bpp = img->pixel_depth / 8;
+ dest_bpp = bits / 8;
+
+ src_size = size_t(img->width * img->height * src_bpp);
+ dest_size = size_t(img->width * img->height * dest_bpp);
+
+ if (src_size > dest_size)
+ {
+ void *tmp;
+
+ /* convert forwards */
+ dest = img->image_data;
+ for (src = img->image_data;
+ src < img->image_data + img->width * img->height * src_bpp;
+ src += src_bpp)
+ {
+ uint8_t r = 0, g = 0, b = 0, a = 0;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
+ (void)tga_pack_pixel(dest, bits, r, g, b, a);
+ dest += dest_bpp;
+ }
+
+ /* shrink */
+ tmp = realloc(img->image_data, img->width * img->height * dest_bpp);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = reinterpret_cast<uint8_t*>(tmp);
+ }
+ else
+ {
+ /* expand */
+ void *tmp = realloc(img->image_data,
+ img->width * img->height * dest_bpp);
+ if (tmp == NULL) return TGAERR_NO_MEM;
+ img->image_data = reinterpret_cast<uint8_t*>(tmp);
+
+ /* convert backwards */
+ dest = img->image_data + (img->width*img->height - 1) * dest_bpp;
+ for (src = img->image_data + (img->width*img->height - 1) * src_bpp;
+ src >= img->image_data;
+ src -= src_bpp)
+ {
+ uint8_t r = 0, g = 0, b = 0, a = 0;
+ (void)tga_unpack_pixel(src, img->pixel_depth, &r, &g, &b, &a);
+ (void)tga_pack_pixel(dest, bits, r, g, b, a);
+ dest -= dest_bpp;
+ }
+ }
+
+ img->pixel_depth = bits;
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Swap red and blue (RGB becomes BGR and vice verse). (in-place)
+*/
+tga_result tga_swap_red_blue(tga_image *img)
+{
+ uint8_t *ptr;
+ uint8_t bpp = img->pixel_depth / 8;
+
+ if (!UNMAP_DEPTH(img->pixel_depth)) return TGAERR_PIXEL_DEPTH;
+
+ for (ptr = img->image_data;
+ ptr < img->image_data + (img->width * img->height - 1) * bpp;
+ ptr += bpp)
+ {
+ uint8_t r = 0, g = 0, b = 0, a = 0;
+ (void)tga_unpack_pixel(ptr, img->pixel_depth, &b, &g, &r, &a);
+ (void)tga_pack_pixel(ptr, img->pixel_depth, r, g, b, a);
+ }
+ return TGA_NOERR;
+}
+
+
+
+/* ---------------------------------------------------------------------------
+* Free the image_id, color_map_data and image_data buffers of the specified
+* tga_image, if they're not already NULL.
+*/
+void tga_free_buffers(tga_image *img)
+{
+ if (img->image_id != NULL)
+ {
+ free(img->image_id);
+ img->image_id = NULL;
+ }
+ if (img->color_map_data != NULL)
+ {
+ free(img->color_map_data);
+ img->color_map_data = NULL;
+ }
+ if (img->image_data != NULL)
+ {
+ free(img->image_data);
+ img->image_data = NULL;
+ }
+}
+
+
+/* vim:set tabstop=4 shiftwidth=4 textwidth=78 expandtab: */
+
+
+bool LoadTGAFile(const char *filename, TGAFILE *tgaFile)
+{
+ FILE *filePtr;
+ unsigned char ucharBad;
+ short int sintBad;
+ long imageSize;
+ int colorMode;
+ unsigned char colorSwap;
+
+ // Open the TGA file.
+ filePtr = fopen(filename, "rb");
+ if (filePtr == NULL)
+ {
+ return false;
+ }
+
+ // Read the two first bytes we don't need.
+ fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
+ fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
+
+ // Which type of image gets stored in imageTypeCode.
+ fread(&tgaFile->imageTypeCode, sizeof(unsigned char), 1, filePtr);
+
+ // For our purposes, the type code should be 2 (uncompressed RGB image)
+ // or 3 (uncompressed black-and-white images).
+ if (tgaFile->imageTypeCode != 2 && tgaFile->imageTypeCode != 3)
+ {
+ fclose(filePtr);
+ return false;
+ }
+
+ // Read 13 bytes of data we don't need.
+ fread(&sintBad, sizeof(short int), 1, filePtr);
+ fread(&sintBad, sizeof(short int), 1, filePtr);
+ fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
+ fread(&sintBad, sizeof(short int), 1, filePtr);
+ fread(&sintBad, sizeof(short int), 1, filePtr);
+
+ // Read the image's width and height.
+ fread(&tgaFile->imageWidth, sizeof(short int), 1, filePtr);
+ fread(&tgaFile->imageHeight, sizeof(short int), 1, filePtr);
+
+ // Read the bit depth.
+ fread(&tgaFile->bitCount, sizeof(unsigned char), 1, filePtr);
+
+ // Read one byte of data we don't need.
+ fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
+
+ // Color mode -> 3 = BGR, 4 = BGRA.
+ colorMode = tgaFile->bitCount / 8;
+ imageSize = tgaFile->imageWidth * tgaFile->imageHeight * colorMode;
+
+ // Allocate memory for the image data.
+ tgaFile->imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
+
+ // Read the image data.
+ fread(tgaFile->imageData, sizeof(unsigned char), imageSize, filePtr);
+
+ // Change from BGR to RGB so OpenGL can read the image data.
+ for (int imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode)
+ {
+ colorSwap = tgaFile->imageData[imageIdx];
+ tgaFile->imageData[imageIdx] = tgaFile->imageData[imageIdx + 2];
+ tgaFile->imageData[imageIdx + 2] = colorSwap;
+ }
+
+ fclose(filePtr);
+ return true;
+}
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/TgaFile.h b/KaplaDemo/samples/sampleViewer3/TgaFile.h
new file mode 100644
index 00000000..7b6bfae2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/TgaFile.h
@@ -0,0 +1,230 @@
+/* ---------------------------------------------------------------------------
+* Truevision Targa Reader/Writer
+* $Id: targa.h,v 1.7 2003/06/21 09:30:53 emikulic Exp $
+*
+* Copyright (C) 2001-2003, Emil Mikulic.
+*
+* Source and binary redistribution of this code, with or without
+* changes, for free or for profit, is allowed as long as this copyright
+* notice is kept intact. Modified versions have to be clearly marked
+* as modified.
+*
+* This code is provided without any warranty. The copyright holder is
+* not liable for anything bad that might happen as a result of the
+* code.
+*
+*
+* This version modified by NVIDIA Corporation to prevent compilation on
+* platforms other than Windows.
+* -------------------------------------------------------------------------*/
+
+#ifndef _TARGA_H_
+#define _TARGA_H_
+
+#include <stdio.h>
+
+#ifndef _MSC_VER
+# include <inttypes.h>
+#else /* MSVC */
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+#endif
+
+#define BIT(index) (1 << (index))
+
+#if defined(__CELLOS_LV2__) || defined(__ghs__) || (defined(_XBOX) && _XBOX_VER == 200)
+# define htole16(x) ( (((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8) )
+# define letoh16(x) htole16(x)
+#else /* little endian */
+# define htole16(x) (x)
+# define letoh16(x) (x)
+#endif /* endianness */
+
+ /* Targa image and header fields -------------------------------------------*/
+ typedef struct
+ {
+ /* Note that Targa is stored in little-endian order */
+ uint8_t image_id_length;
+
+ uint8_t color_map_type;
+ /* color map = palette */
+#define TGA_COLOR_MAP_ABSENT 0
+#define TGA_COLOR_MAP_PRESENT 1
+
+ uint8_t image_type;
+#define TGA_IMAGE_TYPE_NONE 0 /* no image data */
+#define TGA_IMAGE_TYPE_COLORMAP 1 /* uncompressed, color-mapped */
+#define TGA_IMAGE_TYPE_BGR 2 /* uncompressed, true-color */
+#define TGA_IMAGE_TYPE_MONO 3 /* uncompressed, black and white */
+#define TGA_IMAGE_TYPE_COLORMAP_RLE 9 /* run-length, color-mapped */
+#define TGA_IMAGE_TYPE_BGR_RLE 10 /* run-length, true-color */
+#define TGA_IMAGE_TYPE_MONO_RLE 11 /* run-length, black and white */
+
+ /* color map specification */
+ uint16_t color_map_origin; /* index of first entry */
+ uint16_t color_map_length; /* number of entries included */
+ uint8_t color_map_depth; /* number of bits per entry */
+
+ /* image specification */
+ uint16_t origin_x;
+ uint16_t origin_y;
+ uint16_t width;
+ uint16_t height;
+ uint8_t pixel_depth;
+
+ uint8_t image_descriptor;
+ /* bits 0,1,2,3 - attribute bits per pixel
+ * bit 4 - set if image is stored right-to-left
+ * bit 5 - set if image is stored top-to-bottom
+ * bits 6,7 - unused (must be set to zero)
+ */
+#define TGA_ATTRIB_BITS uint8_t(BIT(0)|BIT(1)|BIT(2)|BIT(3))
+#define TGA_R_TO_L_BIT uint8_t(BIT(4))
+#define TGA_T_TO_B_BIT uint8_t(BIT(5))
+#define TGA_UNUSED_BITS uint8_t(BIT(6)|BIT(7))
+ /* Note: right-to-left order is not honored by some Targa readers */
+
+ uint8_t *image_id;
+ /* The length of this field is given in image_id_length, it's read raw
+ * from the file so it's not not guaranteed to be zero-terminated. If
+ * it's not NULL, it needs to be deallocated. see: tga_free_buffers()
+ */
+
+ uint8_t *color_map_data;
+ /* See the "color map specification" fields above. If not NULL, this
+ * field needs to be deallocated. see: tga_free_buffers()
+ */
+
+ uint8_t *image_data;
+ /* Follows image specification fields (see above) */
+
+ /* Extension area and developer area are silently ignored. The Targa 2.0
+ * spec says we're not required to read or write them.
+ */
+
+ } tga_image;
+
+
+
+ /* For decoding header bits ------------------------------------------------*/
+ uint8_t tga_get_attribute_bits(const tga_image *tga);
+ int tga_is_right_to_left(const tga_image *tga);
+ int tga_is_top_to_bottom(const tga_image *tga);
+ int tga_is_colormapped(const tga_image *tga);
+ int tga_is_rle(const tga_image *tga);
+ int tga_is_mono(const tga_image *tga);
+
+
+
+ /* Error handling ----------------------------------------------------------*/
+ typedef enum {
+ TGA_NOERR,
+ TGAERR_FOPEN,
+ TGAERR_EOF,
+ TGAERR_WRITE,
+ TGAERR_CMAP_TYPE,
+ TGAERR_IMG_TYPE,
+ TGAERR_NO_IMG,
+ TGAERR_CMAP_MISSING,
+ TGAERR_CMAP_PRESENT,
+ TGAERR_CMAP_LENGTH,
+ TGAERR_CMAP_DEPTH,
+ TGAERR_ZERO_SIZE,
+ TGAERR_PIXEL_DEPTH,
+ TGAERR_NO_MEM,
+ TGAERR_NOT_CMAP,
+ TGAERR_RLE,
+ TGAERR_INDEX_RANGE,
+ TGAERR_MONO
+ } tga_result;
+
+ const char *tga_error(const tga_result errcode);
+
+ typedef void TGA_FP;
+ struct tgaFileOperations
+ {
+ int(*m_fopen_s)(TGA_FP** stream, const char * filename, const char * mode);
+ size_t(*m_fread)(void* ptr, size_t size, size_t count, TGA_FP* stream);
+ size_t(*m_fwrite)(const void* ptr, size_t size, size_t count, TGA_FP* stream);
+ int(*m_feof)(TGA_FP* stream);
+ int(*m_fclose)(void* stream);
+ };
+
+
+ /* Load/save ---------------------------------------------------------------*/
+ tga_result tga_read(tga_image *dest, const char *filename, tgaFileOperations* fops = NULL);
+ tga_result tga_read_from_FILE(tga_image *dest, TGA_FP* fp, tgaFileOperations* fops = NULL);
+ tga_result tga_write(const char *filename, const tga_image *src, tgaFileOperations* fops = NULL);
+ tga_result tga_write_to_FILE(TGA_FP *fp, const tga_image *src, tgaFileOperations* fops = NULL);
+
+
+ /* Convenient writing functions --------------------------------------------*/
+ tga_result tga_write_mono(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height);
+
+ tga_result tga_write_mono_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height);
+
+ tga_result tga_write_bgr(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth);
+
+ tga_result tga_write_bgr_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth);
+
+ /* These functions will use tga_swap_red_blue to MODIFY your image data */
+ tga_result tga_write_rgb(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth);
+
+ tga_result tga_write_rgb_rle(const char *filename, uint8_t *image,
+ const uint16_t width, const uint16_t height, const uint8_t depth);
+
+
+
+ /* Manipulation ------------------------------------------------------------*/
+ tga_result tga_flip_horiz(tga_image *img);
+ tga_result tga_flip_vert(tga_image *img);
+ tga_result tga_color_unmap(tga_image *img);
+
+ uint8_t *tga_find_pixel(const tga_image *img, uint16_t x, uint16_t y);
+ tga_result tga_unpack_pixel(const uint8_t *src, const uint8_t bits,
+ uint8_t *b, uint8_t *g, uint8_t *r, uint8_t *a);
+ tga_result tga_pack_pixel(uint8_t *dest, const uint8_t bits,
+ const uint8_t b, const uint8_t g, const uint8_t r, const uint8_t a);
+
+ tga_result tga_desaturate(tga_image *img,
+ const int cr, const int cg, const int cb, const int dv);
+ tga_result tga_desaturate_rec_601_1(tga_image *img);
+ tga_result tga_desaturate_rec_709(tga_image *img);
+ tga_result tga_desaturate_itu(tga_image *img);
+ tga_result tga_desaturate_avg(tga_image *img);
+ tga_result tga_convert_depth(tga_image *img, const uint8_t bits);
+ tga_result tga_swap_red_blue(tga_image *img);
+
+ void tga_free_buffers(tga_image *img);
+
+
+
+#ifndef TGA_KEEP_MACROS /* useful for targa.c */
+# undef htole16
+# undef letoh16
+#endif
+
+
+
+#include <vector>
+
+typedef struct
+{
+ unsigned char imageTypeCode;
+ short int imageWidth;
+ short int imageHeight;
+ unsigned char bitCount;
+ unsigned char *imageData;
+} TGAFILE;
+
+
+bool LoadTGAFile(const char *filename, TGAFILE *tgaFile);
+
+#endif /* !_TARGA_H_ */
+/* vim:set tabstop=4 shiftwidth=4 textwidth=78 expandtab: */
diff --git a/KaplaDemo/samples/sampleViewer3/Timing.cpp b/KaplaDemo/samples/sampleViewer3/Timing.cpp
new file mode 100644
index 00000000..1dd37742
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Timing.cpp
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#define NOMINMAX
+#include <windows.h>
+#include "Timing.h"
+
+
+unsigned long getTime()
+{
+ return timeGetTime();
+}
+
+
+float getCurrentTime()
+{
+ unsigned int currentTime = timeGetTime();
+ return (float)(currentTime)*0.001f;
+}
+
+
+float getElapsedTime()
+{
+ static LARGE_INTEGER previousTime;
+ static LARGE_INTEGER freq;
+ static bool init = false;
+ if(!init){
+ QueryPerformanceFrequency(&freq);
+ QueryPerformanceCounter(&previousTime);
+ init=true;
+ }
+ LARGE_INTEGER currentTime;
+ QueryPerformanceCounter(&currentTime);
+ unsigned long long elapsedTime = currentTime.QuadPart - previousTime.QuadPart;
+ previousTime = currentTime;
+ return (float)(elapsedTime)/(freq.QuadPart);
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/Timing.h b/KaplaDemo/samples/sampleViewer3/Timing.h
new file mode 100644
index 00000000..89b1d00d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Timing.h
@@ -0,0 +1,8 @@
+#ifndef TIMING_H
+#define TIMING_H
+
+ unsigned long getTime();
+ float getCurrentTime();
+ float getElapsedTime();
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Vec/Bounds3.h b/KaplaDemo/samples/sampleViewer3/Vec/Bounds3.h
new file mode 100644
index 00000000..24b68fbf
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Vec/Bounds3.h
@@ -0,0 +1,182 @@
+#ifndef BOUNDS3_H
+#define BOUNDS3_H
+
+#include "Vec3.h"
+
+// Singe / VecVecReal Precision Vec 3
+// Matthias Mueller
+// derived from Vec3.h
+
+namespace M
+{
+
+class Bounds3
+{
+public:
+
+ Vec3 minimum, maximum;
+
+ Bounds3()
+ {
+ // Default to empty boxes for compatibility TODO: PT: remove this if useless
+ setEmpty();
+ }
+
+
+ ~Bounds3()
+ {
+ //nothing
+ }
+
+
+ void setEmpty()
+ {
+ // We know use this particular pattern for empty boxes
+ set(MAX_VEC_REAL, MAX_VEC_REAL, MAX_VEC_REAL,
+ MIN_VEC_REAL, MIN_VEC_REAL, MIN_VEC_REAL);
+ }
+
+ void setInfinite()
+ {
+ set(MIN_VEC_REAL, MIN_VEC_REAL, MIN_VEC_REAL,
+ MAX_VEC_REAL, MAX_VEC_REAL, MAX_VEC_REAL);
+ }
+
+ void set(VecReal mi, VecReal miny, VecReal minz, VecReal maxx, VecReal maxy,VecReal maxz)
+ {
+ minimum.set(mi, miny, minz);
+ maximum.set(maxx, maxy, maxz);
+ }
+
+ void set(const Vec3& _min, const Vec3& _max)
+ {
+ minimum = _min;
+ maximum = _max;
+ }
+
+ void include(const Vec3& v)
+ {
+ maximum.max(v);
+ minimum.min(v);
+ }
+
+ void combine(const Bounds3& b2)
+ {
+ // - if we're empty, min = MAX,MAX,MAX => min will be b2 in all cases => it will copy b2, ok
+ // - if b2 is empty, the opposite happens => keep us unchanged => ok
+ // => same behavior as before, automatically
+ minimum.min(b2.minimum);
+ maximum.max(b2.maximum);
+ }
+
+ //void boundsOfOBB(const Mat33& orientation, const Vec3& translation, const Vec3& halfDims)
+ //{
+ //VecReal dimx = halfDims[0];
+ //VecReal dimy = halfDims[1];
+ //VecReal dimz = halfDims[2];
+
+ //VecReal x = Math::abs(orientation(0,0) * dimx) + Math::abs(orientation(0,1) * dimy) + Math::abs(orientation(0,2) * dimz);
+ //VecReal y = Math::abs(orientation(1,0) * dimx) + Math::abs(orientation(1,1) * dimy) + Math::abs(orientation(1,2) * dimz);
+ //VecReal z = Math::abs(orientation(2,0) * dimx) + Math::abs(orientation(2,1) * dimy) + Math::abs(orientation(2,2) * dimz);
+
+ //set(-x + translation[0], -y + translation[1], -z + translation[2], x + translation[0], y + translation[1], z + translation[2]);
+ //}
+
+ //void transform(const Mat33& orientation, const Vec3& translation)
+ //{
+ //// convert to center and extents form
+ //Vec3 center, extents;
+ //getCenter(center);
+ //getExtents(extents);
+
+ //center = orientation * center + translation;
+ //boundsOfOBB(orientation, center, extents);
+ //}
+
+ bool isEmpty() const
+ {
+ // Consistency condition for (Min, Max) boxes: min < max
+ // TODO: PT: should we test against the explicit pattern ?
+ if(minimum.x < maximum.x) return false;
+ if(minimum.y < maximum.y) return false;
+ if(minimum.z < maximum.z) return false;
+ return true;
+ }
+
+ bool intersects(const Bounds3& b) const
+ {
+ if ((b.minimum.x > maximum.x) || (minimum.x > b.maximum.x)) return false;
+ if ((b.minimum.y > maximum.y) || (minimum.y > b.maximum.y)) return false;
+ if ((b.minimum.z > maximum.z) || (minimum.z > b.maximum.z)) return false;
+ return true;
+ }
+
+ bool intersects2D(const Bounds3& b, unsigned axis) const
+ {
+ // TODO: PT: could be static and like this:
+ // static unsigned i[3] = { 1,2,0,1 };
+ // const unsigned ii = i[axis];
+ // const unsigned jj = i[axis+1];
+ const unsigned i[3] = { 1,0,0 };
+ const unsigned j[3] = { 2,2,1 };
+ const unsigned ii = i[axis];
+ const unsigned jj = j[axis];
+ if ((b.minimum[ii] > maximum[ii]) || (minimum[ii] > b.maximum[ii])) return false;
+ if ((b.minimum[jj] > maximum[jj]) || (minimum[jj] > b.maximum[jj])) return false;
+ return true;
+ }
+
+ bool contain(const Vec3& v) const
+ {
+ if ((v.x < minimum.x) || (v.x > maximum.x)) return false;
+ if ((v.y < minimum.y) || (v.y > maximum.y)) return false;
+ if ((v.z < minimum.z) || (v.z > maximum.z)) return false;
+ return true;
+ }
+
+ void getCenter(Vec3& center) const
+ {
+ center.add(minimum,maximum);
+ center *= VecReal(0.5);
+ }
+
+ void getDimensions(Vec3& dims) const
+ {
+ dims.subtract(maximum,minimum);
+ }
+
+ void getExtents(Vec3& extents) const
+ {
+ extents.subtract(maximum,minimum);
+ extents *= VecReal(0.5);
+ }
+
+ void setCenterExtents(const Vec3& c, const Vec3& e)
+ {
+ minimum = c - e;
+ maximum = c + e;
+ }
+
+ void scale(VecReal _scale)
+ {
+ Vec3 center, extents;
+ getCenter(center);
+ getExtents(extents);
+ setCenterExtents(center, extents * _scale);
+ }
+
+ void fatten(VecReal distance)
+ {
+ minimum.x -= distance;
+ minimum.y -= distance;
+ minimum.z -= distance;
+
+ maximum.x += distance;
+ maximum.y += distance;
+ maximum.z += distance;
+ }
+};
+
+}
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Vec/Plane.h b/KaplaDemo/samples/sampleViewer3/Vec/Plane.h
new file mode 100644
index 00000000..db735926
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Vec/Plane.h
@@ -0,0 +1,73 @@
+#ifndef PLANE_H
+#define PLANE_H
+
+#include "Vec3.H"
+
+// Singe / VecReal Precision Vec 3
+// Matthias Mueller
+// derived from Plane
+
+namespace M
+{
+
+class Plane
+{
+public:
+ Plane() {}
+ Plane(VecReal nx, VecReal ny, VecReal nz, VecReal distance)
+ : n(nx, ny, nz)
+ , d(distance)
+ {}
+
+ Plane(const Vec3& normal, VecReal distance)
+ : n(normal)
+ , d(distance)
+ {}
+
+ Plane(const Vec3& point, const Vec3& normal)
+ : n(normal)
+ , d(-point.dot(n)) // p satisfies normal.dot(p) + d = 0
+ {
+ }
+
+ Plane(const Vec3& p0, const Vec3& p1, const Vec3& p2)
+ {
+ n = (p1 - p0).cross(p2 - p0).getNormalized();
+ d = -p0.dot(n);
+ }
+
+ VecReal distance(const Vec3& p) const
+ {
+ return p.dot(n) + d;
+ }
+
+ bool contains(const Vec3& p) const
+ {
+ return vecAbs(distance(p)) < (1.0e-7f);
+ }
+
+ Vec3 project(const Vec3 & p) const
+ {
+ return p - n * distance(p);
+ }
+
+ Vec3 pointInPlane() const
+ {
+ return -n*d;
+ }
+
+ void normalize()
+ {
+ VecReal denom = 1.0f / n.magnitude();
+ n *= denom;
+ d *= denom;
+ }
+
+ Vec3 n; //!< The normal to the plane
+ VecReal d; //!< The distance from the origin
+};
+
+}
+
+#endif
+
diff --git a/KaplaDemo/samples/sampleViewer3/Vec/Quat.h b/KaplaDemo/samples/sampleViewer3/Vec/Quat.h
new file mode 100644
index 00000000..d6b63633
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Vec/Quat.h
@@ -0,0 +1,301 @@
+#ifndef QUAT_H
+#define QUAT_H
+
+// Singe / VecReal Precision Vec 3
+// Matthias Mueller
+// derived from Quat.h
+
+#include "Vec3.h"
+
+namespace M
+{
+
+class Quat
+{
+public:
+ Quat() { }
+
+ VecReal x,y,z,w;
+
+ Quat(VecReal nx, VecReal ny, VecReal nz, VecReal nw) : x(nx),y(ny),z(nz),w(nw) {}
+
+ Quat(VecReal angleRadians, const Vec3& unitAxis)
+ {
+ const VecReal a = angleRadians * 0.5f;
+ const VecReal s = vecSin(a);
+ w = cos(a);
+ x = unitAxis.x * s;
+ y = unitAxis.y * s;
+ z = unitAxis.z * s;
+ }
+
+ Quat(const Quat& v): x(v.x), y(v.y), z(v.z), w(v.w) {}
+
+ void toRadiansAndUnitAxis(VecReal& angle, Vec3& axis) const
+ {
+ const VecReal quatEpsilon = VecReal(1.0e-8f);
+ const VecReal s2 = x*x+y*y+z*z;
+ if(s2<quatEpsilon*quatEpsilon) // can't extract a sensible axis
+ {
+ angle = 0;
+ axis = Vec3(1,0,0);
+ }
+ else
+ {
+ const VecReal s = 1.0f / vecSqrt(s2);
+ axis = Vec3(x,y,z) * s;
+ angle = vecAbs(w)<quatEpsilon ? VEC_PI : vecAtan2(s2*s, w) * 2;
+ }
+
+ }
+
+ /**
+ \brief Gets the angle between this quat and the identity quaternion.
+
+ <b>Unit:</b> Radians
+ */
+ VecReal getAngle() const
+ {
+ return vecACos(w) * VecReal(2);
+ }
+
+
+ /**
+ \brief Gets the angle between this quat and the argument
+
+ <b>Unit:</b> Radians
+ */
+ VecReal getAngle(const Quat& q) const
+ {
+ return vecACos(dot(q)) * VecReal(2);
+ }
+
+
+ /**
+ \brief This is the squared 4D vector length, should be 1 for unit quaternions.
+ */
+ VecReal magnitudeSquared() const
+ {
+ return x*x + y*y + z*z + w*w;
+ }
+
+ /**
+ \brief returns the scalar product of this and other.
+ */
+ VecReal dot(const Quat& v) const
+ {
+ return x * v.x + y * v.y + z * v.z + w * v.w;
+ }
+
+ Quat getNormalized() const
+ {
+ const VecReal s = (VecReal)1.0/magnitude();
+ return Quat(x*s, y*s, z*s, w*s);
+ }
+
+
+ VecReal magnitude() const
+ {
+ return vecSqrt(magnitudeSquared());
+ }
+
+ //modifiers:
+ /**
+ \brief maps to the closest unit quaternion.
+ */
+ VecReal normalize() // convert this Quat to a unit quaternion
+ {
+ const VecReal mag = magnitude();
+ if (mag)
+ {
+ const VecReal imag = VecReal(1) / mag;
+
+ x *= imag;
+ y *= imag;
+ z *= imag;
+ w *= imag;
+ }
+ return mag;
+ }
+
+ /*
+ \brief returns the conjugate.
+
+ \note for unit quaternions, this is the inverse.
+ */
+ Quat getConjugate() const
+ {
+ return Quat(-x,-y,-z,w);
+ }
+
+ /*
+ \brief returns imaginary part.
+ */
+ Vec3 getImaginaryPart() const
+ {
+ return Vec3(x,y,z);
+ }
+
+ /** brief computes rotation of x-axis */
+ Vec3 getBasisVector0() const
+ {
+ // return rotate(Vec3(1,0,0));
+ const VecReal x2 = x*(VecReal)2.0;
+ const VecReal w2 = w*(VecReal)2.0;
+ return Vec3( (w * w2) - 1.0f + x*x2,
+ (z * w2) + y*x2,
+ (-y * w2) + z*x2);
+ }
+
+ /** brief computes rotation of y-axis */
+ Vec3 getBasisVector1() const
+ {
+ // return rotate(Vec3(0,1,0));
+ const VecReal y2 = y*(VecReal)2.0;
+ const VecReal w2 = w*(VecReal)2.0;
+ return Vec3( (-z * w2) + x*y2,
+ (w * w2) - 1.0f + y*y2,
+ (x * w2) + z*y2);
+ }
+
+
+ /** brief computes rotation of z-axis */
+ Vec3 getBasisVector2() const
+ {
+ // return rotate(Vec3(0,0,1));
+ const VecReal z2 = z*(VecReal)2.0;
+ const VecReal w2 = w*(VecReal)2.0;
+ return Vec3( (y * w2) + x*z2,
+ (-x * w2) + y*z2,
+ (w * w2) - 1.0f + z*z2);
+ }
+
+ /**
+ rotates passed vec by this (assumed unitary)
+ */
+ const Vec3 rotate(const Vec3& v) const
+ // const Vec3 rotate(const Vec3& v) const
+ {
+ const VecReal vx = (VecReal)2.0*v.x;
+ const VecReal vy = (VecReal)2.0*v.y;
+ const VecReal vz = (VecReal)2.0*v.z;
+ const VecReal w2 = w*w-(VecReal)0.5;
+ const VecReal dot2 = (x*vx + y*vy +z*vz);
+ return Vec3
+ (
+ (vx*w2 + (y * vz - z * vy)*w + x*dot2),
+ (vy*w2 + (z * vx - x * vz)*w + y*dot2),
+ (vz*w2 + (x * vy - y * vx)*w + z*dot2)
+ );
+ /*
+ const Vec3 qv(x,y,z);
+ return (v*(w*w-0.5f) + (qv.cross(v))*w + qv*(qv.dot(v)))*2;
+ */
+ }
+
+ /**
+ inverse rotates passed vec by this (assumed unitary)
+ */
+ const Vec3 rotateInv(const Vec3& v) const
+ // const Vec3 rotateInv(const Vec3& v) const
+ {
+ const VecReal vx = (VecReal)2.0*v.x;
+ const VecReal vy = (VecReal)2.0*v.y;
+ const VecReal vz = (VecReal)2.0*v.z;
+ const VecReal w2 = w*w-(VecReal)0.5;
+ const VecReal dot2 = (x*vx + y*vy +z*vz);
+ return Vec3
+ (
+ (vx*w2 - (y * vz - z * vy)*w + x*dot2),
+ (vy*w2 - (z * vx - x * vz)*w + y*dot2),
+ (vz*w2 - (x * vy - y * vx)*w + z*dot2)
+ );
+ // const Vec3 qv(x,y,z);
+ // return (v*(w*w-0.5f) - (qv.cross(v))*w + qv*(qv.dot(v)))*2;
+ }
+
+ /**
+ \brief Assignment operator
+ */
+ Quat& operator=(const Quat& p) { x = p.x; y = p.y; z = p.z; w = p.w; return *this; }
+
+ Quat& operator*= (const Quat& q)
+ {
+ const VecReal tx = w*q.x + q.w*x + y*q.z - q.y*z;
+ const VecReal ty = w*q.y + q.w*y + z*q.x - q.z*x;
+ const VecReal tz = w*q.z + q.w*z + x*q.y - q.x*y;
+
+ w = w*q.w - q.x*x - y*q.y - q.z*z;
+ x = tx;
+ y = ty;
+ z = tz;
+
+ return *this;
+ }
+
+ Quat& operator+= (const Quat& q)
+ {
+ x+=q.x;
+ y+=q.y;
+ z+=q.z;
+ w+=q.w;
+ return *this;
+ }
+
+ Quat& operator-= (const Quat& q)
+ {
+ x-=q.x;
+ y-=q.y;
+ z-=q.z;
+ w-=q.w;
+ return *this;
+ }
+
+ Quat& operator*= (const VecReal s)
+ {
+ x*=s;
+ y*=s;
+ z*=s;
+ w*=s;
+ return *this;
+ }
+
+ /** quaternion multiplication */
+ Quat operator*(const Quat& q) const
+ {
+ return Quat(w*q.x + q.w*x + y*q.z - q.y*z,
+ w*q.y + q.w*y + z*q.x - q.z*x,
+ w*q.z + q.w*z + x*q.y - q.x*y,
+ w*q.w - x*q.x - y*q.y - z*q.z);
+ }
+
+ /** quaternion addition */
+ Quat operator+(const Quat& q) const
+ {
+ return Quat(x+q.x,y+q.y,z+q.z,w+q.w);
+ }
+
+ /** quaternion subtraction */
+ Quat operator-() const
+ {
+ return Quat(-x,-y,-z,-w);
+ }
+
+
+ Quat operator-(const Quat& q) const
+ {
+ return Quat(x-q.x,y-q.y,z-q.z,w-q.w);
+ }
+
+
+ Quat operator*(VecReal r) const
+ {
+ return Quat(x*r,y*r,z*r,w*r);
+ }
+
+ static Quat createIdentity() { return Quat(0,0,0,1); }
+};
+
+}
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Vec/Transform.h b/KaplaDemo/samples/sampleViewer3/Vec/Transform.h
new file mode 100644
index 00000000..e08801de
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Vec/Transform.h
@@ -0,0 +1,94 @@
+#ifndef TRANSFORM_H
+#define TRANSFORM_H
+
+#include "Vec3.h"
+#include "Quat.h"
+#include "Plane.h"
+
+// Singe / VecVecReal Precision Vec 3
+// Matthias Mueller
+// derived from NxVec3.h
+
+namespace M
+{
+
+class Transform
+{
+public:
+ Quat q;
+ Vec3 p;
+
+ Transform() {};
+ Transform(const Vec3& position): q(0, 0, 0, 1), p(position) {}
+ Transform(const Quat& orientation): q(orientation), p(0, 0, 0) {}
+ Transform(const Vec3& p0, const Quat& q0): q(q0), p(p0) {}
+
+ Transform operator*(const Transform& x) const
+ {
+ return transform(x);
+ }
+
+ Transform getInverse() const
+ {
+ return Transform(q.rotateInv(-p),q.getConjugate());
+ }
+
+
+ Vec3 transform(const Vec3& input) const
+ {
+ return q.rotate(input) + p;
+ }
+
+ Vec3 transformInv(const Vec3& input) const
+ {
+ return q.rotateInv(input-p);
+ }
+
+ Vec3 rotate(const Vec3& input) const
+ {
+ return q.rotate(input);
+ }
+
+ Vec3 rotateInv(const Vec3& input) const
+ {
+ return q.rotateInv(input);
+ }
+
+ Transform transform(const Transform& src) const
+ {
+ return Transform(q.rotate(src.p) + p, q*src.q);
+ }
+
+ Transform transformInv(const Transform& src) const
+ {
+ Quat qinv = q.getConjugate();
+ return Transform(qinv.rotate(src.p - p), qinv*src.q);
+ }
+
+ static Transform createIdentity()
+ {
+ return Transform(Vec3(0));
+ }
+
+ Plane transform(const Plane& plane) const
+ {
+ Vec3 transformedNormal = rotate(plane.n);
+ return Plane(transformedNormal, plane.d - p.dot(transformedNormal));
+ }
+
+ Plane inverseTransform(const Plane& plane) const
+ {
+ Vec3 transformedNormal = rotateInv(plane.n);
+ return Plane(transformedNormal, plane.d + p.dot(plane.n));
+ }
+
+ Transform getNormalized() const
+ {
+ return Transform(p, q.getNormalized());
+ }
+
+};
+
+}
+
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Vec/Vec3.h b/KaplaDemo/samples/sampleViewer3/Vec/Vec3.h
new file mode 100644
index 00000000..13b877dd
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Vec/Vec3.h
@@ -0,0 +1,490 @@
+#ifndef VEC3_H
+#define VEC3_H
+
+#include <math.h>
+
+// Singe / VecReal Precision Vec 3
+// Matthias Mueller
+// derived from NxVec3.h
+
+namespace M
+{
+
+#define VEC3_DOUBLE 0
+
+#if VEC3_DOUBLE
+
+typedef double VecReal;
+#define MAX_VEC_REAL DBL_MAX
+#define MIN_VEC_REAL -DBL_MAX
+#define VEC_PI 3.14159265358979323846
+
+inline int vecFloor(VecReal f ) { return (int)::floor(f); }
+inline VecReal vecSqrt(VecReal f) { return ::sqrt(f); }
+inline VecReal vecSin(VecReal f) { return ::sin(f); }
+inline VecReal vecCos(VecReal f) { return ::cos(f); }
+inline VecReal vecAbs(VecReal f) { return ::abs(f); }
+inline VecReal vecAtan2(VecReal y, VecReal x) { return ::atan2(y, x); }
+inline VecReal vecASin(VecReal f) { return ::asin(f); }
+inline VecReal vecACos(VecReal f) { return ::acos(f); }
+inline VecReal vecATan(VecReal f) { return ::atan(f); }
+
+#else
+
+typedef float VecReal;
+#define MAX_VEC_REAL FLT_MAX
+#define MIN_VEC_REAL -FLT_MAX
+#define VEC_PI 3.14159265358979323846f
+
+inline int vecFloor(VecReal f ) { return (int)::floorf(f); }
+inline VecReal vecSqrt(VecReal f) { return ::sqrtf(f); }
+inline VecReal vecSin(VecReal f) { return ::sinf(f); }
+inline VecReal vecCos(VecReal f) { return ::cosf(f); }
+inline VecReal vecAbs(VecReal f) { return ::fabs(f); }
+inline VecReal vecAtan2(VecReal y, VecReal x) { return ::atan2f(y, x); }
+inline VecReal vecASin(VecReal f) { return ::asinf(f); }
+inline VecReal vecACos(VecReal f) { return ::acosf(f); }
+inline VecReal vecATan(VecReal f) { return ::atanf(f); }
+
+#endif
+
+
+/**
+\brief Enum to classify an axis.
+*/
+ enum DAxisType
+ {
+ D_AXIS_PLUS_X,
+ D_AXIS_MINUS_X,
+ D_AXIS_PLUS_Y,
+ D_AXIS_MINUS_Y,
+ D_AXIS_PLUS_Z,
+ D_AXIS_MINUS_Z,
+ D_AXIS_ARBITRARY
+ };
+
+// -------------------------------------------------------------------------------------
+class Vec3
+{
+public:
+ VecReal x,y,z;
+
+ Vec3() {};
+ Vec3(VecReal _x, VecReal _y, VecReal _z) : x(_x), y(_y), z(_z) {}
+ Vec3(const VecReal v[]) : x(v[0]), y(v[1]), z(v[2]) {}
+
+ const VecReal* Vec3::get() const { return &x;}
+ VecReal* get() { return &x; }
+ void get(VecReal * v) const
+ {
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ }
+
+ VecReal& operator[](int index)
+ {
+ return (&x)[index];
+ }
+
+ const VecReal operator[](int index) const
+ {
+ return (&x)[index];
+ }
+
+ void setx(const VecReal & d)
+ {
+ x = d;
+ }
+
+
+ void sety(const VecReal & d)
+ {
+ y = d;
+ }
+
+
+ void setz(const VecReal & d)
+ {
+ z = d;
+ }
+
+ Vec3 getNormalized() const
+ {
+ const VecReal m = magnitudeSquared();
+ return m>0 ? *this * 1.0 / vecSqrt(m) : Vec3(0,0,0);
+ }
+
+ //Operators
+
+ bool operator< (const Vec3&v) const
+ {
+ return ((x < v.x)&&(y < v.y)&&(z < v.z));
+ }
+
+
+ bool operator==(const Vec3& v) const
+ {
+ return ((x == v.x)&&(y == v.y)&&(z == v.z));
+ }
+
+
+ bool operator!=(const Vec3& v) const
+ {
+ return ((x != v.x)||(y != v.y)||(z != v.z));
+ }
+
+ //Methods
+
+ void set(const Vec3 & v)
+ {
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ }
+
+
+ void setNegative(const Vec3 & v)
+ {
+ x = -v.x;
+ y = -v.y;
+ z = -v.z;
+ }
+
+
+ void setNegative()
+ {
+ x = -x;
+ y = -y;
+ z = -z;
+ }
+
+
+
+ void set(const VecReal * v)
+ {
+ x = v[0];
+ y = v[1];
+ z = v[2];
+ }
+
+
+ void set(VecReal _x, VecReal _y, VecReal _z)
+ {
+ this->x = _x;
+ this->y = _y;
+ this->z = _z;
+ }
+
+
+ void set(VecReal v)
+ {
+ x = v;
+ y = v;
+ z = v;
+ }
+
+
+ void zero()
+ {
+ x = y = z = 0.0;
+ }
+
+
+ void setPlusInfinity()
+ {
+ x = y = z = MAX_VEC_REAL;
+ }
+
+
+ void setMinusInfinity()
+ {
+ x = y = z = MIN_VEC_REAL;
+ }
+
+
+ void max(const Vec3 & v)
+ {
+ x = x > v.x ? x : v.x;
+ y = y > v.y ? y : v.y;
+ z = z > v.z ? z : v.z;
+ }
+
+ void min(const Vec3 & v)
+ {
+ x = x < v.x ? x : v.x;
+ y = y < v.y ? y : v.y;
+ z = z < v.z ? z : v.z;
+ }
+
+
+
+
+ void add(const Vec3 & a, const Vec3 & b)
+ {
+ x = a.x + b.x;
+ y = a.y + b.y;
+ z = a.z + b.z;
+ }
+
+
+ void subtract(const Vec3 &a, const Vec3 &b)
+ {
+ x = a.x - b.x;
+ y = a.y - b.y;
+ z = a.z - b.z;
+ }
+
+
+ void arrayMultiply(const Vec3 &a, const Vec3 &b)
+ {
+ x = a.x * b.x;
+ y = a.y * b.y;
+ z = a.z * b.z;
+ }
+
+
+ void multiply(VecReal s, const Vec3 & a)
+ {
+ x = a.x * s;
+ y = a.y * s;
+ z = a.z * s;
+ }
+
+
+ void multiplyAdd(VecReal s, const Vec3 & a, const Vec3 & b)
+ {
+ x = s * a.x + b.x;
+ y = s * a.y + b.y;
+ z = s * a.z + b.z;
+ }
+
+
+ VecReal normalize()
+ {
+ VecReal m = magnitude();
+ if (m)
+ {
+ const VecReal il = VecReal(1.0) / m;
+ x *= il;
+ y *= il;
+ z *= il;
+ }
+ return m;
+ }
+
+
+ void setMagnitude(VecReal length)
+ {
+ VecReal m = magnitude();
+ if(m)
+ {
+ VecReal newLength = length / m;
+ x *= newLength;
+ y *= newLength;
+ z *= newLength;
+ }
+ }
+
+
+ DAxisType snapToClosestAxis()
+ {
+ const VecReal almostOne = 0.999999f;
+ if(x >= almostOne) { set( 1.0f, 0.0f, 0.0f); return D_AXIS_PLUS_X ; }
+ else if(x <= -almostOne) { set(-1.0f, 0.0f, 0.0f); return D_AXIS_MINUS_X; }
+ else if(y >= almostOne) { set( 0.0f, 1.0f, 0.0f); return D_AXIS_PLUS_Y ; }
+ else if(y <= -almostOne) { set( 0.0f, -1.0f, 0.0f); return D_AXIS_MINUS_Y; }
+ else if(z >= almostOne) { set( 0.0f, 0.0f, 1.0f); return D_AXIS_PLUS_Z ; }
+ else if(z <= -almostOne) { set( 0.0f, 0.0f, -1.0f); return D_AXIS_MINUS_Z; }
+ else return D_AXIS_ARBITRARY;
+ }
+
+
+ unsigned int closestAxis() const
+ {
+ const VecReal* vals = &x;
+ unsigned int m = 0;
+ if(abs(vals[1]) > abs(vals[m])) m = 1;
+ if(abs(vals[2]) > abs(vals[m])) m = 2;
+ return m;
+ }
+
+
+ //const methods
+
+ //bool isFinite() const
+ //{
+ // return NxMath::isFinite(x) && NxMath::isFinite(y) && NxMath::isFinite(z);
+ //}
+
+
+ VecReal dot(const Vec3 &v) const
+ {
+ return x * v.x + y * v.y + z * v.z;
+ }
+
+
+ bool sameDirection(const Vec3 &v) const
+ {
+ return x*v.x + y*v.y + z*v.z >= 0.0f;
+ }
+
+
+ VecReal magnitude() const
+ {
+ return sqrt(x * x + y * y + z * z);
+ }
+
+
+ VecReal magnitudeSquared() const
+ {
+ return x * x + y * y + z * z;
+ }
+
+
+ VecReal distance(const Vec3 & v) const
+ {
+ VecReal dx = x - v.x;
+ VecReal dy = y - v.y;
+ VecReal dz = z - v.z;
+ return sqrt(dx * dx + dy * dy + dz * dz);
+ }
+
+
+ VecReal distanceSquared(const Vec3 &v) const
+ {
+ VecReal dx = x - v.x;
+ VecReal dy = y - v.y;
+ VecReal dz = z - v.z;
+ return dx * dx + dy * dy + dz * dz;
+ }
+
+
+ void cross(const Vec3 &left, const Vec3 & right) //prefered version, w/o temp object.
+ {
+ // temps needed in case left or right is this.
+ VecReal a = (left.y * right.z) - (left.z * right.y);
+ VecReal b = (left.z * right.x) - (left.x * right.z);
+ VecReal c = (left.x * right.y) - (left.y * right.x);
+
+ x = a;
+ y = b;
+ z = c;
+ }
+
+
+ bool equals(const Vec3 & v, VecReal epsilon) const
+ {
+ return
+ abs(x - v.x) < epsilon &&
+ abs(y - v.y) < epsilon &&
+ abs(z - v.z) < epsilon;
+ }
+
+
+
+ Vec3 operator -() const
+ {
+ return Vec3(-x, -y, -z);
+ }
+
+
+ Vec3 operator +(const Vec3 & v) const
+ {
+ return Vec3(x + v.x, y + v.y, z + v.z); // RVO version
+ }
+
+
+ Vec3 operator -(const Vec3 & v) const
+ {
+ return Vec3(x - v.x, y - v.y, z - v.z); // RVO version
+ }
+
+
+
+ Vec3 operator *(VecReal f) const
+ {
+ return Vec3(x * f, y * f, z * f); // RVO version
+ }
+
+
+ Vec3 operator /(VecReal f) const
+ {
+ f = VecReal(1.0) / f; return Vec3(x * f, y * f, z * f);
+ }
+
+
+ Vec3& operator +=(const Vec3& v)
+ {
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ return *this;
+ }
+
+
+ Vec3& operator -=(const Vec3& v)
+ {
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ return *this;
+ }
+
+
+ Vec3& operator *=(VecReal f)
+ {
+ x *= f;
+ y *= f;
+ z *= f;
+
+ return *this;
+ }
+
+
+ Vec3& operator /=(VecReal f)
+ {
+ f = 1.0f/f;
+ x *= f;
+ y *= f;
+ z *= f;
+
+ return *this;
+ }
+
+
+ Vec3 cross(const Vec3& v) const
+ {
+ Vec3 temp;
+ temp.cross(*this,v);
+ return temp;
+ }
+
+
+ Vec3 operator^(const Vec3& v) const
+ {
+ Vec3 temp;
+ temp.cross(*this,v);
+ return temp;
+ }
+
+
+ VecReal operator|(const Vec3& v) const
+ {
+ return x * v.x + y * v.y + z * v.z;
+ }
+};
+
+ /**
+ scalar pre-multiplication
+ */
+
+inline Vec3 operator *(VecReal f, const Vec3& v)
+ {
+ return Vec3(f * v.x, f * v.y, f * v.z);
+ }
+
+
+}
+ /** @} */
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleCameraController.cpp b/KaplaDemo/samples/sampleViewer3/VehicleCameraController.cpp
new file mode 100644
index 00000000..8087d25d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleCameraController.cpp
@@ -0,0 +1,165 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "VehicleCameraController.h"
+#include "PxRigidDynamic.h"
+#include "PxQueryFiltering.h"
+#include "PxScene.h"
+#include "PxSceneLock.h"
+#include "vehicle/PxVehicleWheels.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+VehicleCameraController::VehicleCameraController()
+ : mRotateInputY(0.0f),
+ mRotateInputZ(0.0f),
+ mMaxCameraRotateSpeed(5.0f),
+ mCameraRotateAngleY(0.0f),
+ mCameraRotateAngleZ(0.13f),
+ mCameraPos(PxVec3(0, 0, 0)),
+ mCameraTargetPos(PxVec3(0, 0, 0)),
+ mLastCarPos(PxVec3(0, 0, 0)),
+ mLastCarVelocity(PxVec3(0, 0, 0)),
+ mCameraInit(false),
+ mLockOnFocusVehTransform(true),
+ mLastFocusVehTransform(PxTransform(PxIdentity)),
+ mCamDist(5.f)
+{
+}
+
+VehicleCameraController::~VehicleCameraController()
+{
+}
+
+static void dampVec3(const PxVec3& oldPosition, PxVec3& newPosition, PxF32 timestep)
+{
+ PxF32 t = 0.7f * timestep * 8.0f;
+ t = PxMin(t, 1.0f);
+ newPosition = oldPosition * (1 - t) + newPosition * t;
+}
+
+
+void VehicleCameraController::update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene)
+{
+ PxSceneReadLock scopedLock(scene);
+ PxTransform carChassisTransfm;
+ if (mLockOnFocusVehTransform)
+ {
+ carChassisTransfm = actor->getGlobalPose();
+ mLastFocusVehTransform = carChassisTransfm;
+ }
+ else
+ {
+ carChassisTransfm = mLastFocusVehTransform;
+ }
+
+ PxF32 camDist = 5.f;
+ PxF32 cameraYRotExtra = 0.0f;
+
+ PxVec3 velocity = mLastCarPos - carChassisTransfm.p;
+
+ if (mCameraInit)
+ {
+ //Work out the forward and sideways directions.
+ PxVec3 unitZ(0, 0, 1);
+ PxVec3 carDirection = carChassisTransfm.q.rotate(unitZ);
+ PxVec3 unitX(1, 0, 0);
+ PxVec3 carSideDirection = carChassisTransfm.q.rotate(unitX);
+
+ //Acceleration (note that is not scaled by time).
+ PxVec3 acclVec = mLastCarVelocity - velocity;
+
+ //Higher forward accelerations allow the car to speed away from the camera.
+ PxF32 velZ = PxAbs(carDirection.dot(velocity));
+ camDist = PxMin(PxMax(camDist + velZ*100.0f, 10.0f), 15.f);
+
+ //Higher sideways accelerations allow the car's rotation to speed away from the camera's rotation.
+ PxF32 acclX = carSideDirection.dot(acclVec);
+ cameraYRotExtra = -acclX*10.0f;
+ //At very small sideways speeds the camera greatly amplifies any numeric error in the body and leads to a slight jitter.
+ //Scale cameraYRotExtra by a value in range (0,1) for side speeds in range (0.1,1.0) and by zero for side speeds less than 0.1.
+ PxFixedSizeLookupTable<4> table;
+ table.addPair(0.0f, 0.0f);
+ table.addPair(0.1f*dtime, 0);
+ table.addPair(1.0f*dtime, 1);
+ PxF32 velX = carSideDirection.dot(velocity);
+ cameraYRotExtra *= table.getYVal(PxAbs(velX));
+ }
+
+ mCameraRotateAngleY += mRotateInputY*mMaxCameraRotateSpeed*dtime;
+ mCameraRotateAngleY = physx::intrinsics::fsel(mCameraRotateAngleY - 10 * PxPi, mCameraRotateAngleY - 10 * PxPi, physx::intrinsics::fsel(-mCameraRotateAngleY - 10 * PxPi, mCameraRotateAngleY + 10 * PxPi, mCameraRotateAngleY));
+ mCameraRotateAngleZ += mRotateInputZ*mMaxCameraRotateSpeed*dtime;
+ mCameraRotateAngleZ = PxClamp(mCameraRotateAngleZ, -PxPi*0.05f, PxPi*0.45f);
+
+ PxVec3 cameraDir = PxVec3(0, 0, 1)*PxCos(mCameraRotateAngleY + cameraYRotExtra) + PxVec3(1, 0, 0)*PxSin(mCameraRotateAngleY + cameraYRotExtra);
+
+ cameraDir = cameraDir*PxCos(mCameraRotateAngleZ) - PxVec3(0, 1, 0)*PxSin(mCameraRotateAngleZ);
+
+ const PxVec3 direction = carChassisTransfm.q.rotate(cameraDir);
+ PxVec3 target = carChassisTransfm.p;
+ target.y += 0.5f;
+
+ PxRaycastBuffer hit;
+ PxQueryFilterData filterData(PxQueryFlag::eSTATIC | PxQueryFlag::eDYNAMIC);
+ scene.raycast(target, -direction, camDist, hit, PxHitFlag::eDISTANCE, filterData);
+ if (hit.hasBlock && hit.block.shape != NULL)
+ {
+ camDist = hit.block.distance - 0.25f;
+ }
+
+ camDist = PxMax(4.0f, PxMin(camDist, 50.0f));
+
+ mCamDist += PxMax(camDist - mCamDist, 0.f)*0.05f + PxMin(0.f, camDist - mCamDist);
+ camDist = mCamDist;
+
+ PxVec3 position = target - direction*camDist;
+
+ if (mCameraInit)
+ {
+ dampVec3(mCameraPos, position, dtime);
+ dampVec3(mCameraTargetPos, target, dtime);
+ }
+
+ mCameraPos = position;
+ mCameraTargetPos = target;
+ mCameraInit = true;
+
+ mLastCarVelocity = velocity;
+ mLastCarPos = carChassisTransfm.p;
+}
+
+void VehicleCameraController::update(const PxReal dtime, const PxVehicleWheels& focusVehicle, PxScene& scene)
+{
+ const PxRigidDynamic* actor = focusVehicle.getRigidDynamicActor();
+ update(dtime, actor, scene);
+}
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleCameraController.h b/KaplaDemo/samples/sampleViewer3/VehicleCameraController.h
new file mode 100644
index 00000000..e4df2d39
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleCameraController.h
@@ -0,0 +1,93 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef VEHICLE_CAMERA_CONTROLLER_H
+#define VEHICLE_CAMERA_CONTROLLER_H
+
+#include "common/PxPhysXCommonConfig.h"
+#include "foundation/PxVec3.h"
+#include "foundation/PxTransform.h"
+
+using namespace physx;
+
+namespace physx
+{
+ class PxScene;
+ class PxVehicleWheels;
+ class PxRigidDynamic;
+}
+;
+
+class VehicleCameraController
+{
+public:
+
+ VehicleCameraController();
+ ~VehicleCameraController();
+
+ void setInputs(const PxF32 rotateInputY, const PxF32 rotateInputZ)
+ {
+ mRotateInputY = rotateInputY;
+ mRotateInputZ = rotateInputZ;
+ }
+
+ void update(const PxF32 dtime, const PxVehicleWheels& focusVehicle, PxScene& scene);
+
+ void restart() {}
+
+ bool getIsLockedOnVehicleTransform() const { return mLockOnFocusVehTransform; }
+ void toggleLockOnVehTransform() { mLockOnFocusVehTransform = !mLockOnFocusVehTransform; }
+
+ const PxVec3& getCameraPos() const { return mCameraPos; }
+ const PxVec3& getCameraTar() const { return mCameraTargetPos; }
+
+private:
+
+ PxF32 mRotateInputY;
+ PxF32 mRotateInputZ;
+
+ PxF32 mMaxCameraRotateSpeed;
+ PxF32 mCameraRotateAngleY;
+ PxF32 mCameraRotateAngleZ;
+ PxVec3 mCameraPos;
+ PxVec3 mCameraTargetPos;
+ PxVec3 mLastCarPos;
+ PxVec3 mLastCarVelocity;
+ bool mCameraInit;
+
+ bool mLockOnFocusVehTransform;
+ PxTransform mLastFocusVehTransform;
+
+ PxReal mCamDist;
+
+ void update(const PxReal dtime, const PxRigidDynamic* actor, PxScene& scene);
+};
+
+#endif //SAMPLE_VEHICLE_CAMERA_CONTROLLER_H \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.cpp b/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.cpp
new file mode 100644
index 00000000..85ac82ed
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.cpp
@@ -0,0 +1,65 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "VehicleControlInputs.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+VehicleControlInputs::VehicleControlInputs()
+ : mCameraRotateInputY(0.0f),
+ mCameraRotateInputZ(0.0f),
+ mAccelKeyPressed(false),
+ mGearUpKeyPressed(false),
+ mGearDownKeyPressed(false),
+ mBrakeKeyPressed(false),
+ mHandbrakeKeyPressed(false),
+ mSteerLeftKeyPressed(false),
+ mSteerRightKeyPressed(false),
+ mBrakeLeftKeyPressed(false),
+ mBrakeRightKeyPressed(false),
+ mThrustLeftKeyPressed(false),
+ mThrustRightKeyPressed(false),
+ mAccel(0.0f),
+ mGearup(false),
+ mGeardown(false),
+ mBrake(0.0f),
+ mSteer(0.0f),
+ mHandbrake(false),
+ mThrustLeft(0.0f),
+ mThrustRight(0.0f),
+ mBrakeLeft(0.0f),
+ mBrakeRight(0.0f)
+{
+}
+
+VehicleControlInputs::~VehicleControlInputs()
+{
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.h b/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.h
new file mode 100644
index 00000000..c7cc2fb2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleControlInputs.h
@@ -0,0 +1,145 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef VEHICLE_CONTROL_INPUTS_H
+#define VEHICLE_CONTROL_INPUTS_H
+
+#include "common/PxPhysXCommonConfig.h"
+
+using namespace physx;
+
+class VehicleControlInputs
+{
+public:
+
+ VehicleControlInputs();
+ ~VehicleControlInputs();
+
+ //Camera inputs
+ void setRotateY(const PxF32 f) { mCameraRotateInputY = f; }
+ void setRotateZ(const PxF32 f) { mCameraRotateInputZ = f; }
+ PxF32 getRotateY() const { return mCameraRotateInputY; }
+ PxF32 getRotateZ() const { return mCameraRotateInputZ; }
+
+ //Keyboard driving inputs - (car + tank)
+ void setAccelKeyPressed(const bool b) { mAccelKeyPressed = b; }
+ void setGearUpKeyPressed(const bool b) { mGearUpKeyPressed = b; }
+ void setGearDownKeyPressed(const bool b) { mGearDownKeyPressed = b; }
+ bool getAccelKeyPressed() const { return mAccelKeyPressed; }
+ bool getGearUpKeyPressed() const { return mGearUpKeyPressed; }
+ bool getGearDownKeyPressed() const { return mGearDownKeyPressed; }
+
+ //Keyboard driving inputs - (car only)
+ void setBrakeKeyPressed(const bool b) { mBrakeKeyPressed = b; }
+ void setHandbrakeKeyPressed(const bool b) { mHandbrakeKeyPressed = b; }
+ void setSteerLeftKeyPressed(const bool b) { mSteerLeftKeyPressed = b; }
+ void setSteerRightKeyPressed(const bool b) { mSteerRightKeyPressed = b; }
+ bool getBrakeKeyPressed() const { return mBrakeKeyPressed; }
+ bool getHandbrakeKeyPressed() const { return mHandbrakeKeyPressed; }
+ bool getSteerLeftKeyPressed() const { return mSteerLeftKeyPressed; }
+ bool getSteerRightKeyPressed() const { return mSteerRightKeyPressed; }
+
+ //Keyboard driving inputs - (tank only)
+ void setBrakeLeftKeyPressed(const bool b) { mBrakeLeftKeyPressed = b; }
+ void setBrakeRightKeyPressed(const bool b) { mBrakeRightKeyPressed = b; }
+ void setThrustLeftKeyPressed(const bool b) { mThrustLeftKeyPressed = b; }
+ void setThrustRightKeyPressed(const bool b) { mThrustRightKeyPressed = b; }
+ bool getBrakeLeftKeyPressed() const { return mBrakeLeftKeyPressed; }
+ bool getBrakeRightKeyPressed() const { return mBrakeRightKeyPressed; }
+ bool getThrustLeftKeyPressed() const { return mThrustLeftKeyPressed; }
+ bool getThrustRightKeyPressed() const { return mThrustRightKeyPressed; }
+
+ //Gamepad driving inputs (car + tank)
+ void setAccel(const PxF32 f) { mAccel = f; }
+ void setGearUp(const bool b) { mGearup = b; }
+ void setGearDown(const bool b) { mGeardown = b; }
+ PxF32 getAccel() const { return mAccel; }
+ bool getGearUp() const { return mGearup; }
+ bool getGearDown() const { return mGeardown; }
+
+ //Gamepad driving inputs (car only)
+ void setBrake(const PxF32 f) { mBrake = f; }
+ void setSteer(const PxF32 f) { mSteer = f; }
+ void setHandbrake(const bool b) { mHandbrake = b; }
+ PxF32 getBrake() const { return mBrake; }
+ PxF32 getSteer() const { return mSteer; }
+ bool getHandbrake() const { return mHandbrake; }
+
+ //Gamepad driving inputs (tank only)
+ void setThrustLeft(const PxF32 f) { mThrustLeft = f; }
+ void setThrustRight(const PxF32 f) { mThrustRight = f; }
+ PxF32 getThrustLeft() const { return mThrustLeft; }
+ PxF32 getThrustRight() const { return mThrustRight; }
+ void setBrakeLeft(const PxF32 f) { mBrakeLeft = f; }
+ void setBrakeRight(const PxF32 f) { mBrakeRight = f; }
+ PxF32 getBrakeLeft() const { return mBrakeLeft; }
+ PxF32 getBrakeRight() const { return mBrakeRight; }
+
+private:
+
+ //Camera inputs.
+ PxF32 mCameraRotateInputY;
+ PxF32 mCameraRotateInputZ;
+
+ //keyboard inputs (car and tank)
+ bool mAccelKeyPressed;
+ bool mGearUpKeyPressed;
+ bool mGearDownKeyPressed;
+
+ //keyboard inputs (car only)
+ bool mBrakeKeyPressed;
+ bool mHandbrakeKeyPressed;
+ bool mSteerLeftKeyPressed;
+ bool mSteerRightKeyPressed;
+
+ //keyboard inputs (tank only)
+ bool mBrakeLeftKeyPressed;
+ bool mBrakeRightKeyPressed;
+ bool mThrustLeftKeyPressed;
+ bool mThrustRightKeyPressed;
+
+ //gamepad inputs (car and tank)
+ PxF32 mAccel;
+ bool mGearup;
+ bool mGeardown;
+
+ //gamepad inputs (car only)
+ PxF32 mBrake;
+ PxF32 mSteer;
+ bool mHandbrake;
+
+ //gamepad inputs (tank only)
+ PxF32 mThrustLeft;
+ PxF32 mThrustRight;
+ PxF32 mBrakeLeft;
+ PxF32 mBrakeRight;
+};
+
+#endif //VEHICLE_CONTROL_INPUTS_H \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleController.cpp b/KaplaDemo/samples/sampleViewer3/VehicleController.cpp
new file mode 100644
index 00000000..57b42ddc
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleController.cpp
@@ -0,0 +1,808 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "VehicleController.h"
+#include "vehicle/PxVehicleDrive4W.h"
+#include "vehicle/PxVehicleDriveNW.h"
+#include "vehicle/PxVehicleUtilControl.h"
+#include "vehicle/PxVehicleUtil.h"
+#include <stdio.h>
+
+
+PxVehicleKeySmoothingData gKeySmoothingData =
+{
+ {
+ 5.0f, //rise rate eANALOG_INPUT_ACCEL
+ 5.0f, //rise rate eANALOG_INPUT_BRAKE
+ 10.0f, //rise rate eANALOG_INPUT_HANDBRAKE
+ 2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
+ 2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
+ },
+ {
+ 7.0f, //fall rate eANALOG_INPUT__ACCEL
+ 7.0f, //fall rate eANALOG_INPUT__BRAKE
+ 10.0f, //fall rate eANALOG_INPUT__HANDBRAKE
+ 5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
+ 5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
+ }
+};
+
+PxVehiclePadSmoothingData gCarPadSmoothingData =
+{
+ {
+ 6.0f, //rise rate eANALOG_INPUT_ACCEL
+ 6.0f, //rise rate eANALOG_INPUT_BRAKE
+ 12.0f, //rise rate eANALOG_INPUT_HANDBRAKE
+ 2.5f, //rise rate eANALOG_INPUT_STEER_LEFT
+ 2.5f, //rise rate eANALOG_INPUT_STEER_RIGHT
+ },
+ {
+ 10.0f, //fall rate eANALOG_INPUT_ACCEL
+ 10.0f, //fall rate eANALOG_INPUT_BRAKE
+ 12.0f, //fall rate eANALOG_INPUT_HANDBRAKE
+ 5.0f, //fall rate eANALOG_INPUT_STEER_LEFT
+ 5.0f //fall rate eANALOG_INPUT_STEER_RIGHT
+ }
+};
+
+PxF32 gSteerVsForwardSpeedData[2 * 8] =
+{
+ 0.0f, 0.75f,
+ 5.0f, 0.75f,
+ 30.0f, 0.125f,
+ 120.0f, 0.1f,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32,
+ PX_MAX_F32, PX_MAX_F32
+};
+PxFixedSizeLookupTable<8> gSteerVsForwardSpeedTable(gSteerVsForwardSpeedData, 4);
+
+//Tank smoothing data.
+PxVehiclePadSmoothingData gTankPadSmoothingData =
+{
+ {
+ 6.0f, //rise rate eTANK_ANALOG_INPUT_ACCEL
+ 6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_LEFT
+ 6.0f, //rise rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
+ 2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_LEFT
+ 2.5f, //rise rate eTANK_ANALOG_INPUT_THRUST_RIGHT
+ },
+ {
+ 10.0f, //fall rate eTANK_ANALOG_INPUT_ACCEL
+ 10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_LEFT
+ 10.0f, //fall rate eTANK_ANALOG_INPUT_BRAKE_RIGHT
+ 5.0f, //fall rate eTANK_ANALOG_INPUT_THRUST_LEFT
+ 5.0f //fall rate eTANK_ANALOG_INPUT_THRUST_RIGHT
+ }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+VehicleController::VehicleController()
+{
+ clear();
+}
+
+VehicleController::~VehicleController()
+{
+}
+
+void VehicleController::clear()
+{
+ mKeyPressedAccel = false;
+ mKeyPressedGearUp = false;
+ mKeyPressedGearDown = false;
+
+ mKeyPressedBrake = false;
+ mKeyPressedHandbrake = false;
+ mKeyPressedSteerLeft = false;
+ mKeyPressedSteerRight = false;
+
+ mKeyPressedThrustLeft = false;
+ mKeyPressedThrustRight = false;
+ mKeyPressedBrakeLeft = false;
+ mKeyPressedBrakeRight = false;
+
+ mGamepadAccel = 0.0f;
+ mGamepadGearup = false;
+ mGamepadGeardown = false;
+
+ mGamepadCarBrake = 0.0f;
+ mGamepadCarSteer = 0.0f;
+ mGamepadCarHandbrake = false;
+
+ mTankThrustLeft = 0.0f;
+ mTankThrustRight = 0.0f;
+ mTankBrakeLeft = 0.0f;
+ mTankBrakeRight = 0.0f;
+
+ mRecord = false;
+ mReplay = false;
+ mNumSamples = 0;
+ mNumRecordedSamples = 0;
+ mUseKeyInputs = true;
+ mToggleAutoGears = false;
+ mIsMovingForwardSlowly = true;
+ mInReverseMode = false;
+}
+
+
+/*
+bool SampleVehicle_VehicleController::processAutoReverse
+(const PxF32 timestep, const bool isInAir, const PxF32 forwardSpeed, const PxF32 sidewaysSpeed, const PxVehicleDriveTankRawInputData& rawInputData)
+{
+//Keyboard controls for tank not implemented yet.
+bool brakeLeft,brakeRight,accelLeft,accelRight;
+if(mUseKeyInputs)
+{
+//Keyboard controls for tank not implemented yet.
+brakeLeft=false;
+brakeRight=false;
+accelLeft=false;
+accelRight=false;
+}
+else if(PxVehicleDriveTank::eDRIVE_MODEL_STANDARD==rawInputData.getDriveModel())
+{
+brakeLeft = mInReverseMode ? rawInputData.getAnalogLeftThrust() > 0 : rawInputData.getAnalogLeftBrake() > 0.0f;
+brakeRight = mInReverseMode ? rawInputData.getAnalogRightThrust() > 0 : rawInputData.getAnalogRightBrake() > 0.0f;
+accelLeft = mInReverseMode ? rawInputData.getAnalogLeftBrake() > 0 : rawInputData.getAnalogLeftThrust() > 0.0f;
+accelRight = mInReverseMode ? rawInputData.getAnalogRightBrake() > 0 : rawInputData.getAnalogRightThrust() > 0.0f;
+}
+else
+{
+//Not much point in auto-reverse for tanks that can just spin both wheels backwards.
+return false;
+}
+
+//If the car has been brought to rest by pressing the brake then raise a flag.
+bool justRaisedFlag=false;
+if(brakeLeft && brakeRight && !mAtRestUnderBraking)
+{
+if(!isInAir && forwardSpeed < THRESHOLD_FORWARD_SPEED && sidewaysSpeed < THRESHOLD_SIDEWAYS_SPEED)
+{
+justRaisedFlag=true;
+mAtRestUnderBraking = true;
+mTimeElapsedSinceAtRestUnderBraking = 0.0f;
+}
+}
+
+//If the flag is raised and the player pressed accelerate then lower the flag.
+if(mAtRestUnderBraking && (accelLeft || accelRight))
+{
+mAtRestUnderBraking = false;
+mTimeElapsedSinceAtRestUnderBraking = 0.0f;
+}
+
+//If the flag is raised and the player doesn't press brake then increment the timer.
+if(!brakeLeft && !brakeRight && mAtRestUnderBraking && !justRaisedFlag)
+{
+mTimeElapsedSinceAtRestUnderBraking += timestep;
+}
+
+//If the flag is raised and the player pressed brake again then switch auto-reverse.
+if(brakeLeft && brakeRight && mAtRestUnderBraking && !justRaisedFlag && mTimeElapsedSinceAtRestUnderBraking > 0.0f)
+{
+mAtRestUnderBraking = false;
+mTimeElapsedSinceAtRestUnderBraking = 0.0f;
+return true;
+}
+
+return false;
+}
+*/
+
+void VehicleController::processRawInputs
+(const PxF32 dtime, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData)
+{
+ // Keyboard
+ {
+ if (mRecord)
+ {
+ if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
+ {
+ mKeyboardAccelValues[mNumSamples] = mKeyPressedAccel;
+ mKeyboardBrakeValues[mNumSamples] = mKeyPressedBrake;
+ mKeyboardHandbrakeValues[mNumSamples] = mKeyPressedHandbrake;
+ mKeyboardSteerLeftValues[mNumSamples] = mKeyPressedSteerLeft;
+ mKeyboardSteerRightValues[mNumSamples] = mKeyPressedSteerRight;
+ mKeyboardGearupValues[mNumSamples] = mKeyPressedGearUp;
+ mKeyboardGeardownValues[mNumSamples] = mKeyPressedGearDown;
+ }
+ }
+ else if (mReplay)
+ {
+ if (mNumSamples<mNumRecordedSamples)
+ {
+ mKeyPressedAccel = mKeyboardAccelValues[mNumSamples];
+ mKeyPressedBrake = mKeyboardBrakeValues[mNumSamples];
+ mKeyPressedHandbrake = mKeyboardHandbrakeValues[mNumSamples];
+ mKeyPressedSteerLeft = mKeyboardSteerLeftValues[mNumSamples];
+ mKeyPressedSteerRight = mKeyboardSteerRightValues[mNumSamples];
+ mKeyPressedGearUp = mKeyboardGearupValues[mNumSamples];
+ mKeyPressedGearDown = mKeyboardGeardownValues[mNumSamples];
+ }
+ }
+
+ rawInputData.setDigitalAccel(mKeyPressedAccel);
+ rawInputData.setDigitalBrake(mKeyPressedBrake);
+ rawInputData.setDigitalHandbrake(mKeyPressedHandbrake);
+ rawInputData.setDigitalSteerLeft(mKeyPressedSteerLeft);
+ rawInputData.setDigitalSteerRight(mKeyPressedSteerRight);
+ rawInputData.setGearUp(mKeyPressedGearUp);
+ rawInputData.setGearDown(mKeyPressedGearDown);
+
+ mUseKeyInputs =
+ (mKeyPressedAccel || mKeyPressedBrake || mKeyPressedHandbrake ||
+ mKeyPressedSteerLeft || mKeyPressedSteerRight ||
+ mKeyPressedGearUp || mKeyPressedGearDown);
+ }
+
+ // Gamepad
+ {
+ if (mRecord)
+ {
+ if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
+ {
+ mGamepadAccelValues[mNumSamples] = mGamepadAccel;
+ mGamepadCarBrakeValues[mNumSamples] = mGamepadCarBrake;
+ mGamepadCarSteerValues[mNumSamples] = mGamepadCarSteer;
+ mGamepadGearupValues[mNumSamples] = mGamepadGearup;
+ mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
+ mGamepadCarHandbrakeValues[mNumSamples] = mGamepadCarHandbrake;
+ }
+ }
+ else if (mReplay)
+ {
+ if (mNumSamples<mNumRecordedSamples)
+ {
+ mGamepadAccel = mGamepadAccelValues[mNumSamples];
+ mGamepadCarBrake = mGamepadCarBrakeValues[mNumSamples];
+ mGamepadCarSteer = mGamepadCarSteerValues[mNumSamples];
+ mGamepadGearup = mGamepadGearupValues[mNumSamples];
+ mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
+ mGamepadCarHandbrake = mGamepadCarHandbrakeValues[mNumSamples];
+ }
+ }
+
+ if (mGamepadAccel<0.0f || mGamepadAccel>1.01f)
+ printf("Illegal accel value from gamepad!\n");
+
+ if (mGamepadCarBrake<0.0f || mGamepadCarBrake>1.01f)
+ printf("Illegal brake value from gamepad!\n");
+
+ if (PxAbs(mGamepadCarSteer)>1.01f)
+ printf("Illegal steer value from gamepad!\n");
+
+ if (mUseKeyInputs && ((mGamepadAccel + mGamepadCarBrake + mGamepadCarSteer) != 0.0f || mGamepadGearup || mGamepadGeardown || mGamepadCarHandbrake))
+ {
+ mUseKeyInputs = false;
+ }
+
+ if (!mUseKeyInputs)
+ {
+ rawInputData.setAnalogAccel(mGamepadAccel);
+ rawInputData.setAnalogBrake(mGamepadCarBrake);
+ rawInputData.setAnalogHandbrake(mGamepadCarHandbrake ? 1.0f : 0.0f);
+ rawInputData.setAnalogSteer(mGamepadCarSteer);
+ rawInputData.setGearUp(mGamepadGearup);
+ rawInputData.setGearDown(mGamepadGeardown);
+ }
+ }
+
+ if (useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
+ {
+ rawInputData.setGearDown(false);
+ rawInputData.setGearUp(false);
+ }
+
+ mNumSamples++;
+}
+
+void VehicleController::processRawInputs
+(const PxF32 dtime, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData)
+{
+ // Keyboard
+ //Keyboard controls for tank not implemented yet.
+ {
+ /*
+ if(mRecord)
+ {
+ if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
+ {
+ mKeyboardAccelValues[mNumSamples] = mAccelKeyPressed;
+ mKeyboardBrakeValues[mNumSamples] = mBrakeKeyPressed;
+ mKeyboardHandbrakeValues[mNumSamples] = mHandbrakeKeyPressed;
+ mKeyboardSteerLeftValues[mNumSamples] = mSteerLeftKeyPressed;
+ mKeyboardSteerRightValues[mNumSamples] = mSteerRightKeyPressed;
+ mKeyboardGearupValues[mNumSamples] = mGearUpKeyPressed;
+ mKeyboardGeardownValues[mNumSamples] = mGearDownKeyPressed;
+ }
+ }
+ else if(mReplay)
+ {
+ if(mNumSamples<mNumRecordedSamples)
+ {
+ mAccelKeyPressed = mKeyboardAccelValues[mNumSamples];
+ mBrakeKeyPressed = mKeyboardBrakeValues[mNumSamples];
+ mHandbrakeKeyPressed = mKeyboardHandbrakeValues[mNumSamples];
+ mSteerLeftKeyPressed = mKeyboardSteerLeftValues[mNumSamples];
+ mSteerRightKeyPressed = mKeyboardSteerRightValues[mNumSamples];
+ mGearUpKeyPressed = mKeyboardGearupValues[mNumSamples];
+ mGearDownKeyPressed = mKeyboardGeardownValues[mNumSamples];
+ }
+ }
+ */
+
+ rawInputData.setDigitalAccel(mKeyPressedAccel);
+ rawInputData.setDigitalLeftThrust(mKeyPressedThrustLeft);
+ rawInputData.setDigitalRightThrust(mKeyPressedThrustRight);
+ rawInputData.setDigitalLeftBrake(mKeyPressedBrakeLeft);
+ rawInputData.setDigitalRightBrake(mKeyPressedBrakeRight);
+ rawInputData.setGearUp(mKeyPressedGearUp);
+ rawInputData.setGearDown(mKeyPressedGearDown);
+
+ mUseKeyInputs =
+ (mKeyPressedAccel || mKeyPressedThrustLeft || mKeyPressedThrustRight ||
+ mKeyPressedBrakeLeft || mKeyPressedBrakeRight ||
+ mKeyPressedGearUp || mKeyPressedGearDown);
+ }
+
+
+ // Gamepad
+ {
+ if (mRecord)
+ {
+ if (mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES)
+ {
+ mGamepadAccelValues[mNumSamples] = mGamepadAccel;
+ mGamepadTankThrustLeftValues[mNumSamples] = mTankThrustLeft;
+ mGamepadTankThrustRightValues[mNumSamples] = mTankThrustRight;
+ mGamepadGearupValues[mNumSamples] = mGamepadGearup;
+ mGamepadGeardownValues[mNumSamples] = mGamepadGeardown;
+ }
+ }
+ else if (mReplay)
+ {
+ if (mNumSamples<mNumRecordedSamples)
+ {
+ mGamepadAccel = mGamepadAccelValues[mNumSamples];
+ mTankThrustLeft = mGamepadTankThrustLeftValues[mNumSamples];
+ mTankThrustRight = mGamepadTankThrustRightValues[mNumSamples];
+ mGamepadGearup = mGamepadGearupValues[mNumSamples];
+ mGamepadGeardown = mGamepadGeardownValues[mNumSamples];
+ }
+ }
+
+ if (mGamepadAccel<0.0f || mGamepadAccel>1.01f)
+ printf("Illegal accel value from gamepad!\n");
+
+ if (mTankThrustLeft<-1.01f || mTankThrustLeft>1.01f)
+ printf("Illegal brake value from gamepad!\n");
+
+ if (mTankThrustRight<-1.01f || mTankThrustRight>1.01f)
+ printf("Illegal steer value from gamepad\n");
+
+ if (mUseKeyInputs && ((mGamepadAccel + mTankThrustLeft + mTankThrustRight) != 0.0f || mGamepadGearup || mGamepadGeardown))
+ {
+ mUseKeyInputs = false;
+ }
+
+ if (!mUseKeyInputs)
+ {
+ rawInputData.setAnalogAccel(mGamepadAccel);
+ rawInputData.setAnalogLeftThrust(mTankThrustLeft);
+ rawInputData.setAnalogRightThrust(mTankThrustRight);
+ rawInputData.setAnalogLeftBrake(mTankBrakeLeft);
+ rawInputData.setAnalogRightBrake(mTankBrakeRight);
+ rawInputData.setGearUp(mGamepadGearup);
+ rawInputData.setGearDown(mGamepadGeardown);
+ }
+ }
+
+ if (useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp()))
+ {
+ rawInputData.setGearDown(false);
+ rawInputData.setGearUp(false);
+ }
+
+ mNumSamples++;
+}
+
+#define THRESHOLD_FORWARD_SPEED (0.1f)
+#define THRESHOLD_SIDEWAYS_SPEED (0.2f)
+#define THRESHOLD_ROLLING_BACKWARDS_SPEED (0.1f)
+
+void VehicleController::processAutoReverse
+(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
+const PxVehicleDrive4WRawInputData& carRawInputs,
+bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
+{
+ newIsMovingForwardSlowly = false;
+ toggleAutoReverse = false;
+
+ if (driveDynData.getUseAutoGears())
+ {
+ //If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
+ //If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
+ //If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
+ //If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
+ //(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
+ //to indicate they want to toggle between forward and reverse.)
+
+ const bool prevIsMovingForwardSlowly = mIsMovingForwardSlowly;
+ bool isMovingForwardSlowly = false;
+ bool isMovingBackwards = false;
+ const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
+ if (!isInAir)
+ {
+ bool accelRaw, brakeRaw, handbrakeRaw;
+ if (mUseKeyInputs)
+ {
+ accelRaw = carRawInputs.getDigitalAccel();
+ brakeRaw = carRawInputs.getDigitalBrake();
+ handbrakeRaw = carRawInputs.getDigitalHandbrake();
+ }
+ else
+ {
+ accelRaw = carRawInputs.getAnalogAccel() > 0 ? true : false;
+ brakeRaw = carRawInputs.getAnalogBrake() > 0 ? true : false;
+ handbrakeRaw = carRawInputs.getAnalogHandbrake() > 0 ? true : false;
+ }
+
+ const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
+ const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
+ const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
+ const PxU32 currentGear = driveDynData.getCurrentGear();
+ const PxU32 targetGear = driveDynData.getTargetGear();
+
+ //Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
+ if (PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
+ {
+ isMovingBackwards = true;
+ }
+ else if (PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
+ {
+ isMovingBackwards = true;
+ }
+
+ //Check if the car is moving slowly.
+ if (forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
+ {
+ isMovingForwardSlowly = true;
+ }
+
+ //Now work if we need to toggle from forwards gear to reverse gear or vice versa.
+ if (isMovingBackwards)
+ {
+ if (!accelRaw && !brakeRaw && !handbrakeRaw && (currentGear == targetGear))
+ {
+ //The car is rolling against the gear and the player is doing nothing to stop this.
+ toggleAutoReverse = true;
+ }
+ }
+ else if (prevIsMovingForwardSlowly && isMovingForwardSlowly)
+ {
+ if ((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeRaw && !accelRaw && (currentGear == targetGear))
+ {
+ //The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
+ //player wants to switch to reverse gear.
+ toggleAutoReverse = true;
+ }
+ else if (currentGear == PxVehicleGearsData::eREVERSE && accelRaw && !brakeRaw && (currentGear == targetGear))
+ {
+ //The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
+ //player wants to switch to forward gear.
+ toggleAutoReverse = true;
+ }
+ }
+
+ //If the car was brought to rest through braking and the player is still braking then start the process that will lead to toggling
+ //between reverse and forward gears.
+ if (isMovingForwardSlowly)
+ {
+ if (currentGear >= PxVehicleGearsData::eFIRST && brakeRaw)
+ {
+ newIsMovingForwardSlowly = true;
+ }
+ else if (currentGear == PxVehicleGearsData::eREVERSE && accelRaw)
+ {
+ newIsMovingForwardSlowly = true;
+ }
+ }
+ }
+ }
+}
+
+void VehicleController::processAutoReverse
+(const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
+const PxVehicleDriveTankRawInputData& tankRawInputs,
+bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const
+{
+ newIsMovingForwardSlowly = false;
+ toggleAutoReverse = false;
+
+ if (driveDynData.getUseAutoGears())
+ {
+ //If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear
+ //If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear
+ //If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear.
+ //If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear.
+ //(If the player brings the car to rest with the brake the player needs to release the brake then reapply it
+ //to indicate they want to toggle between forward and reverse.)
+
+ const bool prevIsMovingForwardSlowly = mIsMovingForwardSlowly;
+ bool isMovingForwardSlowly = false;
+ bool isMovingBackwards = false;
+ const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
+ if (!isInAir)
+ {
+ bool accelLeft, accelRight, brakeLeft, brakeRight;
+ if (mUseKeyInputs)
+ {
+ accelLeft = tankRawInputs.getDigitalLeftThrust();
+ accelRight = tankRawInputs.getDigitalRightThrust();
+ brakeLeft = tankRawInputs.getDigitalLeftBrake();
+ brakeRight = tankRawInputs.getDigitalRightBrake();
+ }
+ else
+ {
+ accelLeft = tankRawInputs.getAnalogLeftThrust() > 0 ? true : false;
+ accelRight = tankRawInputs.getAnalogRightThrust() > 0 ? true : false;
+ brakeLeft = tankRawInputs.getAnalogLeftBrake() > 0 ? true : false;
+ brakeRight = tankRawInputs.getAnalogRightBrake() > 0 ? true : false;
+
+ /*
+ if(accelLeft && accelLeft==accelRight && !brakeLeft && !brakeRight)
+ {
+ shdfnd::printFormatted("aligned accel\n");
+ }
+
+ if(brakeLeft && brakeLeft==brakeRight && !accelLeft && !accelRight)
+ {
+ shdfnd::printFormatted("aligned brake\n");
+ }
+ */
+
+ }
+
+ const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed();
+ const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed);
+ const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed());
+ const PxU32 currentGear = driveDynData.getCurrentGear();
+ const PxU32 targetGear = driveDynData.getTargetGear();
+
+ //Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear).
+ if (PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED)
+ {
+ isMovingBackwards = true;
+ }
+ else if (PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED)
+ {
+ isMovingBackwards = true;
+ }
+
+ //Check if the car is moving slowly.
+ if (forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED)
+ {
+ isMovingForwardSlowly = true;
+ }
+
+ //Now work if we need to toggle from forwards gear to reverse gear or vice versa.
+ if (isMovingBackwards)
+ {
+ if (!accelLeft && !accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
+ {
+ //The car is rolling against the gear and the player is doing nothing to stop this.
+ toggleAutoReverse = true;
+ }
+ }
+ else if (prevIsMovingForwardSlowly && isMovingForwardSlowly)
+ {
+ if ((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeLeft && brakeRight && !accelLeft && !accelRight && (currentGear == targetGear))
+ {
+ //The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the
+ //player wants to switch to reverse gear.
+ toggleAutoReverse = true;
+ }
+ else if (currentGear == PxVehicleGearsData::eREVERSE && accelLeft && accelRight && !brakeLeft && !brakeRight && (currentGear == targetGear))
+ {
+ //The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the
+ //player wants to switch to forward gear.
+ toggleAutoReverse = true;
+ }
+ }
+
+ //If the car was brought to rest through braking then the player needs to release the brake then reapply
+ //to indicate that the gears should toggle between reverse and forward.
+ if (isMovingForwardSlowly && (!brakeLeft || !brakeRight) && (!accelLeft || !accelRight))
+ {
+ newIsMovingForwardSlowly = true;
+ }
+ }
+ }
+}
+
+void VehicleController::update(const PxF32 timestep, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle)
+{
+ PxVehicleDriveDynData* driveDynData = NULL;
+ bool isTank = false;
+ PxVehicleDriveTankControlModel::Enum tankDriveModel = PxVehicleDriveTankControlModel::eSTANDARD;
+ switch (focusVehicle.getVehicleType())
+ {
+ case PxVehicleTypes::eDRIVE4W:
+ {
+ PxVehicleDrive4W& vehDrive4W = (PxVehicleDrive4W&)focusVehicle;
+ driveDynData = &vehDrive4W.mDriveDynData;
+ isTank = false;
+ }
+ break;
+ case PxVehicleTypes::eDRIVENW:
+ {
+ PxVehicleDriveNW& vehDriveNW = (PxVehicleDriveNW&)focusVehicle;
+ driveDynData = &vehDriveNW.mDriveDynData;
+ isTank = false;
+ }
+ break;
+ case PxVehicleTypes::eDRIVETANK:
+ {
+ PxVehicleDriveTank& vehDriveTank = (PxVehicleDriveTank&)focusVehicle;
+ driveDynData = &vehDriveTank.mDriveDynData;
+ isTank = true;
+ tankDriveModel = vehDriveTank.getDriveModel();
+ }
+ break;
+ default:
+ PX_ASSERT(false);
+ break;
+ }
+
+ //Toggle autogear flag
+ if (mToggleAutoGears)
+ {
+ driveDynData->toggleAutoGears();
+ mToggleAutoGears = false;
+ }
+
+ //Store raw inputs in replay stream if in recording mode.
+ //Set raw inputs from replay stream if in replay mode.
+ //Store raw inputs from active stream in handy arrays so we don't need to worry
+ //about which stream (live input or replay) is active.
+ //Work out if we are using keys or gamepad controls depending on which is being used
+ //(gamepad selected if both are being used).
+ PxVehicleDrive4WRawInputData carRawInputs;
+ PxVehicleDriveTankRawInputData tankRawInputs(tankDriveModel);
+
+ processRawInputs(timestep, driveDynData->getUseAutoGears(), carRawInputs);
+
+
+ //Work out if the car is to flip from reverse to forward gear or from forward gear to reverse.
+ bool toggleAutoReverse = false;
+ bool newIsMovingForwardSlowly = false;
+
+ processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, carRawInputs, toggleAutoReverse, newIsMovingForwardSlowly);
+
+ mIsMovingForwardSlowly = newIsMovingForwardSlowly;
+
+
+ //If the car is to flip gear direction then switch gear as appropriate.
+ if (toggleAutoReverse)
+ {
+ mInReverseMode = !mInReverseMode;
+
+ if (mInReverseMode)
+ {
+ driveDynData->forceGearChange(PxVehicleGearsData::eREVERSE);
+ }
+ else
+ {
+ driveDynData->forceGearChange(PxVehicleGearsData::eFIRST);
+ }
+ }
+
+ //If in reverse mode then swap the accel and brake.
+ if (mInReverseMode)
+ {
+ if (mUseKeyInputs)
+ {
+ const bool accel = carRawInputs.getDigitalAccel();
+ const bool brake = carRawInputs.getDigitalBrake();
+ carRawInputs.setDigitalAccel(brake);
+ carRawInputs.setDigitalBrake(accel);
+ }
+ else
+ {
+ if (!isTank)
+ {
+ const PxF32 accel = carRawInputs.getAnalogAccel();
+ const PxF32 brake = carRawInputs.getAnalogBrake();
+ carRawInputs.setAnalogAccel(brake);
+ carRawInputs.setAnalogBrake(accel);
+ }
+ else if (PxVehicleDriveTankControlModel::eSPECIAL == tankDriveModel)
+ {
+ const PxF32 thrustLeft = tankRawInputs.getAnalogLeftThrust();
+ const PxF32 thrustRight = tankRawInputs.getAnalogRightThrust();
+ tankRawInputs.setAnalogLeftThrust(-thrustLeft);
+ tankRawInputs.setAnalogRightThrust(-thrustRight);
+ }
+ else
+ {
+ const PxF32 thrustLeft = tankRawInputs.getAnalogLeftThrust();
+ const PxF32 thrustRight = tankRawInputs.getAnalogRightThrust();
+ const PxF32 brakeLeft = tankRawInputs.getAnalogLeftBrake();
+ const PxF32 brakeRight = tankRawInputs.getAnalogRightBrake();
+ tankRawInputs.setAnalogLeftThrust(brakeLeft);
+ tankRawInputs.setAnalogLeftBrake(thrustLeft);
+ tankRawInputs.setAnalogRightThrust(brakeRight);
+ tankRawInputs.setAnalogRightBrake(thrustRight);
+ }
+ }
+ }
+
+ // Now filter the raw input values and apply them to focus vehicle
+ // as floats for brake,accel,handbrake,steer and bools for gearup,geardown.
+ if (mUseKeyInputs)
+ {
+
+ const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
+ PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs
+ (gKeySmoothingData, gSteerVsForwardSpeedTable, carRawInputs, timestep, isInAir, (PxVehicleDrive4W&)focusVehicle);
+
+ }
+ else
+ {
+
+ const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults);
+ PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs
+ (gCarPadSmoothingData, gSteerVsForwardSpeedTable, carRawInputs, timestep, isInAir, (PxVehicleDrive4W&)focusVehicle);
+
+ }
+}
+
+void VehicleController::restart()
+{
+ const bool record = mRecord;
+ const bool replay = mReplay;
+ const PxU32 numSamples = mNumSamples;
+ const PxU32 numRecordedSamples = mNumRecordedSamples;
+ clear();
+ mRecord = record;
+ mReplay = replay;
+ mNumRecordedSamples = numRecordedSamples;
+
+ if (record)
+ {
+ PX_ASSERT(!replay);
+ mNumRecordedSamples = numSamples;
+ mRecord = false;
+ mReplay = true;
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleController.h b/KaplaDemo/samples/sampleViewer3/VehicleController.h
new file mode 100644
index 00000000..b8456e2f
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleController.h
@@ -0,0 +1,226 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef VEHICLE_CONTROLLER_H
+#define VEHICLE_CONTROLLER_H
+
+#include "common/PxPhysXCommonConfig.h"
+#include "foundation/PxVec3.h"
+#include "vehicle/PxVehicleSDK.h"
+#include "vehicle/PxVehicleUpdate.h"
+#include "vehicle/PxVehicleUtilControl.h"
+
+using namespace physx;
+
+class VehicleController
+{
+public:
+
+ VehicleController();
+ ~VehicleController();
+
+ void setCarKeyboardInputs
+ (const bool accel, const bool brake, const bool handbrake,
+ const bool steerleft, const bool steerright,
+ const bool gearup, const bool geardown)
+ {
+ mKeyPressedAccel = accel;
+ mKeyPressedBrake = brake;
+ mKeyPressedHandbrake = handbrake;
+ mKeyPressedSteerLeft = steerleft;
+ mKeyPressedSteerRight = steerright;
+ mKeyPressedGearUp = gearup;
+ mKeyPressedGearDown = geardown;
+ }
+
+ void setCarGamepadInputs
+ (const PxF32 accel, const PxF32 brake,
+ const PxF32 steer,
+ const bool gearup, const bool geardown,
+ const bool handbrake)
+ {
+ mGamepadAccel = accel;
+ mGamepadCarBrake = brake;
+ mGamepadCarSteer = steer;
+ mGamepadGearup = gearup;
+ mGamepadGeardown = geardown;
+ mGamepadCarHandbrake = handbrake;
+ }
+
+ void setTankKeyboardInputs
+ (const bool accel, const bool thrustLeft, const bool thrustRight, const bool brakeLeft, const bool brakeRight, const bool gearUp, const bool gearDown)
+ {
+ mKeyPressedAccel = accel;
+ mKeyPressedThrustLeft = thrustLeft;
+ mKeyPressedThrustRight = thrustRight;
+ mKeyPressedBrakeLeft = brakeLeft;
+ mKeyPressedBrakeRight = brakeRight;
+ mKeyPressedGearUp = gearUp;
+ mKeyPressedGearDown = gearDown;
+ }
+
+ void setTankGamepadInputs
+ (const PxF32 accel, const PxF32 thrustLeft, const PxF32 thrustRight, const PxF32 brakeLeft, const PxF32 brakeRight, const bool gearUp, const bool gearDown)
+ {
+ mGamepadAccel = accel;
+ mTankThrustLeft = thrustLeft;
+ mTankThrustRight = thrustRight;
+ mTankBrakeLeft = brakeLeft;
+ mTankBrakeRight = brakeRight;
+ mGamepadGearup = gearUp;
+ mGamepadGeardown = gearDown;
+ }
+
+ void toggleAutoGearFlag()
+ {
+ mToggleAutoGears = true;
+ }
+
+ void update(const PxF32 dtime, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle);
+
+ void clear();
+
+private:
+
+ //Raw driving inputs - keys (car + tank)
+ bool mKeyPressedAccel;
+ bool mKeyPressedGearUp;
+ bool mKeyPressedGearDown;
+
+ //Raw driving inputs - keys (car only)
+ bool mKeyPressedBrake;
+ bool mKeyPressedHandbrake;
+ bool mKeyPressedSteerLeft;
+ bool mKeyPressedSteerRight;
+
+ //Raw driving inputs - keys (tank only)
+ bool mKeyPressedThrustLeft;
+ bool mKeyPressedThrustRight;
+ bool mKeyPressedBrakeLeft;
+ bool mKeyPressedBrakeRight;
+
+ //Raw driving inputs - gamepad (car + tank)
+ PxF32 mGamepadAccel;
+ bool mGamepadGearup;
+ bool mGamepadGeardown;
+
+ //Raw driving inputs - gamepad (car only)
+ PxF32 mGamepadCarBrake;
+ PxF32 mGamepadCarSteer;
+ bool mGamepadCarHandbrake;
+
+ //Raw driving inputs - (tank only)
+ PxF32 mTankThrustLeft;
+ PxF32 mTankThrustRight;
+ PxF32 mTankBrakeLeft;
+ PxF32 mTankBrakeRight;
+
+ //Record and replay using raw driving inputs.
+ bool mRecord;
+ bool mReplay;
+ enum
+ {
+ MAX_NUM_RECORD_REPLAY_SAMPLES = 8192
+ };
+ // Keyboard
+ bool mKeyboardAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardSteerLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardSteerRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mKeyboardGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ // Gamepad - (tank + car)
+ PxF32 mGamepadAccelValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mGamepadGearupValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mGamepadGeardownValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ // Gamepad - car only
+ PxF32 mGamepadCarBrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ PxF32 mGamepadCarSteerValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ bool mGamepadCarHandbrakeValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ //Gamepad - tank only.
+ PxF32 mGamepadTankThrustLeftValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+ PxF32 mGamepadTankThrustRightValues[MAX_NUM_RECORD_REPLAY_SAMPLES];
+
+ PxU32 mNumSamples;
+ PxU32 mNumRecordedSamples;
+
+ // Raw data taken from the correct stream (live input stream or replay stream)
+ bool mUseKeyInputs;
+
+ // Toggle autogears flag on focus vehicle
+ bool mToggleAutoGears;
+
+ //Auto-reverse mode.
+ bool mIsMovingForwardSlowly;
+ bool mInReverseMode;
+
+ //Update
+ void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData);
+ void processRawInputs(const PxF32 timestep, const bool useAutoGears, PxVehicleDriveTankRawInputData& rawInputData);
+ void processAutoReverse(
+ const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
+ const PxVehicleDrive4WRawInputData& rawInputData,
+ bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
+ void processAutoReverse(
+ const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleWheelQueryResult& vehicleWheelQueryResults,
+ const PxVehicleDriveTankRawInputData& rawInputData,
+ bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const;
+
+ ////////////////////////////////
+ //Record and replay deprecated at the moment.
+ //Setting functions as private to avoid them being used.
+ ///////////////////////////////
+ bool getIsInRecordReplayMode() const { return (mRecord || mReplay); }
+ bool getIsRecording() const { return mRecord; }
+ bool getIsReplaying() const { return mReplay; }
+
+ void enableRecordReplayMode()
+ {
+ PX_ASSERT(!getIsInRecordReplayMode());
+ mRecord = true;
+ mReplay = false;
+ mNumRecordedSamples = 0;
+ }
+
+ void disableRecordReplayMode()
+ {
+ PX_ASSERT(getIsInRecordReplayMode());
+ mRecord = false;
+ mReplay = false;
+ mNumRecordedSamples = 0;
+ }
+
+ void restart();
+ ////////////////////////////
+
+};
+
+#endif //VehicleController \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleManager.cpp b/KaplaDemo/samples/sampleViewer3/VehicleManager.cpp
new file mode 100644
index 00000000..ee0b2624
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleManager.cpp
@@ -0,0 +1,473 @@
+
+#include "SceneVehicleSceneQuery.h"
+#include "VehicleManager.h"
+#include "VehicleWheelQueryResults.h"
+#include "vehicle/PxVehicleUtilSetup.h"
+#include "PxRigidActorExt.h"
+#include "PxSceneLock.h"
+#include "PxD6Joint.h"
+
+
+VehicleManager::VehicleManager() : mSqWheelRaycastBatchQuery(NULL)
+{
+
+}
+
+VehicleManager::~VehicleManager()
+{
+ PxCloseVehicleSDK();
+}
+
+void VehicleManager::init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes)
+{
+ //Initialise the sdk.
+ PxInitVehicleSDK(physics, NULL);
+
+ //Set the basis vectors.
+ PxVec3 up(0, 1, 0);
+ PxVec3 forward(0, 0, 1);
+ PxVehicleSetBasisVectors(up, forward);
+
+ //Set the vehicle update mode to be immediate velocity changes.
+ PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
+
+ //Initialise vehicle ptrs to null.
+ mVehicle = NULL;
+
+ //Allocate simulation data so we can switch from 3-wheeled to 4-wheeled cars by switching simulation data.
+ mWheelsSimData4W = PxVehicleWheelsSimData::allocate(4);
+
+ //Scene query data for to allow raycasts for all suspensions of all vehicles.
+ mSqData = VehicleSceneQueryData::allocate(4);
+
+ //Data to store reports for each wheel.
+ mWheelQueryResults = VehicleWheelQueryResults::allocate(4);
+
+ //Set up the friction values arising from combinations of tire type and surface type.
+ mSurfaceTirePairs = PxVehicleDrivableSurfaceToTireFrictionPairs::allocate(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES);
+ mSurfaceTirePairs->setup(MAX_NUM_TIRE_TYPES, MAX_NUM_SURFACE_TYPES, drivableSurfaceMaterials, drivableSurfaceTypes);
+ for (PxU32 i = 0; i<MAX_NUM_SURFACE_TYPES; i++)
+ {
+ for (PxU32 j = 0; j<MAX_NUM_TIRE_TYPES; j++)
+ {
+ mSurfaceTirePairs->setTypePairFriction(i, j, 1.3f*TireFrictionMultipliers::getValue(i, j));
+ }
+ }
+
+}
+
+void VehicleManager::computeWheelWidthsAndRadii(PxConvexMesh** wheelConvexMeshes, PxF32* wheelWidths, PxF32* wheelRadii)
+{
+ for (PxU32 i = 0; i<4; i++)
+ {
+ const PxU32 numWheelVerts = wheelConvexMeshes[i]->getNbVertices();
+ const PxVec3* wheelVerts = wheelConvexMeshes[i]->getVertices();
+ PxVec3 wheelMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
+ PxVec3 wheelMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
+ for (PxU32 j = 0; j<numWheelVerts; j++)
+ {
+ wheelMin.x = PxMin(wheelMin.x, wheelVerts[j].x);
+ wheelMin.y = PxMin(wheelMin.y, wheelVerts[j].y);
+ wheelMin.z = PxMin(wheelMin.z, wheelVerts[j].z);
+ wheelMax.x = PxMax(wheelMax.x, wheelVerts[j].x);
+ wheelMax.y = PxMax(wheelMax.y, wheelVerts[j].y);
+ wheelMax.z = PxMax(wheelMax.z, wheelVerts[j].z);
+ }
+ wheelWidths[i] = wheelMax.x - wheelMin.x;
+ wheelRadii[i] = PxMax(wheelMax.y, wheelMax.z)*0.975f;
+ }
+}
+
+PxVec3 VehicleManager::computeChassisAABBDimensions(const PxConvexMesh* chassisConvexMesh)
+{
+ const PxU32 numChassisVerts = chassisConvexMesh->getNbVertices();
+ const PxVec3* chassisVerts = chassisConvexMesh->getVertices();
+ PxVec3 chassisMin(PX_MAX_F32, PX_MAX_F32, PX_MAX_F32);
+ PxVec3 chassisMax(-PX_MAX_F32, -PX_MAX_F32, -PX_MAX_F32);
+ for (PxU32 i = 0; i<numChassisVerts; i++)
+ {
+ chassisMin.x = PxMin(chassisMin.x, chassisVerts[i].x);
+ chassisMin.y = PxMin(chassisMin.y, chassisVerts[i].y);
+ chassisMin.z = PxMin(chassisMin.z, chassisVerts[i].z);
+ chassisMax.x = PxMax(chassisMax.x, chassisVerts[i].x);
+ chassisMax.y = PxMax(chassisMax.y, chassisVerts[i].y);
+ chassisMax.z = PxMax(chassisMax.z, chassisVerts[i].z);
+ }
+ const PxVec3 chassisDims = chassisMax - chassisMin;
+ return chassisDims;
+}
+
+void VehicleManager::createVehicle4WSimulationData(const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes,
+ const PxVec3* wheelCentreOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData)
+{
+ //Extract the chassis AABB dimensions from the chassis convex mesh.
+ const PxVec3 chassisDims = computeChassisAABBDimensions(chassisConvexMesh);
+
+ //The origin is at the center of the chassis mesh.
+ //Set the center of mass to be below this point and a little towards the front.
+ const PxVec3 chassisCMOffset = PxVec3(0.0f, -chassisDims.y*0.5f + 0.65f, 0.25f);
+
+ //Now compute the chassis mass and moment of inertia.
+ //Use the moment of inertia of a cuboid as an approximate value for the chassis moi.
+ PxVec3 chassisMOI
+ ((chassisDims.y*chassisDims.y + chassisDims.z*chassisDims.z)*chassisMass / 12.0f,
+ (chassisDims.x*chassisDims.x + chassisDims.z*chassisDims.z)*chassisMass / 12.0f,
+ (chassisDims.x*chassisDims.x + chassisDims.y*chassisDims.y)*chassisMass / 12.0f);
+ //A bit of tweaking here. The car will have more responsive turning if we reduce the
+ //y-component of the chassis moment of inertia.
+ chassisMOI.y *= 0.8f;
+
+ //Let's set up the chassis data structure now.
+ chassisData.mMass = chassisMass;
+ chassisData.mMOI = chassisMOI;
+ chassisData.mCMOffset = chassisCMOffset;
+
+ //Compute the sprung masses of each suspension spring using a helper function.
+ PxF32 suspSprungMasses[4];
+ PxVehicleComputeSprungMasses(4, wheelCentreOffsets, chassisCMOffset, chassisMass, 1, suspSprungMasses);
+
+ //Extract the wheel radius and width from the wheel convex meshes.
+ PxF32 wheelWidths[4];
+ PxF32 wheelRadii[4];
+ computeWheelWidthsAndRadii(wheelConvexMeshes, wheelWidths, wheelRadii);
+
+ //Now compute the wheel masses and inertias components around the axle's axis.
+ //http://en.wikipedia.org/wiki/List_of_moments_of_inertia
+ PxF32 wheelMOIs[4];
+ for (PxU32 i = 0; i<4; i++)
+ {
+ wheelMOIs[i] = 0.5f*wheelMass*wheelRadii[i] * wheelRadii[i];
+ }
+ //Let's set up the wheel data structures now with radius, mass, and moi.
+ PxVehicleWheelData wheels[4];
+ for (PxU32 i = 0; i<4; i++)
+ {
+ wheels[i].mRadius = wheelRadii[i];
+ wheels[i].mMass = wheelMass;
+ wheels[i].mMOI = wheelMOIs[i];
+ wheels[i].mWidth = wheelWidths[i];
+ }
+ //Disable the handbrake from the front wheels and enable for the rear wheels
+ wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxHandBrakeTorque = 0.0f;
+ wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxHandBrakeTorque = 0.0f;
+ wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxHandBrakeTorque = 4000.0f;
+ wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxHandBrakeTorque = 4000.0f;
+ //Enable steering for the front wheels and disable for the front wheels.
+ wheels[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mMaxSteer = PxPi*0.3333f;
+ wheels[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mMaxSteer = PxPi*0.3333f;
+ wheels[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mMaxSteer = 0.0f;
+ wheels[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mMaxSteer = 0.0f;
+
+ //Let's set up the tire data structures now.
+ //Put slicks on the front tires and wets on the rear tires.
+ PxVehicleTireData tires[4];
+ tires[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mType = TIRE_TYPE_SLICKS;
+ tires[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mType = TIRE_TYPE_SLICKS;
+ tires[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mType = TIRE_TYPE_WETS;
+ tires[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mType = TIRE_TYPE_WETS;
+
+ //Let's set up the suspension data structures now.
+ PxVehicleSuspensionData susps[4];
+ for (PxU32 i = 0; i<4; i++)
+ {
+ susps[i].mMaxCompression = 0.3f;
+ susps[i].mMaxDroop = 0.1f;
+ susps[i].mSpringStrength = 35000.0f;
+ susps[i].mSpringDamperRate = 4500.0f;
+ }
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_LEFT];
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT];
+ susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_LEFT];
+ susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mSprungMass = suspSprungMasses[PxVehicleDrive4WWheelOrder::eREAR_RIGHT];
+
+ //Set up the camber.
+ //Remember that the left and right wheels need opposite camber so that the car preserves symmetry about the forward direction.
+ //Set the camber to 0.0f when the spring is neither compressed or elongated.
+ const PxF32 camberAngleAtRest = 0.0;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtRest = camberAngleAtRest;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtRest = -camberAngleAtRest;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtRest = camberAngleAtRest;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtRest = -camberAngleAtRest;
+ //Set the wheels to camber inwards at maximum droop (the left and right wheels almost form a V shape)
+ const PxF32 camberAngleAtMaxDroop = 0.001f;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxDroop = camberAngleAtMaxDroop;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxDroop = -camberAngleAtMaxDroop;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxDroop = camberAngleAtMaxDroop;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxDroop = -camberAngleAtMaxDroop;
+ //Set the wheels to camber outwards at maximum compression (the left and right wheels almost form a A shape).
+ const PxF32 camberAngleAtMaxCompression = -0.001f;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].mCamberAtMaxCompression = camberAngleAtMaxCompression;
+ susps[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].mCamberAtMaxCompression = -camberAngleAtMaxCompression;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_LEFT].mCamberAtMaxCompression = camberAngleAtMaxCompression;
+ susps[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].mCamberAtMaxCompression = -camberAngleAtMaxCompression;
+
+ //We need to set up geometry data for the suspension, wheels, and tires.
+ //We already know the wheel centers described as offsets from the actor center and the center of mass offset from actor center.
+ //From here we can approximate application points for the tire and suspension forces.
+ //Lets assume that the suspension travel directions are absolutely vertical.
+ //Also assume that we apply the tire and suspension forces 30cm below the center of mass.
+ PxVec3 suspTravelDirections[4] = { PxVec3(0, -1, 0), PxVec3(0, -1, 0), PxVec3(0, -1, 0), PxVec3(0, -1, 0) };
+ PxVec3 wheelCentreCMOffsets[4];
+ PxVec3 suspForceAppCMOffsets[4];
+ PxVec3 tireForceAppCMOffsets[4];
+ for (PxU32 i = 0; i<4; i++)
+ {
+ wheelCentreCMOffsets[i] = wheelCentreOffsets[i] - chassisCMOffset;
+ suspForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z);
+ tireForceAppCMOffsets[i] = PxVec3(wheelCentreCMOffsets[i].x, -0.3f, wheelCentreCMOffsets[i].z);
+ }
+
+ //Now add the wheel, tire and suspension data.
+ for (PxU32 i = 0; i<4; i++)
+ {
+ wheelsData.setWheelData(i, wheels[i]);
+ wheelsData.setTireData(i, tires[i]);
+ wheelsData.setSuspensionData(i, susps[i]);
+ wheelsData.setSuspTravelDirection(i, suspTravelDirections[i]);
+ wheelsData.setWheelCentreOffset(i, wheelCentreCMOffsets[i]);
+ wheelsData.setSuspForceAppPointOffset(i, suspForceAppCMOffsets[i]);
+ wheelsData.setTireForceAppPointOffset(i, tireForceAppCMOffsets[i]);
+ }
+
+ //Set the car to perform 3 sub-steps when it moves with a forwards speed of less than 5.0
+ //and with a single step when it moves at speed greater than or equal to 5.0.
+ wheelsData.setSubStepCount(5.0f, 5, 5);
+
+
+ //Now set up the differential, engine, gears, clutch, and ackermann steering.
+
+ //Diff
+ PxVehicleDifferential4WData diff;
+ diff.mType = PxVehicleDifferential4WData::eDIFF_TYPE_LS_4WD;
+ driveData.setDiffData(diff);
+
+ //Engine
+ PxVehicleEngineData engine;
+ engine.mPeakTorque = 1500.0f;
+ engine.mMaxOmega = 1000.0f;//approx 6000 rpm
+ engine.mMOI = 2.f;
+
+ driveData.setEngineData(engine);
+
+ //Gears
+ PxVehicleGearsData gears;
+ gears.mSwitchTime = 0.5f;
+ driveData.setGearsData(gears);
+
+ //Clutch
+ PxVehicleClutchData clutch;
+ clutch.mStrength = 10.0f;
+ driveData.setClutchData(clutch);
+
+ //Ackermann steer accuracy
+ PxVehicleAckermannGeometryData ackermann;
+ ackermann.mAccuracy = 1.0f;
+ ackermann.mAxleSeparation = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].z - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].z;
+ ackermann.mFrontWidth = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_RIGHT].x - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eFRONT_LEFT].x;
+ ackermann.mRearWidth = wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_RIGHT].x - wheelCentreOffsets[PxVehicleDrive4WWheelOrder::eREAR_LEFT].x;
+ driveData.setAckermannGeometryData(ackermann);
+}
+
+void setupActor
+(PxRigidDynamic* vehActor,
+const PxFilterData& vehQryFilterData,
+const PxGeometry** wheelGeometries, const PxTransform* wheelLocalPoses, const PxU32 numWheelGeometries, const PxMaterial* wheelMaterial, const PxFilterData& wheelCollFilterData,
+const PxGeometry** chassisGeometries, const PxTransform* chassisLocalPoses, const PxU32 numChassisGeometries, const PxMaterial* chassisMaterial, const PxFilterData& chassisCollFilterData,
+const PxVehicleChassisData& chassisData,
+PxPhysics* physics)
+{
+ //Add all the wheel shapes to the actor.
+ for (PxU32 i = 0; i<numWheelGeometries; i++)
+ {
+ PxShape* wheelShape = PxRigidActorExt::createExclusiveShape(*vehActor, *wheelGeometries[i], *wheelMaterial);
+ wheelShape->setQueryFilterData(vehQryFilterData);
+ wheelShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+ //wheelShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
+ wheelShape->setSimulationFilterData(wheelCollFilterData);
+ wheelShape->setLocalPose(wheelLocalPoses[i]);
+ }
+
+ //Add the chassis shapes to the actor.
+ for (PxU32 i = 0; i<numChassisGeometries; i++)
+ {
+ PxShape* chassisShape = PxRigidActorExt::createExclusiveShape(*vehActor, *chassisGeometries[i], *chassisMaterial);
+ chassisShape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, false);
+ chassisShape->setQueryFilterData(vehQryFilterData);
+ chassisShape->setSimulationFilterData(chassisCollFilterData);
+ chassisShape->setLocalPose(chassisLocalPoses[i]);
+ }
+
+ vehActor->setMass(chassisData.mMass);
+ vehActor->setMassSpaceInertiaTensor(chassisData.mMOI);
+ vehActor->setCMassLocalPose(PxTransform(chassisData.mCMOffset, PxQuat(PxIdentity)));
+}
+
+PxRigidDynamic* createVehicleActor4W
+(const PxVehicleChassisData& chassisData,
+PxConvexMesh** wheelConvexMeshes, PxConvexMesh* chassisConvexMesh,
+PxScene& scene, PxPhysics& physics, const PxMaterial& material)
+{
+ //We need a rigid body actor for the vehicle.
+ //Don't forget to add the actor the scene after setting up the associated vehicle.
+ PxRigidDynamic* vehActor = physics.createRigidDynamic(PxTransform(PxIdentity));
+
+ //We need to add wheel collision shapes, their local poses, a material for the wheels, and a simulation filter for the wheels.
+ PxConvexMeshGeometry frontLeftWheelGeom(wheelConvexMeshes[0]);
+ PxConvexMeshGeometry frontRightWheelGeom(wheelConvexMeshes[1]);
+ PxConvexMeshGeometry rearLeftWheelGeom(wheelConvexMeshes[2]);
+ PxConvexMeshGeometry rearRightWheelGeom(wheelConvexMeshes[3]);
+ const PxGeometry* wheelGeometries[4] = { &frontLeftWheelGeom, &frontRightWheelGeom, &rearLeftWheelGeom, &rearRightWheelGeom };
+
+ const PxTransform wheelLocalPoses[4] = { PxTransform(PxIdentity), PxTransform(PxIdentity), PxTransform(PxIdentity), PxTransform(PxIdentity) };
+ const PxMaterial& wheelMaterial = material;
+ PxFilterData wheelCollFilterData;
+ wheelCollFilterData.word0 = COLLISION_FLAG_WHEEL;
+ wheelCollFilterData.word1 = COLLISION_FLAG_WHEEL_AGAINST;
+ wheelCollFilterData.word2 = PxPairFlag::eMODIFY_CONTACTS;
+
+ //We need to add chassis collision shapes, their local poses, a material for the chassis, and a simulation filter for the chassis.
+ PxConvexMeshGeometry chassisConvexGeom(chassisConvexMesh);
+ const PxGeometry* chassisGeoms[1] = { &chassisConvexGeom };
+ const PxTransform chassisLocalPoses[1] = { PxTransform(PxIdentity) };
+ const PxMaterial& chassisMaterial = material;
+ PxFilterData chassisCollFilterData;
+ chassisCollFilterData.word0 = COLLISION_FLAG_CHASSIS;
+ chassisCollFilterData.word1 = COLLISION_FLAG_CHASSIS_AGAINST;
+
+ //Create a query filter data for the car to ensure that cars
+ //do not attempt to drive on themselves.
+ PxFilterData vehQryFilterData;
+ VehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData);
+
+ //Set up the physx rigid body actor with shapes, local poses, and filters.
+ setupActor
+ (vehActor,
+ vehQryFilterData,
+ wheelGeometries, wheelLocalPoses, 4, &wheelMaterial, wheelCollFilterData,
+ chassisGeoms, chassisLocalPoses, 1, &chassisMaterial, chassisCollFilterData,
+ chassisData,
+ &physics);
+
+ return vehActor;
+}
+
+
+void VehicleManager::resetNWCar(const PxTransform& startTransform, PxVehicleWheels* vehWheels)
+{
+
+ PxVehicleDrive4W* vehDrive4W = (PxVehicleDrive4W*)vehWheels;
+ //Set the car back to its rest state.
+ vehDrive4W->setToRestState();
+ //Set the car to first gear.
+ vehDrive4W->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
+
+ //Set the car's transform to be the start transform.
+ PxRigidDynamic* actor = vehWheels->getRigidDynamicActor();
+ PxSceneWriteLock scopedLock(*actor->getScene());
+ actor->setGlobalPose(startTransform);
+}
+
+void VehicleManager::suspensionRaycasts(PxScene* scene)
+{
+ //Create a scene query if we haven't already done so.
+ if (NULL == mSqWheelRaycastBatchQuery)
+ {
+ mSqWheelRaycastBatchQuery = mSqData->setUpBatchedSceneQuery(scene);
+ }
+ //Raycasts.
+ PxSceneReadLock scopedLock(*scene);
+ PxVehicleWheels* vehicles[1] = { mVehicle };
+ PxVehicleSuspensionRaycasts(mSqWheelRaycastBatchQuery, 1, vehicles, mSqData->getRaycastQueryResultBufferSize(), mSqData->getRaycastQueryResultBuffer());
+}
+
+void VehicleManager::suspensionSweeps(PxScene* scene)
+{
+ //Create a scene query if we haven't already done so.
+ if (NULL == mSqWheelRaycastBatchQuery)
+ {
+ mSqWheelRaycastBatchQuery = mSqData->setUpBatchedSceneQuerySweep(scene);
+ }
+ //Raycasts.
+ PxSceneReadLock scopedLock(*scene);
+ PxVehicleWheels* vehicles[1] = { mVehicle };
+ PxVehicleSuspensionSweeps(mSqWheelRaycastBatchQuery, 1, vehicles, mSqData->getSweepQueryResultBufferSize(), mSqData->getSweepQueryResultBuffer(), 1);
+}
+
+void VehicleManager::update(const PxF32 timestep, const PxVec3& gravity)
+{
+ PxVehicleWheels* vehicles[1] = { mVehicle };
+
+ PxVehicleUpdates(timestep, gravity, *mSurfaceTirePairs, 1, vehicles, &mVehicleWheelQueryResults);
+}
+
+void VehicleManager::create4WVehicle(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material,
+ const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4,
+ const PxTransform& startTransform, const bool useAutoGearFlag)
+{
+ PxVehicleWheelsSimData* wheelsSimData = PxVehicleWheelsSimData::allocate(4);
+ PxVehicleDriveSimData4W driveSimData;
+ PxVehicleChassisData chassisData;
+
+ createVehicle4WSimulationData
+ (chassisMass, chassisConvexMesh,
+ 20.0f, wheelConvexMeshes4, wheelCentreOffsets4,
+ *wheelsSimData, driveSimData, chassisData);
+
+ //Instantiate and finalize the vehicle using physx.
+ PxRigidDynamic* vehActor = createVehicleActor4W(chassisData, wheelConvexMeshes4, chassisConvexMesh, scene, physics, material);
+
+ //Create a car.
+ PxVehicleDrive4W* car = PxVehicleDrive4W::allocate(4);
+ car->setup(&physics, vehActor, *wheelsSimData, driveSimData, 0);
+
+ //Free the sim data because we don't need that any more.
+ wheelsSimData->free();
+
+ //Don't forget to add the actor to the scene.
+ {
+ PxSceneWriteLock scopedLock(scene);
+ scene.addActor(*vehActor);
+ }
+
+ //Set up the mapping between wheel and actor shape.
+ car->mWheelsSimData.setWheelShapeMapping(0, 0);
+ car->mWheelsSimData.setWheelShapeMapping(1, 1);
+ car->mWheelsSimData.setWheelShapeMapping(2, 2);
+ car->mWheelsSimData.setWheelShapeMapping(3, 3);
+
+ //Set up the scene query filter data for each suspension line.
+ PxFilterData vehQryFilterData;
+ VehicleSetupVehicleShapeQueryFilterData(&vehQryFilterData);
+ car->mWheelsSimData.setSceneQueryFilterData(0, vehQryFilterData);
+ car->mWheelsSimData.setSceneQueryFilterData(1, vehQryFilterData);
+ car->mWheelsSimData.setSceneQueryFilterData(2, vehQryFilterData);
+ car->mWheelsSimData.setSceneQueryFilterData(3, vehQryFilterData);
+
+ //Set the autogear mode of the instantiate car.
+ car->mDriveDynData.setUseAutoGears(useAutoGearFlag);
+ car->mDriveDynData.forceGearChange(PxVehicleGearsData::eFIRST);
+
+ //Increment the number of vehicles
+ mVehicle = car;
+ mVehicleWheelQueryResults.nbWheelQueryResults = 4;
+ mVehicleWheelQueryResults.wheelQueryResults = mWheelQueryResults->addVehicle(4);
+
+ PxQuat rotation(3.1415 / 2.f, PxVec3(0.f, 0.f, 1.f));
+
+ PxD6Joint* joint = PxD6JointCreate(physics, vehActor, PxTransform(rotation), NULL, PxTransform(rotation));
+
+ joint->setMotion(PxD6Axis::eX, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eY, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eZ, PxD6Motion::eFREE);
+
+ joint->setMotion(PxD6Axis::eTWIST, PxD6Motion::eFREE);
+ joint->setMotion(PxD6Axis::eSWING1, PxD6Motion::eLIMITED);
+ joint->setMotion(PxD6Axis::eSWING2, PxD6Motion::eLIMITED);
+
+ PxJointLimitCone limitCone(3.1415/4.f, 3.1415 / 4.f);
+ joint->setSwingLimit(limitCone);
+
+}
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleManager.h b/KaplaDemo/samples/sampleViewer3/VehicleManager.h
new file mode 100644
index 00000000..949373bf
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleManager.h
@@ -0,0 +1,134 @@
+#ifndef VEHICLE_H
+#define VEHICLE_H
+
+#include "vehicle/PxVehicleWheels.h"
+#include "vehicle/PxVehicleDrive4W.h"
+#include "vehicle/PxVehicleTireFriction.h"
+#include "vehicle/PxVehicleUpdate.h"
+#include "RawLoader.h"
+#include "PxPhysics.h"
+#include "PxCooking.h"
+
+using namespace physx;
+
+namespace physx
+{
+ class PxBatchQuery;
+
+ namespace fracture
+ {
+ namespace base
+ {
+ class Compound;
+ }
+ }
+}
+
+class VehicleWheelQueryResults;
+class VehicleSceneQueryData;
+
+//Tire types.
+enum
+{
+ TIRE_TYPE_WETS = 0,
+ TIRE_TYPE_SLICKS,
+ TIRE_TYPE_ICE,
+ TIRE_TYPE_MUD,
+ MAX_NUM_TIRE_TYPES
+};
+
+//Drivable surface types.
+enum
+{
+ SURFACE_TYPE_MUD = 0,
+ SURFACE_TYPE_TARMAC,
+ SURFACE_TYPE_SNOW,
+ SURFACE_TYPE_GRASS,
+ MAX_NUM_SURFACE_TYPES
+};
+
+
+//Collision types and flags describing collision interactions of each collision type.
+enum
+{
+ COLLISION_FLAG_GROUND = 1 << 0,
+ COLLISION_FLAG_WHEEL = 1 << 1,
+ COLLISION_FLAG_CHASSIS = 1 << 2,
+ COLLISION_FLAG_OBSTACLE = 1 << 3,
+ COLLISION_FLAG_DRIVABLE_OBSTACLE = 1 << 4,
+
+ COLLISION_FLAG_GROUND_AGAINST = COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
+ COLLISION_FLAG_WHEEL_AGAINST = COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE,
+ COLLISION_FLAG_CHASSIS_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
+ COLLISION_FLAG_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_WHEEL | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
+ COLLISION_FLAG_DRIVABLE_OBSTACLE_AGAINST = COLLISION_FLAG_GROUND | COLLISION_FLAG_CHASSIS | COLLISION_FLAG_OBSTACLE | COLLISION_FLAG_DRIVABLE_OBSTACLE,
+};
+// ---------------------------------------------------------------------
+
+
+struct TireFrictionMultipliers
+{
+ static float getValue(PxU32 surfaceType, PxU32 tireType)
+ {
+ //Tire model friction for each combination of drivable surface type and tire type.
+ static PxF32 tireFrictionMultipliers[MAX_NUM_SURFACE_TYPES][MAX_NUM_TIRE_TYPES] =
+ {
+ //WETS SLICKS ICE MUD
+ { 0.95f, 0.95f, 0.95f, 0.95f }, //MUD
+ { 1.10f, 1.15f, 1.10f, 1.10f }, //TARMAC
+ { 0.70f, 0.70f, 0.70f, 0.70f }, //ICE
+ { 0.80f, 0.80f, 0.80f, 0.80f } //GRASS
+ };
+ return tireFrictionMultipliers[surfaceType][tireType];
+ }
+};
+
+class VehicleManager
+{
+public:
+ VehicleManager();
+ virtual ~VehicleManager();
+
+ void init(PxPhysics& physics, const PxMaterial** drivableSurfaceMaterials, const PxVehicleDrivableSurfaceType* drivableSurfaceTypes);
+
+ void create4WVehicle(PxScene& scene, PxPhysics& physics, PxCooking& cooking, const PxMaterial& material,
+ const PxF32 chassisMass, const PxVec3* wheelCentreOffsets4, PxConvexMesh* chassisConvexMesh, PxConvexMesh** wheelConvexMeshes4,
+ const PxTransform& startTransform, const bool useAutoGearFlag);
+ void createVehicle4WSimulationData(const PxF32 chassisMass, PxConvexMesh* chassisConvexMesh, const PxF32 wheelMass, PxConvexMesh** wheelConvexMeshes,
+ const PxVec3* wheelCentreOffsets, PxVehicleWheelsSimData& wheelsData, PxVehicleDriveSimData4W& driveData, PxVehicleChassisData& chassisData);
+ PxVec3 computeChassisAABBDimensions(const PxConvexMesh* chassisConvexMesh);
+ void computeWheelWidthsAndRadii(PxConvexMesh** wheelConvexMeshes, PxF32* wheelWidths, PxF32* wheelRadii);
+ void resetNWCar(const PxTransform& startTransform, PxVehicleWheels* vehWheels);
+ void suspensionRaycasts(PxScene* scene);
+ void suspensionSweeps(PxScene* scene);
+ void update(const PxF32 timestep, const PxVec3& gravity);
+
+ PxVehicleWheels* getVehicle() { return mVehicle; }
+
+ PxVehicleWheelQueryResult& getWheelQueryResult() { return mVehicleWheelQueryResults; };
+
+ void clearBatchQuery() { mSqWheelRaycastBatchQuery = NULL; }
+
+private:
+
+ PxVehicleWheels* mVehicle;
+ PxVehicleWheelQueryResult mVehicleWheelQueryResults;
+ //sdk raycasts (for the suspension lines).
+ VehicleSceneQueryData* mSqData;
+ PxBatchQuery* mSqWheelRaycastBatchQuery;
+
+ //Reports for each wheel.
+ VehicleWheelQueryResults* mWheelQueryResults;
+
+ //Cached simulation data of focus vehicle in 4W mode.
+ PxVehicleWheelsSimData* mWheelsSimData4W;
+ PxVehicleDriveSimData4W mDriveSimData4W;
+
+ //Friction from combinations of tire and surface types.
+ PxVehicleDrivableSurfaceToTireFrictionPairs* mSurfaceTirePairs;
+
+public:
+ fracture::base::Compound* mCompoundShape;
+
+};
+#endif // SCENE_BOXES_H
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.cpp b/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.cpp
new file mode 100644
index 00000000..3b305d0d
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.cpp
@@ -0,0 +1,72 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "VehicleWheelQueryResults.h"
+#include "vehicle/PxVehicleSDK.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+
+
+//#define CHECK_MSG(exp, msg) (!!(exp) || (physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, msg), 0) )
+
+VehicleWheelQueryResults* VehicleWheelQueryResults::allocate(const PxU32 maxNumWheels)
+{
+ const PxU32 size = sizeof(VehicleWheelQueryResults) + sizeof(PxWheelQueryResult)*maxNumWheels;
+ VehicleWheelQueryResults* resData = (VehicleWheelQueryResults*)PX_ALLOC(size, "VehicleWheelQueryResults");
+ resData->init();
+ PxU8* ptr = (PxU8*)resData;
+ ptr += sizeof(VehicleWheelQueryResults);
+ resData->mWheelQueryResults = (PxWheelQueryResult*)ptr;
+ ptr += sizeof(PxWheelQueryResult)*maxNumWheels;
+ resData->mMaxNumWheels = maxNumWheels;
+ for (PxU32 i = 0; i<maxNumWheels; i++)
+ {
+ new(&resData->mWheelQueryResults[i]) PxWheelQueryResult();
+ }
+ return resData;
+}
+
+void VehicleWheelQueryResults::free()
+{
+ PX_FREE(this);
+}
+
+PxWheelQueryResult* VehicleWheelQueryResults::addVehicle(const PxU32 numWheels)
+{
+ PX_ASSERT((mNumWheels + numWheels) <= mMaxNumWheels);
+ PxWheelQueryResult* r = &mWheelQueryResults[mNumWheels];
+ mNumWheels += numWheels;
+ return r;
+}
+
+
+
+
+
+
diff --git a/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.h b/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.h
new file mode 100644
index 00000000..e3d6d1e3
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/VehicleWheelQueryResults.h
@@ -0,0 +1,82 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef VEHICLE_WHEELQUERYRESULTS_H
+#define VEHICLE_WHEELQUERYRESULTS_H
+
+#include "vehicle/PxVehicleSDK.h"
+#include "vehicle/PxVehicleUpdate.h"
+
+using namespace physx;
+
+//Data structure to store reports for each wheel.
+class VehicleWheelQueryResults
+{
+public:
+
+ //Allocate a buffer of wheel query results for up to maxNumWheels.
+ static VehicleWheelQueryResults* allocate(const PxU32 maxNumWheels);
+
+ //Free allocated buffer.
+ void free();
+
+ PxWheelQueryResult* addVehicle(const PxU32 numWheels);
+
+private:
+
+ //One result for each wheel.
+ PxWheelQueryResult* mWheelQueryResults;
+
+ //Maximum number of wheels.
+ PxU32 mMaxNumWheels;
+
+ //Number of wheels
+ PxU32 mNumWheels;
+
+
+ VehicleWheelQueryResults()
+ : mWheelQueryResults(NULL), mMaxNumWheels(0), mNumWheels(0)
+ {
+ init();
+ }
+
+ ~VehicleWheelQueryResults()
+ {
+ }
+
+ void init()
+ {
+ mWheelQueryResults = NULL;
+ mMaxNumWheels = 0;
+ mNumWheels = 0;
+ }
+};
+
+
+#endif //VEHICLE_WHEELQUERYRESULTS_H
diff --git a/KaplaDemo/samples/sampleViewer3/XMLParser.cpp b/KaplaDemo/samples/sampleViewer3/XMLParser.cpp
new file mode 100644
index 00000000..4fec0532
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/XMLParser.cpp
@@ -0,0 +1,198 @@
+#include "XMLParser.h"
+
+#include <string.h>
+#include <float.h>
+
+#define EOL 10
+
+#ifdef __CELLOS_LV2__
+#include <safeStdio.h>
+#endif
+
+// ------ singleton pattern -----------------------------------------------------------
+
+static XMLParser *gXMLParser = NULL;
+
+XMLParser* XMLParser::getInstance()
+{
+ if (gXMLParser == NULL) {
+ gXMLParser = new XMLParser();
+ }
+ return gXMLParser;
+}
+
+void XMLParser::destroyInstance()
+{
+ if (gXMLParser != NULL) {
+ delete gXMLParser;
+ }
+ gXMLParser = NULL;
+}
+
+//---------------------------------------------------------------------
+XMLParser::XMLParser()
+{
+ clearTag();
+}
+
+//---------------------------------------------------------------------
+XMLParser::~XMLParser()
+{
+}
+
+//---------------------------------------------------------------------
+void XMLParser::clearTag()
+{
+ tagName.clear();
+ vars.clear();
+ closed = false;
+ endTag = false;
+}
+
+//---------------------------------------------------------------------
+bool XMLParser::open(std::string filename)
+{
+ return fs.open(filename.c_str());
+}
+
+//---------------------------------------------------------------------
+void XMLParser::close()
+{
+ fs.close();
+}
+
+//---------------------------------------------------------------------
+bool XMLParser::endOfFile()
+{
+ return fs.endReached();
+}
+
+//---------------------------------------------------------------------
+bool XMLParser::readNextTag()
+{
+ clearTag();
+
+ char sym[1024];
+
+ while (!fs.endReached()) {
+ fs.getSymbol(sym);
+ if (strlen(sym) > 0 && sym[0] == '<')
+ break;
+ }
+ if (fs.endReached()) return false;
+ fs.getSymbol(sym);
+ if (strlen(sym) == 0) return false;
+ if (sym[0] == '/') {
+ endTag = true;
+ fs.getSymbol(sym);
+ }
+ tagName = sym;
+
+ while (!fs.endReached()) {
+ fs.getSymbol(sym);
+ if (strlen(sym) == 0) return false;
+ if (sym[0] == '/') {
+ closed = true;
+ fs.getSymbol(sym);
+ if (strlen(sym) == 0) return false;
+ }
+ if (sym[0] == '>') break;
+
+ XMLVariable var;
+ var.name = sym;
+ fs.getSymbol(sym);
+ if (strlen(sym) == 0 || sym[0] != '=') return false;
+ fs.getSymbol(sym);
+ var.value = sym;
+ vars.push_back(var);
+ }
+ return true;
+}
+
+// ezm
+
+//---------------------------------------------------------------------
+void XMLParser::ezmParseSemantic(int &count)
+{
+ count = 0;
+ ezmTypes.clear();
+ ezmAttrs.clear();
+
+ std::string ctype = "";
+ std::string semantic = "";
+
+ for (int i = 0; i < (int)vars.size(); i++) {
+ if (vars[i].name == "count")
+ sscanf_s(vars[i].value.c_str(), "%i", &count);
+ else if (vars[i].name == "ctype")
+ ctype = vars[i].value;
+ else if (vars[i].name == "semantic")
+ semantic = vars[i].value;
+ }
+
+ std::string s;
+ int i = 0;
+ while (i < (int)ctype.size()) {
+ while (i < (int)ctype.size() && ctype[i] == ' ')
+ i++;
+ s = "";
+ while (i < (int)ctype.size() && ctype[i] != ' ') {
+ s += ctype[i]; i++;
+ }
+ if (!s.empty())
+ ezmTypes.push_back(s);
+ }
+ i = 0;
+ while (i < (int)semantic.size()) {
+ while (i < (int)semantic.size() && semantic[i] == ' ')
+ i++;
+ s = "";
+ while (i < (int)semantic.size() && semantic[i] != ' ') {
+ s += semantic[i]; i++;
+ }
+ if (!s.empty())
+ ezmAttrs.push_back(s);
+ }
+
+ // should not happen
+ if (ezmTypes.size() > ezmAttrs.size())
+ ezmTypes.resize(ezmAttrs.size());
+ if (ezmAttrs.size() > ezmTypes.size())
+ ezmAttrs.resize(ezmTypes.size());
+}
+
+//---------------------------------------------------------------------
+void XMLParser::ezmReadSemanticEntry(int nr)
+{
+ ezmFloats.clear();
+ ezmInts.clear();
+
+ if (nr < 0 || nr >= (int)ezmTypes.size())
+ return;
+
+ std::string &type = ezmTypes[nr];
+
+ if (type == "x1" || type == "x2" || type == "x4") {
+ char sym[32];
+ fs.getSymbol(sym);
+ int x4;
+ sscanf(sym, "%X", &x4);
+ ezmInts.push_back(x4);
+ }
+ else if (type.size() > 0) {
+ if (type[0] == 'f') {
+ for (int k = 0; k < (int)type.size(); k++) {
+ float fsym;
+ fs.getFloatSymbol(fsym);
+ ezmFloats.push_back(fsym);
+ }
+ }
+ if (type[0] == 'h' || type[0] == 'd' || type[0] == 'c' || type[0] == 'b') {
+ for (int k = 0; k < (int)type.size(); k++) {
+ int isym;
+ fs.getIntSymbol(isym);
+ ezmInts.push_back(isym);
+ }
+ }
+ }
+}
diff --git a/KaplaDemo/samples/sampleViewer3/XMLParser.h b/KaplaDemo/samples/sampleViewer3/XMLParser.h
new file mode 100644
index 00000000..e9c3d9bb
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/XMLParser.h
@@ -0,0 +1,60 @@
+#ifndef XML_PARSER_H
+#define XML_PARSER_H
+
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include "FileScanner.h"
+
+#define XML_LINE_MAX 1024
+
+
+// -------------------------------------------------------------------------
+struct XMLVariable {
+ std::string name;
+ std::string value;
+};
+
+// -------------------------------------------------------------------------
+class XMLParser {
+public:
+ // singleton pattern
+ static XMLParser* getInstance();
+ static void destroyInstance();
+
+ bool open(std::string filename);
+ void close();
+ bool endOfFile();
+ bool readNextTag();
+
+ std::string tagName;
+ std::vector<XMLVariable> vars;
+ bool closed;
+ bool endTag;
+
+ FileScanner &getFileScanner() { return fs; }
+
+ // ezm
+ void ezmParseSemantic(int &count);
+ void ezmReadSemanticEntry(int nr);
+
+ std::vector<std::string> ezmAttrs;
+ std::vector<std::string> ezmTypes;
+ std::vector<float> ezmFloats;
+ std::vector<int> ezmInts;
+
+private:
+ XMLParser();
+ ~XMLParser();
+
+ void clearTag();
+ FileScanner fs;
+};
+
+#include <stdio.h>
+
+#define FILE_SCANNER_LINE_MAX 1024
+
+
+
+#endif \ No newline at end of file