OpenSource.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. #include "bsp.h"
  2. #include "collection.h"
  3. #include "mempools.h"
  4. #include "atto/app.h"
  5. #define ATTO_GL_DEBUG
  6. #define ATTO_GL_H_IMPLEMENT
  7. #include "atto/gl.h"
  8. #include "atto/math.h"
  9. #include <string.h>
  10. #include <stdlib.h> /* malloc */
  11. #include <stddef.h> /* offsetof */
  12. static char temp_data[64*1024*1024];
  13. static struct TemporaryPool temp = {
  14. .storage = temp_data,
  15. .size = sizeof(temp_data),
  16. .cursor = 0
  17. };
  18. static void* stdpool_alloc(struct MemoryPool *pool, size_t size) {
  19. (void)(pool);
  20. return malloc(size);
  21. }
  22. static void stdpool_free(struct MemoryPool *pool, void *ptr) {
  23. (void)(pool);
  24. free(ptr);
  25. }
  26. static struct MemoryPool stdpool = {
  27. .alloc = stdpool_alloc,
  28. .free = stdpool_free
  29. };
  30. struct SimpleCamera {
  31. struct AVec3f pos, dir, up;
  32. struct AMat3f axes;
  33. struct AMat4f projection;
  34. struct AMat4f view_projection;
  35. };
  36. static void simplecamRecalc(struct SimpleCamera *cam) {
  37. cam->dir = aVec3fNormalize(cam->dir);
  38. const struct AVec3f
  39. z = aVec3fNeg(cam->dir),
  40. x = aVec3fNormalize(aVec3fCross(cam->up, z)),
  41. y = aVec3fCross(z, x);
  42. cam->axes = aMat3fv(x, y, z);
  43. const struct AMat3f axes_inv = aMat3fTranspose(cam->axes);
  44. cam->view_projection = aMat4fMul(cam->projection,
  45. aMat4f3(axes_inv, aVec3fMulMat(axes_inv, aVec3fNeg(cam->pos))));
  46. }
  47. static void simplecamProjection(struct SimpleCamera *cam, float near, float far, float horizfov, float aspect) {
  48. const float w = 2.f * near * tanf(horizfov / 2.f), h = w / aspect;
  49. //aAppDebugPrintf("%f %f %f %f -> %f %f", near, far, horizfov, aspect, w, h);
  50. cam->projection = aMat4fPerspective(near, far, w, h);
  51. }
  52. static void simplecamLookAt(struct SimpleCamera *cam, struct AVec3f pos, struct AVec3f at, struct AVec3f up) {
  53. cam->pos = pos;
  54. cam->dir = aVec3fNormalize(aVec3fSub(at, pos));
  55. cam->up = up;
  56. simplecamRecalc(cam);
  57. }
  58. static void simplecamMove(struct SimpleCamera *cam, struct AVec3f v) {
  59. cam->pos = aVec3fAdd(cam->pos, aVec3fMulf(cam->axes.X, v.x));
  60. cam->pos = aVec3fAdd(cam->pos, aVec3fMulf(cam->axes.Y, v.y));
  61. cam->pos = aVec3fAdd(cam->pos, aVec3fMulf(cam->axes.Z, v.z));
  62. }
  63. static void simplecamRotateYaw(struct SimpleCamera *cam, float yaw) {
  64. const struct AMat3f rot = aMat3fRotateAxis(cam->up, yaw);
  65. cam->dir = aVec3fMulMat(rot, cam->dir);
  66. }
  67. static void simplecamRotatePitch(struct SimpleCamera *cam, float pitch) {
  68. /* TODO limit pitch */
  69. const struct AMat3f rot = aMat3fRotateAxis(cam->axes.X, pitch);
  70. cam->dir = aVec3fMulMat(rot, cam->dir);
  71. }
  72. #define COUNTOF(v) (sizeof(v) / sizeof(*(v)))
  73. static const float fsquad_vertices[] = {
  74. -1.f, 1.f, -1.f, -1.f, 1.f, 1.f, 1.f, -1.f
  75. };
  76. static const char fsquad_vertex_src[] =
  77. "attribute vec2 av2_pos;\n"
  78. "varying vec2 vv2_pos;\n"
  79. "void main() {\n"
  80. "vv2_pos = av2_pos;\n"
  81. "gl_Position = vec4(vv2_pos, 0., 1.);\n"
  82. "}\n";
  83. static const char fsquad_fragment_src[] =
  84. "uniform sampler2D us2_tex;\n"
  85. "varying vec2 vv2_pos;\n"
  86. "void main() {\n"
  87. "gl_FragColor = texture2D(us2_tex, vv2_pos * .5 + .5);\n"
  88. "}\n";
  89. static struct {
  90. AGLDrawSource source;
  91. AGLDrawMerge merge;
  92. AGLProgramUniform uniforms[2];
  93. AGLAttribute attrib_pos;
  94. } fsquad;
  95. static void fsquadInit() {
  96. fsquad.merge.depth.mode = AGLDM_Disabled;
  97. fsquad.merge.blend.enable = 0;
  98. fsquad.source.program = aGLProgramCreateSimple(fsquad_vertex_src, fsquad_fragment_src);
  99. if (fsquad.source.program < 1) {
  100. aAppDebugPrintf("Shader compilation error: %s", a_gl_error);
  101. aAppTerminate(-1);
  102. }
  103. fsquad.source.primitive.mode = GL_TRIANGLE_STRIP;
  104. fsquad.source.primitive.cull_mode = AGLCM_Disable;
  105. fsquad.source.primitive.front_face = AGLFF_CounterClockwise;
  106. fsquad.source.primitive.first = 0;
  107. fsquad.source.primitive.index.buffer = 0;
  108. fsquad.source.primitive.index.type = 0;
  109. fsquad.source.primitive.index.data.ptr = 0;
  110. fsquad.source.primitive.count = 4;
  111. fsquad.source.uniforms.p = fsquad.uniforms;
  112. fsquad.source.uniforms.n = COUNTOF(fsquad.uniforms);
  113. fsquad.source.attribs.p = &fsquad.attrib_pos;
  114. fsquad.source.attribs.n = 1;
  115. fsquad.attrib_pos.name = "av2_pos";
  116. fsquad.attrib_pos.size = 2;
  117. fsquad.attrib_pos.type = GL_FLOAT;
  118. fsquad.attrib_pos.normalized = GL_FALSE;
  119. fsquad.attrib_pos.stride = 2 * sizeof(float);
  120. fsquad.attrib_pos.ptr = fsquad_vertices;
  121. fsquad.attrib_pos.buffer = 0;
  122. fsquad.uniforms[0].name = "uf_aspect";
  123. fsquad.uniforms[0].type = AGLAT_Float;
  124. fsquad.uniforms[0].count = 1;
  125. fsquad.uniforms[1].name = "us2_tex";
  126. fsquad.uniforms[1].type = AGLAT_Texture;
  127. fsquad.uniforms[1].count = 1;
  128. }
  129. static void fsquadDraw(float aspect, const AGLTexture *tex, const AGLDrawTarget *target) {
  130. fsquad.uniforms[0].value.pf = &aspect;
  131. fsquad.uniforms[1].value.texture = tex;
  132. aGLDraw(&fsquad.source, &fsquad.merge, target);
  133. }
  134. static const float aabb_draw_vertices[] = {
  135. 0.f, 0.f, 0.f,
  136. 0.f, 0.f, 1.f,
  137. 0.f, 1.f, 1.f,
  138. 0.f, 1.f, 0.f,
  139. 1.f, 0.f, 0.f,
  140. 1.f, 0.f, 1.f,
  141. 1.f, 1.f, 1.f,
  142. 1.f, 1.f, 0.f
  143. };
  144. static const uint16_t aabb_draw_indices[] = {
  145. 0, 1, 1, 2, 2, 3, 3, 0,
  146. 4, 5, 5, 6, 6, 7, 7, 4,
  147. 0, 4, 1, 5, 2, 6, 3, 7
  148. };
  149. static const char aabb_draw_vertex_src[] =
  150. "attribute vec3 av3_pos;\n"
  151. "uniform mat4 um4_MVP;\n"
  152. "uniform vec3 uv3_mul, uv3_add;\n"
  153. "varying vec3 vv3_pos;\n"
  154. "void main() {\n"
  155. "vv3_pos = av3_pos;\n"
  156. "gl_Position = um4_MVP * vec4(av3_pos * uv3_mul + uv3_add, 1.);\n"
  157. "}\n";
  158. static const char aabb_draw_fragment_src[] =
  159. "uniform vec3 uv3_color;\n"
  160. "varying vec3 vv3_pos;\n"
  161. "void main() {\n"
  162. "gl_FragColor = vec4(vv3_pos * uv3_color, 1.);\n"
  163. "}\n";
  164. enum { AABBDUniformMVP, AABBDUniformMul, AABBDUniformAdd, AABBDUniformColor, AABBDUniform_COUNT };
  165. struct AABBDraw {
  166. struct AVec3f min, max, color;
  167. const struct AMat4f *mvp;
  168. const AGLDrawTarget *target;
  169. };
  170. static struct {
  171. AGLProgram program;
  172. } aabb_draw;
  173. static void aabbDraw(const struct AABBDraw *draw) {
  174. AGLDrawSource source;
  175. AGLDrawMerge merge;
  176. AGLProgramUniform uniforms[AABBDUniform_COUNT];
  177. AGLAttribute attrib_pos;
  178. const struct AVec3f mul = aVec3fSub(draw->max, draw->min);
  179. merge.depth.mode = AGLDM_Disabled;
  180. merge.blend.enable = 0;
  181. if (aabb_draw.program < 1) {
  182. aabb_draw.program = aGLProgramCreateSimple(aabb_draw_vertex_src, aabb_draw_fragment_src);
  183. if (aabb_draw.program < 1) {
  184. aAppDebugPrintf("Shader compilation error: %s", a_gl_error);
  185. aAppTerminate(-1);
  186. }
  187. }
  188. source.program = aabb_draw.program;
  189. source.primitive.mode = GL_LINES;
  190. source.primitive.cull_mode = AGLCM_Back;//AGLCM_Disable;
  191. source.primitive.front_face = AGLFF_CounterClockwise;
  192. source.primitive.first = 0;
  193. source.primitive.index.buffer = 0;
  194. #if 1
  195. source.primitive.index.type = GL_UNSIGNED_SHORT;
  196. source.primitive.index.data.ptr = aabb_draw_indices;
  197. source.primitive.count = COUNTOF(aabb_draw_indices);
  198. #else
  199. source.primitive.index.type = 0;//GL_UNSIGNED_SHORT;
  200. source.primitive.index.data.ptr = 0;//aabb_draw_indices;
  201. source.primitive.count = 8;(void)(aabb_draw_indices);//COUNTOF(aabb_draw_indices);
  202. #endif
  203. source.uniforms.p = uniforms;
  204. source.uniforms.n = AABBDUniform_COUNT;
  205. source.attribs.p = &attrib_pos;
  206. source.attribs.n = 1;
  207. attrib_pos.name = "av3_pos";
  208. attrib_pos.size = 3;
  209. attrib_pos.type = GL_FLOAT;
  210. attrib_pos.normalized = GL_FALSE;
  211. attrib_pos.stride = 3 * sizeof(float);
  212. attrib_pos.ptr = aabb_draw_vertices;
  213. attrib_pos.buffer = 0;
  214. uniforms[AABBDUniformMVP].name = "um4_MVP";
  215. uniforms[AABBDUniformMVP].type = AGLAT_Mat4;
  216. uniforms[AABBDUniformMVP].count = 1;
  217. uniforms[AABBDUniformMVP].value.pf = &draw->mvp->X.x;
  218. uniforms[AABBDUniformMul].name = "uv3_mul";
  219. uniforms[AABBDUniformMul].type = AGLAT_Vec3;
  220. uniforms[AABBDUniformMul].count = 1;
  221. uniforms[AABBDUniformMul].value.pf = &mul.x;
  222. uniforms[AABBDUniformAdd].name = "uv3_add";
  223. uniforms[AABBDUniformAdd].type = AGLAT_Vec3;
  224. uniforms[AABBDUniformAdd].count = 1;
  225. uniforms[AABBDUniformAdd].value.pf = &draw->min.x;
  226. uniforms[AABBDUniformColor].name = "uv3_color";
  227. uniforms[AABBDUniformColor].type = AGLAT_Vec3;
  228. uniforms[AABBDUniformColor].count = 1;
  229. uniforms[AABBDUniformColor].value.pf = &draw->color.x;
  230. aGLDraw(&source, &merge, draw->target);
  231. }
  232. static const char vertex_src[] =
  233. "attribute vec3 av3_pos, av3_normal;\n"
  234. "attribute vec2 av2_lightmap;\n"
  235. "uniform mat4 um4_VP;\n"
  236. "varying vec2 vv2_lightmap;\n"
  237. "varying vec3 vv3_normal;\n"
  238. "void main() {\n"
  239. "vv2_lightmap = av2_lightmap;\n"
  240. "vv3_normal = av3_normal;\n"
  241. "gl_Position = um4_VP * vec4(av3_pos, 1.);\n"
  242. "}\n";
  243. static const char fragment_src[] =
  244. "uniform sampler2D us2_lightmap;\n"
  245. "uniform vec2 uv2_lightmap_size;\n"
  246. "varying vec2 vv2_lightmap;\n"
  247. "varying vec3 vv3_normal;\n"
  248. "uniform float uf_lmn;\n"
  249. "void main() {\n"
  250. "gl_FragColor = mix(texture2D(us2_lightmap, vv2_lightmap), vec4(vv3_normal, 0.), uf_lmn);\n"
  251. //"gl_FragColor = texture2D(us2_lightmap, vv2_lightmap);\n"
  252. "}\n";
  253. enum { UniformM, UniformVP, UniformLightmap, UniformLightmapSize, UniformLMN, Uniform_COUNT };
  254. enum { AttribPos, AttribNormal, AttribLightmapUV, Attrib_COUNT };
  255. static struct {
  256. struct SimpleCamera camera;
  257. int forward, right, run;
  258. struct AVec3f center;
  259. float R;
  260. float lmn;
  261. AGLDrawTarget screen;
  262. AGLDrawSource source;
  263. AGLDrawMerge merge;
  264. AGLAttribute attribs[Attrib_COUNT];
  265. AGLProgramUniform uniforms[Uniform_COUNT];
  266. struct BSPModel worldspawn;
  267. struct AMat4f model;
  268. } g;
  269. static void opensrcInit(struct ICollection *collection, const char *map) {
  270. g.source.program = aGLProgramCreateSimple(vertex_src, fragment_src);
  271. if (g.source.program < 1) {
  272. aAppDebugPrintf("Shader compilation error: %s", a_gl_error);
  273. aAppTerminate(-1);
  274. }
  275. fsquadInit();
  276. struct BSPLoadModelContext loadctx = {
  277. .collection = collection,
  278. .pool = &stdpool,
  279. .tmp = &temp,
  280. .model = &g.worldspawn
  281. };
  282. const enum BSPLoadResult result = bspLoadWorldspawn(loadctx, map);
  283. if (result != BSPLoadResult_Success) {
  284. aAppDebugPrintf("Cannot load map \"%s\": %d", map, result);
  285. aAppTerminate(-2);
  286. }
  287. aAppDebugPrintf("Loaded %s to %u draw calls", map, g.worldspawn.draws_count);
  288. aAppDebugPrintf("AABB (%f, %f, %f) - (%f, %f, %f)",
  289. g.worldspawn.aabb.min.x,
  290. g.worldspawn.aabb.min.y,
  291. g.worldspawn.aabb.min.z,
  292. g.worldspawn.aabb.max.x,
  293. g.worldspawn.aabb.max.y,
  294. g.worldspawn.aabb.max.z);
  295. g.center = aVec3fMulf(aVec3fAdd(g.worldspawn.aabb.min, g.worldspawn.aabb.max), .5f);
  296. g.R = aVec3fLength(aVec3fSub(g.worldspawn.aabb.max, g.worldspawn.aabb.min)) * .5f;
  297. aAppDebugPrintf("Center %f, %f, %f, R~=%f", g.center.x, g.center.y, g.center.z, g.R);
  298. g.model = aMat4fIdentity();
  299. g.source.primitive.mode = GL_TRIANGLES;
  300. g.source.primitive.first = 0;
  301. g.source.primitive.cull_mode = AGLCM_Back;
  302. g.source.primitive.front_face = AGLFF_CounterClockwise;
  303. g.source.primitive.index.type = GL_UNSIGNED_SHORT;
  304. g.source.uniforms.p = g.uniforms;
  305. g.source.uniforms.n = Uniform_COUNT;
  306. g.source.attribs.p = g.attribs;
  307. g.source.attribs.n = Attrib_COUNT;
  308. g.attribs[AttribPos].name = "av3_pos";
  309. g.attribs[AttribPos].size = 3;
  310. g.attribs[AttribPos].type = GL_FLOAT;
  311. g.attribs[AttribPos].normalized = GL_FALSE;
  312. g.attribs[AttribPos].stride = sizeof(struct BSPModelVertex);
  313. g.attribs[AttribPos].ptr = 0;
  314. g.attribs[AttribNormal].name = "av3_normal";
  315. g.attribs[AttribNormal].size = 3;
  316. g.attribs[AttribNormal].type = GL_FLOAT;
  317. g.attribs[AttribNormal].normalized = GL_FALSE;
  318. g.attribs[AttribNormal].stride = sizeof(struct BSPModelVertex);
  319. g.attribs[AttribNormal].ptr = (void*)offsetof(struct BSPModelVertex, normal);
  320. g.attribs[AttribLightmapUV].name = "av2_lightmap";
  321. g.attribs[AttribLightmapUV].size = 2;
  322. g.attribs[AttribLightmapUV].type = GL_FLOAT;
  323. g.attribs[AttribLightmapUV].normalized = GL_FALSE;
  324. g.attribs[AttribLightmapUV].stride = sizeof(struct BSPModelVertex);
  325. g.attribs[AttribLightmapUV].ptr = (void*)offsetof(struct BSPModelVertex, lightmap_uv);
  326. g.uniforms[UniformM].name = "um4_M";
  327. g.uniforms[UniformM].type = AGLAT_Mat4;
  328. g.uniforms[UniformM].count = 1;
  329. g.uniforms[UniformM].value.pf = &g.model.X.x;
  330. g.uniforms[UniformVP].name = "um4_VP";
  331. g.uniforms[UniformVP].type = AGLAT_Mat4;
  332. g.uniforms[UniformVP].count = 1;
  333. g.uniforms[UniformVP].value.pf = &g.camera.view_projection.X.x;
  334. g.uniforms[UniformLightmap].name = "us2_lightmap";
  335. g.uniforms[UniformLightmap].type = AGLAT_Texture;
  336. g.uniforms[UniformLightmap].count = 1;
  337. g.uniforms[UniformLightmapSize].name = "uv2_lightmap_size";
  338. g.uniforms[UniformLightmapSize].type = AGLAT_Vec2;
  339. g.uniforms[UniformLightmapSize].count = 1;
  340. g.uniforms[UniformLMN].name = "uf_lmn";
  341. g.uniforms[UniformLMN].type = AGLAT_Float;
  342. g.uniforms[UniformLMN].count = 1;
  343. g.uniforms[UniformLMN].value.pf = &g.lmn;
  344. g.lmn = 0;
  345. g.merge.blend.enable = 0;
  346. g.merge.depth.mode = AGLDM_TestAndWrite;
  347. g.merge.depth.func = AGLDF_Less;
  348. g.screen.framebuffer = 0;
  349. const float t = 0;
  350. simplecamLookAt(&g.camera,
  351. aVec3fAdd(g.center, aVec3fMulf(aVec3f(cosf(t*.5), sinf(t*.5), .25f), g.R*.5f)),
  352. g.center, aVec3f(0.f, 0.f, 1.f));
  353. }
  354. static void drawBSPDraw(const struct BSPDraw *draw) {
  355. g.source.primitive.index.data.offset = draw->start;
  356. g.source.primitive.count = draw->count;
  357. g.attribs[AttribPos].buffer =
  358. g.attribs[AttribNormal].buffer =
  359. g.attribs[AttribLightmapUV].buffer = &draw->vbo;
  360. aGLDraw(&g.source, &g.merge, &g.screen);
  361. }
  362. static void drawModel(const struct BSPModel *model) {
  363. const struct AVec2f lm_size = aVec2f(model->lightmap.width, model->lightmap.height);
  364. g.uniforms[UniformLightmap].value.texture = &model->lightmap;
  365. g.uniforms[UniformLightmapSize].value.pf = &lm_size.x;
  366. g.source.primitive.index.buffer = &model->ibo;
  367. for (unsigned int i = 0; i < model->draws_count; ++i)
  368. drawBSPDraw(model->draws + i);
  369. }
  370. static void opensrcResize(ATimeUs timestamp, unsigned int old_w, unsigned int old_h) {
  371. (void)(timestamp); (void)(old_w); (void)(old_h);
  372. g.screen.viewport.x = g.screen.viewport.y = 0;
  373. g.screen.viewport.w = a_app_state->width;
  374. g.screen.viewport.h = a_app_state->height;
  375. simplecamProjection(&g.camera, 1.f, g.R * 10.f, 3.1415926f/2.f, (float)a_app_state->width / (float)a_app_state->height);
  376. simplecamRecalc(&g.camera);
  377. }
  378. static void opensrcPaint(ATimeUs timestamp, float dt) {
  379. (void)(timestamp); (void)(dt);
  380. if (0) {
  381. const float t = timestamp * 1e-6f;
  382. simplecamLookAt(&g.camera,
  383. aVec3fAdd(g.center, aVec3fMulf(aVec3f(cosf(t*.5), sinf(t*.5), .25f), g.R*.5f)),
  384. g.center, aVec3f(0.f, 0.f, 1.f));
  385. } else {
  386. float move = dt * (g.run?3000.f:300.f);
  387. simplecamMove(&g.camera, aVec3f(g.right * move, 0.f, -g.forward * move));
  388. simplecamRecalc(&g.camera);
  389. }
  390. AGLClearParams clear;
  391. clear.r = clear.g = clear.b = 0;
  392. clear.depth = 1.f;
  393. clear.bits = AGLCB_ColorAndDepth;
  394. aGLClear(&clear, &g.screen);
  395. if (0)
  396. fsquadDraw(1., &g.worldspawn.lightmap, &g.screen);
  397. drawModel(&g.worldspawn);
  398. if (0) {
  399. const struct AABBDraw aabb = {
  400. .min = g.worldspawn.aabb.min,
  401. .max = g.worldspawn.aabb.max,
  402. .color = aVec3ff(1),
  403. .mvp = &g.camera.view_projection,
  404. .target = &g.screen
  405. };
  406. aabbDraw(&aabb);
  407. }
  408. }
  409. static void opensrcKeyPress(ATimeUs timestamp, AKey key, int pressed) {
  410. (void)(timestamp); (void)(key); (void)(pressed);
  411. //printf("KEY %u %d %d\n", timestamp, key, pressed);
  412. switch (key) {
  413. case AK_Esc:
  414. if (!pressed) break;
  415. if (a_app_state->grabbed)
  416. aAppGrabInput(0);
  417. else
  418. aAppTerminate(0);
  419. break;
  420. case AK_W: g.forward += pressed?1:-1; break;
  421. case AK_S: g.forward += pressed?-1:1; break;
  422. case AK_A: g.right += pressed?-1:1; break;
  423. case AK_D: g.right += pressed?1:-1; break;
  424. case AK_LeftShift: g.run = pressed; break;
  425. case AK_E: g.lmn = pressed; break;
  426. default: break;
  427. }
  428. }
  429. static void opensrcPointer(ATimeUs timestamp, int dx, int dy, unsigned int btndiff) {
  430. (void)(timestamp); (void)(dx); (void)(dy); (void)(btndiff);
  431. //printf("PTR %u %d %d %x\n", timestamp, dx, dy, btndiff);
  432. if (a_app_state->grabbed) {
  433. simplecamRotatePitch(&g.camera, dy * -4e-3f);
  434. simplecamRotateYaw(&g.camera, dx * -4e-3f);
  435. simplecamRecalc(&g.camera);
  436. } else if (btndiff)
  437. aAppGrabInput(1);
  438. }
  439. void attoAppInit(struct AAppProctable *proctable) {
  440. aGLInit();
  441. const int max_collections = 16;
  442. struct FilesystemCollection collections[max_collections];
  443. int free_collection = 0;
  444. const char *map = 0;
  445. for (int i = 1; i < a_app_state->argc; ++i) {
  446. const char *argv = a_app_state->argv[i];
  447. if (strcmp(argv, "-d") == 0) {
  448. if (i == a_app_state->argc - 1) {
  449. aAppDebugPrintf("-d requires an argument");
  450. goto print_usage_and_exit;
  451. }
  452. const char *value = a_app_state->argv[++i];
  453. if (free_collection >= max_collections) {
  454. aAppDebugPrintf("Too many fs collections specified: %s", value);
  455. goto print_usage_and_exit;
  456. }
  457. filesystemCollectionCreate(collections + (free_collection++), value);
  458. } else {
  459. if (map) {
  460. aAppDebugPrintf("Only one map can be specified");
  461. goto print_usage_and_exit;
  462. }
  463. map = argv;
  464. }
  465. }
  466. if (!map || !free_collection) {
  467. aAppDebugPrintf("At least one map and one collection required");
  468. goto print_usage_and_exit;
  469. }
  470. for (int i = 0; i < free_collection - 1; ++i)
  471. collections[i].head.next = &collections[i+1].head;
  472. opensrcInit(&collections[0].head, map);
  473. proctable->resize = opensrcResize;
  474. proctable->paint = opensrcPaint;
  475. proctable->key = opensrcKeyPress;
  476. proctable->pointer = opensrcPointer;
  477. return;
  478. print_usage_and_exit:
  479. aAppDebugPrintf("usage: %s <-d path> ... mapname", a_app_state->argv[0]);
  480. aAppTerminate(1);
  481. }