source: trunk/src/scene.cpp @ 1222

Last change on this file since 1222 was 1222, checked in by sam, 10 years ago

build: compilation fixes for errors introduced in the recent Direct3D
and Android changes.

  • Property svn:keywords set to Id
File size: 16.0 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include <cstdlib>
16#include <cmath>
17
18#ifdef WIN32
19#   define WIN32_LEAN_AND_MEAN
20#   include <windows.h>
21#   if defined USE_D3D9
22#       define FAR
23#       define NEAR
24#       include <d3d9.h>
25#   endif
26#endif
27
28#include "core.h"
29#include "lolgl.h"
30
31#if defined USE_D3D9
32extern IDirect3DDevice9 *g_d3ddevice;
33#elif defined _XBOX
34extern D3DDevice *g_d3ddevice;
35#endif
36
37namespace lol
38{
39
40struct Tile
41{
42    TileSet *tileset;
43    uint32_t prio;
44    vec3 pos;
45    vec2 scale;
46    int id, o;
47};
48
49static Shader *stdshader = NULL;
50
51/*
52 * Scene implementation class
53 */
54
55class SceneData
56{
57    friend class Scene;
58
59private:
60    static int Compare(void const *p1, void const *p2)
61    {
62        Tile const *t1 = (Tile const *)p1;
63        Tile const *t2 = (Tile const *)p2;
64
65        return t2->prio - t1->prio;
66    }
67
68    mat4 model_matrix;
69
70    Tile *tiles;
71    int ntiles;
72    float angle;
73
74#if defined USE_D3D9
75    IDirect3DVertexDeclaration9 *m_vdecl;
76    IDirect3DVertexBuffer9 **bufs;
77#elif defined _XBOX
78    D3DVertexDeclaration *m_vdecl;
79    D3DVertexBuffer **bufs;
80#else
81#   if defined HAVE_GL_2X && !defined __APPLE__
82    GLuint vao;
83#   endif
84    GLuint *bufs;
85#endif
86    int nbufs;
87
88    static Scene *scene;
89};
90
91Scene *SceneData::scene = NULL;
92
93/*
94 * Public Scene class
95 */
96
97Scene::Scene(float angle)
98  : data(new SceneData())
99{
100    data->tiles = 0;
101    data->ntiles = 0;
102    data->angle = angle;
103
104    data->bufs = 0;
105    data->nbufs = 0;
106
107#if defined _XBOX || defined USE_D3D9
108    D3DVERTEXELEMENT9 const elements[] =
109    {
110        { 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
111        { 1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
112        D3DDECL_END()
113    };
114    g_d3ddevice->CreateVertexDeclaration(elements, &data->m_vdecl);
115#else
116#   if defined HAVE_GL_2X && !defined __APPLE__
117    glGenVertexArrays(1, &data->vao);
118#   endif
119#endif
120}
121
122Scene::~Scene()
123{
124#if defined USE_D3D9 || defined _XBOX
125    /* FIXME: TODO */
126#else
127    /* FIXME: this must be done while the GL context is still active.
128     * Change the code architecture to make sure of that. */
129    /* XXX: The test is necessary because of a crash with PSGL. */
130    if (data->nbufs > 0)
131        glDeleteBuffers(data->nbufs, data->bufs);
132#   if defined HAVE_GL_2X && !defined __APPLE__
133    glDeleteVertexArrays(1, &data->vao);
134#   endif
135    free(data->bufs);
136#endif
137    delete data;
138}
139
140Scene *Scene::GetDefault()
141{
142    if (!SceneData::scene)
143        SceneData::scene = new Scene(0.0f);
144    return SceneData::scene;
145}
146
147void Scene::Reset()
148{
149    if (SceneData::scene)
150        delete SceneData::scene;
151    SceneData::scene = NULL;
152}
153
154void Scene::AddTile(TileSet *tileset, int id, vec3 pos, int o, vec2 scale)
155{
156    if ((data->ntiles % 1024) == 0)
157        data->tiles = (Tile *)realloc(data->tiles,
158                                      (data->ntiles + 1024) * sizeof(Tile));
159    /* FIXME: this sorting only works for a 45-degree camera */
160    data->tiles[data->ntiles].prio = -pos.y - 2 * 32 * pos.z + (o ? 0 : 32);
161    data->tiles[data->ntiles].tileset = tileset;
162    data->tiles[data->ntiles].id = id;
163    data->tiles[data->ntiles].pos = pos;
164    data->tiles[data->ntiles].o = o;
165    data->tiles[data->ntiles].scale = scale;
166    data->ntiles++;
167}
168
169void Scene::Render() // XXX: rename to Blit()
170{
171    if (!stdshader)
172    {
173#if !defined _XBOX && !defined __CELLOS_LV2__ && !defined USE_D3D9
174        stdshader = Shader::Create(
175#   if !defined HAVE_GLES_2X
176            "#version 130\n"
177#   endif
178            "\n"
179#   if defined HAVE_GLES_2X
180            "attribute vec3 in_Position;\n"
181            "attribute vec2 in_TexCoord;\n"
182            "varying vec2 pass_TexCoord;\n"
183#   else
184            "in vec3 in_Position;\n"
185            "in vec2 in_TexCoord;\n"
186#   endif
187            "uniform mat4 proj_matrix;\n"
188            "uniform mat4 view_matrix;\n"
189            "uniform mat4 model_matrix;\n"
190            "\n"
191            "void main()\n"
192            "{\n"
193            "    gl_Position = proj_matrix * view_matrix * model_matrix"
194            "                * vec4(in_Position, 1.0);\n"
195#   if defined HAVE_GLES_2X
196            "    pass_TexCoord = in_TexCoord;\n"
197#   else
198            "    gl_TexCoord[0] = vec4(in_TexCoord, 0.0, 0.0);\n"
199#   endif
200            "}\n",
201
202#   if !defined HAVE_GLES_2X
203            "#version 130\n"
204#   else
205            "precision mediump float;\n"
206#   endif
207            "\n"
208            "uniform sampler2D in_Texture;\n"
209#   if defined HAVE_GLES_2X
210            "varying vec2 pass_TexCoord;\n"
211#   endif
212            "\n"
213            "void main()\n"
214            "{\n"
215#   if defined HAVE_GLES_2X
216            "    vec4 col = texture2D(in_Texture, pass_TexCoord);\n"
217            //"    vec4 col = vec4(0.5, 1.0, 0.0, 0.5);\n"
218            //"    vec4 col = vec4(pass_TexCoord * 4.0, 0.0, 0.25);\n"
219#   else
220            "    vec4 col = texture2D(in_Texture, vec2(gl_TexCoord[0]));\n"
221#   endif
222#   if 0
223            "    float mul = 2.0;\n"
224#       if 1
225            "    vec2 d1 = mod(vec2(gl_FragCoord), vec2(2.0, 2.0));\n"
226            "    float t1 = mod(3.0 * d1.x + 2.0 * d1.y, 4.0);\n"
227            "    float dx2 = mod(floor(gl_FragCoord.x * 0.5), 2.0);\n"
228            "    float dy2 = mod(floor(gl_FragCoord.y * 0.5), 2.0);\n"
229            "    float t2 = mod(3.0 * dx2 + 2.0 * dy2, 4.0);\n"
230            "    float dx3 = mod(floor(gl_FragCoord.x * 0.25), 2.0);\n"
231            "    float dy3 = mod(floor(gl_FragCoord.y * 0.25), 2.0);\n"
232            "    float t3 = mod(3.0 * dx3 + 2.0 * dy3, 4.0);\n"
233            "    t1 = (1.0 + 16.0 * t1 + 4.0 * t2 + t3) / 65.0;\n"
234            "    t2 = t1;\n"
235            "    t3 = t1;\n"
236#       else
237            "    float rand = sin(gl_FragCoord.x * 1.23456) * 123.456\n"
238            "               + cos(gl_FragCoord.y * 2.34567) * 789.012;\n"
239            "    float t1 = mod(sin(rand) * 17.13043, 1.0);\n"
240            "    float t2 = mod(sin(rand) * 27.13043, 1.0);\n"
241            "    float t3 = mod(sin(rand) * 37.13043, 1.0);\n"
242#       endif
243            "    float fracx = fract(col.x * mul);\n"
244            "    float fracy = fract(col.y * mul);\n"
245            "    float fracz = fract(col.z * mul);\n"
246            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
247            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
248            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
249            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
250            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
251            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
252#   endif
253            "    gl_FragColor = col;\n"
254            "}\n");
255#else
256        stdshader = Shader::Create(
257            "void main(float4 in_Position : POSITION,"
258            "          float2 in_TexCoord : TEXCOORD0,"
259            "          uniform float4x4 proj_matrix,"
260            "          uniform float4x4 view_matrix,"
261            "          uniform float4x4 model_matrix,"
262            "          out float2 out_TexCoord : TEXCOORD0,"
263            "          out float4 out_Position : POSITION)"
264            "{"
265            "    out_Position = mul(proj_matrix, mul(view_matrix, mul(model_matrix, in_Position)));"
266            "    out_TexCoord = in_TexCoord;"
267            "}",
268
269            "void main(float2 in_TexCoord : TEXCOORD0,"
270#   if 0
271            "          float4 in_FragCoord : WPOS,"
272#   endif
273            "          uniform sampler2D tex,"
274            "          out float4 out_FragColor : COLOR)"
275            "{"
276            "    float4 col = tex2D(tex, in_TexCoord);"
277#   if 0
278            "    float mul = 2.0;\n"
279            "    float t1, t2, t3;\n"
280#       if 1
281            "    float dx1 = frac(in_FragCoord.x * 0.5) * 2.0;\n"
282            "    float dy1 = frac(in_FragCoord.y * 0.5) * 2.0;\n"
283            "    t1 = frac((3.0 * dx1 + 2.0 * dy1) / 4.0) * 4.0;\n"
284            "    float dx2 = frac(floor(in_FragCoord.x * 0.5) * 0.5) * 2.0;\n"
285            "    float dy2 = frac(floor(in_FragCoord.y * 0.5) * 0.5) * 2.0;\n"
286            "    t2 = frac((3.0 * dx2 + 2.0 * dy2) / 4.0) * 4.0;\n"
287            "    float dx3 = frac(floor(in_FragCoord.x * 0.25) * 0.5) * 2.0;\n"
288            "    float dy3 = frac(floor(in_FragCoord.y * 0.25) * 0.5) * 2.0;\n"
289            "    t3 = frac((3.0 * dx3 + 2.0 * dy3) / 4.0) * 4.0;\n"
290            "    t1 = (1.0 + 4.0 * t1 + t2) / 17.0;\n"
291            "    t2 = t1;\n"
292            "    t3 = t1;\n"
293#       else
294            "    float rand = sin(in_FragCoord.x * 1.23456) * 123.456\n"
295            "               + cos(in_FragCoord.y * 2.34567) * 789.012;\n"
296            "    t1 = frac(sin(rand) * 17.13043);\n"
297            "    t2 = frac(sin(rand) * 27.13043);\n"
298            "    t3 = frac(sin(rand) * 37.13043);\n"
299#       endif
300            "    float fracx = frac(col.x * mul);\n"
301            "    float fracy = frac(col.y * mul);\n"
302            "    float fracz = frac(col.z * mul);\n"
303            "    fracx = fracx > t1 ? 1.0 : 0.0;\n"
304            "    fracy = fracy > t2 ? 1.0 : 0.0;\n"
305            "    fracz = fracz > t3 ? 1.0 : 0.0;\n"
306            "    col.x = (floor(col.x * mul) + fracx) / mul;\n"
307            "    col.y = (floor(col.y * mul) + fracy) / mul;\n"
308            "    col.z = (floor(col.z * mul) + fracz) / mul;\n"
309#   endif
310            "    out_FragColor = col;"
311            "}");
312#endif
313    }
314
315#if 0
316    // Randomise, then sort.
317    for (int i = 0; i < data->ntiles; i++)
318    {
319        Tile tmp = data->tiles[i];
320        int j = rand() % data->ntiles;
321        data->tiles[i] = data->tiles[j];
322        data->tiles[j] = tmp;
323    }
324#endif
325    qsort(data->tiles, data->ntiles, sizeof(Tile), SceneData::Compare);
326
327    // XXX: debug stuff
328    data->model_matrix = mat4::translate(320.0f, 240.0f, 0.0f);
329    data->model_matrix *= mat4::rotate(-data->angle, 1.0f, 0.0f, 0.0f);
330#if 0
331    static float f = 0.0f;
332    f += 0.01f;
333    data->model_matrix *= mat4::rotate(6.0f * sinf(f), 1.0f, 0.0f, 0.0f);
334    data->model_matrix *= mat4::rotate(17.0f * cosf(f), 0.0f, 0.0f, 1.0f);
335#endif
336    data->model_matrix *= mat4::translate(-320.0f, -240.0f, 0.0f);
337    // XXX: end of debug stuff
338
339    ShaderUniform uni_mat, uni_tex;
340#if defined USE_D3D9 || defined _XBOX
341    /* Nothing? */
342#elif !defined __CELLOS_LV2__
343    int attr_pos, attr_tex;
344    attr_pos = stdshader->GetAttribLocation("in_Position");
345    attr_tex = stdshader->GetAttribLocation("in_TexCoord");
346#endif
347
348    stdshader->Bind();
349
350    uni_mat = stdshader->GetUniformLocation("proj_matrix");
351    stdshader->SetUniform(uni_mat, Video::GetProjMatrix());
352    uni_mat = stdshader->GetUniformLocation("view_matrix");
353    stdshader->SetUniform(uni_mat, Video::GetViewMatrix());
354    uni_mat = stdshader->GetUniformLocation("model_matrix");
355    stdshader->SetUniform(uni_mat, data->model_matrix);
356
357#if defined USE_D3D9 || defined _XBOX
358    //g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
359    g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
360    g_d3ddevice->SetVertexDeclaration(data->m_vdecl);
361#else
362    uni_tex = stdshader->GetUniformLocation("in_Texture");
363    stdshader->SetUniform(uni_tex, 0);
364
365#if !defined HAVE_GLES_2X
366    glEnable(GL_TEXTURE_2D);
367#endif
368    glEnable(GL_DEPTH_TEST);
369    glDepthFunc(GL_LEQUAL);
370#if defined HAVE_GL_2X && !defined __APPLE__
371    glEnable(GL_ALPHA_TEST);
372    glAlphaFunc(GL_GEQUAL, 0.01f);
373#endif
374    glEnable(GL_BLEND);
375    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
376#endif
377
378    for (int buf = 0, i = 0, n; i < data->ntiles; i = n, buf += 2)
379    {
380        /* Generate new vertex / texture coord buffers if necessary */
381        if (buf + 2 > data->nbufs)
382        {
383#if defined USE_D3D9
384            data->bufs = (IDirect3DVertexBuffer9 **)realloc(data->bufs, (buf + 2) * sizeof(IDirect3DVertexBuffer9 *));
385#elif defined _XBOX
386            data->bufs = (D3DVertexBuffer **)realloc(data->bufs, (buf + 2) * sizeof(D3DVertexBuffer *));
387#else
388            data->bufs = (uint32_t *)realloc(data->bufs, (buf + 2) * sizeof(uint32_t));
389            glGenBuffers(buf + 2 - data->nbufs, data->bufs + data->nbufs);
390#endif
391            data->nbufs = buf + 2;
392        }
393#if defined USE_D3D9 || defined _XBOX
394        else
395        {
396            data->bufs[buf]->Release();
397            data->bufs[buf + 1]->Release();
398        }
399#endif
400
401        /* Count how many quads will be needed */
402        for (n = i + 1; n < data->ntiles; n++)
403            if (data->tiles[i].tileset != data->tiles[n].tileset)
404                break;
405
406        /* Create a vertex array object */
407        float *vertex, *texture;
408#if defined USE_D3D9 || defined _XBOX
409        if (FAILED(g_d3ddevice->CreateVertexBuffer(6 * 3 * (n - i) * sizeof(float), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &data->bufs[buf], NULL)))
410            exit(0);
411        if (FAILED(data->bufs[buf]->Lock(0, 0, (void **)&vertex, 0)))
412            exit(0);
413        if (FAILED(g_d3ddevice->CreateVertexBuffer(6 * 2 * (n - i) * sizeof(float), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &data->bufs[buf + 1], NULL)))
414            exit(0);
415        if (FAILED(data->bufs[buf + 1]->Lock(0, 0, (void **)&texture, 0)))
416            exit(0);
417#else
418        vertex = (float *)malloc(6 * 3 * (n - i) * sizeof(float));
419        texture = (float *)malloc(6 * 2 * (n - i) * sizeof(float));
420#endif
421
422        for (int j = i; j < n; j++)
423        {
424            data->tiles[i].tileset->BlitTile(data->tiles[j].id,
425                            data->tiles[j].pos, data->tiles[j].o,
426                            data->tiles[j].scale,
427                            vertex + 18 * (j - i), texture + 12 * (j - i));
428        }
429
430#if defined USE_D3D9 || defined _XBOX
431        data->bufs[buf]->Unlock();
432        data->bufs[buf + 1]->Unlock();
433#endif
434
435        stdshader->Bind();
436
437        /* Bind texture */
438        data->tiles[i].tileset->Bind();
439
440        /* Bind vertex, color and texture coordinate buffers */
441#if defined USE_D3D9 || defined _XBOX
442        g_d3ddevice->SetStreamSource(0, data->bufs[data->nbufs - 2], 0, 6 * 3 * (n - i) * sizeof(float));
443        g_d3ddevice->SetStreamSource(1, data->bufs[data->nbufs - 1], 0, 6 * 2 * (n - i) * sizeof(float));
444        g_d3ddevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, (n - i) * 6);
445#else
446#   if defined HAVE_GL_2X && !defined __APPLE__
447        glBindVertexArray(data->vao);
448#   endif
449#   if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
450        glEnableVertexAttribArray(attr_pos);
451        glEnableVertexAttribArray(attr_tex);
452
453        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf]);
454        glBufferData(GL_ARRAY_BUFFER, 18 * (n - i) * sizeof(GLfloat),
455                     vertex, GL_STATIC_DRAW);
456        glVertexAttribPointer(attr_pos, 3, GL_FLOAT, GL_FALSE, 0, 0);
457
458        glBindBuffer(GL_ARRAY_BUFFER, data->bufs[buf + 1]);
459        glBufferData(GL_ARRAY_BUFFER, 12 * (n - i) * sizeof(GLfloat),
460                     texture, GL_STATIC_DRAW);
461        glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, 0);
462#   else
463        glEnableClientState(GL_VERTEX_ARRAY);
464        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
465
466        glVertexPointer(3, GL_FLOAT, 0, vertex);
467        glTexCoordPointer(2, GL_FLOAT, 0, texture);
468#   endif
469
470        /* Draw arrays */
471        glDrawArrays(GL_TRIANGLES, 0, (n - i) * 6);
472
473#   if defined HAVE_GL_2X && !defined __APPLE__
474        glBindVertexArray(0);
475#   endif
476#   if !defined __CELLOS_LV2__ // Use cgGLEnableClientState etc.
477        glDisableVertexAttribArray(attr_pos);
478        glDisableVertexAttribArray(attr_tex);
479#   else
480        glDisableClientState(GL_VERTEX_ARRAY);
481        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
482#   endif
483
484        free(vertex);
485        free(texture);
486#endif
487    }
488
489    free(data->tiles);
490    data->tiles = 0;
491    data->ntiles = 0;
492
493#if defined USE_D3D9 || defined _XBOX
494    /* TODO */
495#else
496#if !defined HAVE_GLES_2X
497    glDisable(GL_TEXTURE_2D);
498#endif
499    glDisable(GL_DEPTH_TEST);
500#if defined HAVE_GL_2X && !defined __APPLE__
501    glDisable(GL_ALPHA_TEST);
502#endif
503    glDisable(GL_BLEND);
504#endif
505}
506
507} /* namespace lol */
508
Note: See TracBrowser for help on using the repository browser.