/* * 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 };