/*
* Copyright (c) 2011 Hypertriton, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* 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 AUTHOR 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
#include
#include
#include
SG_Map *
SG_MapNew(void *parent, const char *name)
{
SG_Map *m;
m = Malloc(sizeof(SG_Map));
AG_ObjectInitNamed(m, &sgMapClass, name);
AG_ObjectAttach(parent, m);
return (m);
}
static void
InitBlk(SG_Blk *_Nonnull b)
{
b->m = 0;
b->T = 25.0;
b->n = 0;
b->c = NULL;
}
static void
EditListPoll(AG_Event *_Nonnull event)
{
// SG_Map *m = AG_SELF();
// AG_Tlist *tl = AG_PTR(1);
// int depth = AG_INT(2);
}
static void
Init(void *_Nonnull obj)
{
SG_Map *m = obj;
m->flags = 0;
m->root = Malloc(sizeof(SG_Blk));
InitBlk(m->root);
AG_SetEvent(m, "edit-list-poll", EditListPoll, NULL);
}
static void
FreeBlk(SG_Blk *_Nonnull blk)
{
Uint i;
for (i = 0; i < blk->n; i++) {
FreeBlk(&blk->c[i]);
}
Free(blk->c);
}
static void
Reset(void *_Nonnull obj)
{
SG_Map *m = obj;
FreeBlk(m->root);
InitBlk(m->root);
}
int
SG_MapDivide(SG_Blk *bp, Uint n)
{
if (bp->n != 0) {
AG_SetError("Block is already divided by %u", bp->n);
return (-1);
}
bp->c = Malloc(sizeof(SG_Blk)*n*3);
bp->n = n;
return (0);
}
static void
DrawBlock(SG_Map *_Nonnull m, SG_Blk *_Nonnull b, SG_View *_Nonnull sgv,
M_Real bs)
{
M_Real uc[8][3] = {
{ 0.0, 0.0, 0.0 },
{ bs, 0.0, 0.0 },
{ bs, 0.0, bs },
{ 0.0, 0.0, bs },
{ 0.0, bs, 0.0 },
{ bs, bs, 0.0 },
{ bs, bs, bs },
{ 0.0, bs, bs },
};
int x, y, z;
M_Color C;
M_Vector3 cv;
M_Real cbs;
C = M_ColorRGB(0.0, 0.0, 0.0);
/* Render the block */
GL_Begin(GL_QUADS);
GL_MaterialColorv(GL_FRONT, GL_AMBIENT, &C);
GL_MaterialColorv(GL_FRONT, GL_DIFFUSE, &C);
GL_MaterialColorv(GL_FRONT, GL_SPECULAR, &C);
GL_Normal3(0.0, -1.0, 0.0); /* TOP */
GL_Vertex3v(&uc[7]);
GL_Vertex3v(&uc[6]);
GL_Vertex3v(&uc[5]);
GL_Vertex3v(&uc[4]);
GL_Normal3(0.0, +1.0, 0.0); /* BOTTOM */
GL_Vertex3v(&uc[1]);
GL_Vertex3v(&uc[2]);
GL_Vertex3v(&uc[3]);
GL_Vertex3v(&uc[0]);
GL_Normal3(0.0, 0.0, -1.0); /* FRONT */
GL_Vertex3v(&uc[4]);
GL_Vertex3v(&uc[5]);
GL_Vertex3v(&uc[1]);
GL_Vertex3v(&uc[0]);
GL_Normal3(0.0, 0.0, +1.0); /* BACK */
GL_Vertex3v(&uc[3]);
GL_Vertex3v(&uc[2]);
GL_Vertex3v(&uc[6]);
GL_Vertex3v(&uc[7]);
GL_Normal3(-1.0, 0.0, 0.0); /* LEFT */
GL_Vertex3v(&uc[3]);
GL_Vertex3v(&uc[7]);
GL_Vertex3v(&uc[4]);
GL_Vertex3v(&uc[0]);
GL_Normal3(+1.0, 0.0, 0.0); /* RIGHT */
GL_Vertex3v(&uc[5]);
GL_Vertex3v(&uc[6]);
GL_Vertex3v(&uc[2]);
GL_Vertex3v(&uc[1]);
GL_End();
/* Render the block cells */
GL_PushMatrix();
cbs = bs/b->n;
for (z = 0, cv.z = 0.0;
z < b->n;
z++, cv.z += cbs) {
for (y = 0, cv.y = 0.0;
y < b->n;
y++, cv.y += cbs) {
for (x = 0, cv.x = 0.0;
x < b->n;
x++, cv.z += cbs) {
SG_Blk *cb = SG_BlkGet(b, x,y,z);
GL_Translate(cv);
DrawBlock(m, cb, sgv, cbs);
}
}
}
GL_PopMatrix();
}
static void
Draw(void *_Nonnull obj, SG_View *_Nonnull sgv)
{
SG_Map *m = obj;
DrawBlock(m, m->root, sgv, 1.0);
}
static void *_Nullable
Edit(void *_Nonnull obj, SG_View *_Nullable sgv)
{
SG_Map *sgm = obj;
AG_Box *box;
box = AG_BoxNewVert(NULL, AG_BOX_HFILL);
AG_LabelNew(box, 0, "Map: %s", OBJECT(sgm)->name);
return (box);
}
SG_NodeClass sgMapClass = {
{
"SG_Node:SG_Map",
sizeof(SG_Map),
{ 0,0 },
Init,
Reset,
NULL, /* destroy */
NULL, /* load */
NULL, /* save */
SG_NodeEdit
},
NULL, /* menuInstance */
NULL, /* menuClass */
Draw,
NULL, /* intersect */
Edit
};