lighting and smooth lighting updated for anvil
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
// increment this value if you've made a change to the c extesion
|
// increment this value if you've made a change to the c extesion
|
||||||
// and want to force users to rebuild
|
// and want to force users to rebuild
|
||||||
#define OVERVIEWER_EXTENSION_VERSION 23
|
#define OVERVIEWER_EXTENSION_VERSION 24
|
||||||
|
|
||||||
/* Python PIL, and numpy headers */
|
/* Python PIL, and numpy headers */
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
@@ -148,6 +148,10 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
|
|||||||
{
|
{
|
||||||
int chunkx = 1, chunky = state->chunky, chunkz = 1;
|
int chunkx = 1, chunky = state->chunky, chunkz = 1;
|
||||||
PyObject *data_array = NULL;
|
PyObject *data_array = NULL;
|
||||||
|
unsigned int def = 0;
|
||||||
|
if (type == SKYLIGHT)
|
||||||
|
def = 15;
|
||||||
|
|
||||||
if (x >= 16) {
|
if (x >= 16) {
|
||||||
x -= 16;
|
x -= 16;
|
||||||
chunkx++;
|
chunkx++;
|
||||||
@@ -172,12 +176,12 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
|
|||||||
chunky--;
|
chunky--;
|
||||||
}
|
}
|
||||||
if (chunky < 0 || chunky >= SECTIONS_PER_CHUNK)
|
if (chunky < 0 || chunky >= SECTIONS_PER_CHUNK)
|
||||||
return 0;
|
return def;
|
||||||
|
|
||||||
if (!(state->chunks[chunkx][chunkz].loaded))
|
if (!(state->chunks[chunkx][chunkz].loaded))
|
||||||
{
|
{
|
||||||
if (load_chunk(state, chunkx - 1, chunkz - 1, 0))
|
if (load_chunk(state, chunkx - 1, chunkz - 1, 0))
|
||||||
return 0;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
@@ -197,7 +201,7 @@ static inline unsigned int get_data(RenderState *state, DataType type, int x, in
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (data_array == NULL)
|
if (data_array == NULL)
|
||||||
return 0;
|
return def;
|
||||||
|
|
||||||
if (type == BLOCKS)
|
if (type == BLOCKS)
|
||||||
return getArrayShort3D(data_array, x, y, z);
|
return getArrayShort3D(data_array, x, y, z);
|
||||||
|
|||||||
@@ -100,9 +100,6 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
int x, int y, int z, int *authoratative) {
|
int x, int y, int z, int *authoratative) {
|
||||||
|
|
||||||
/* placeholders for later data arrays, coordinates */
|
/* placeholders for later data arrays, coordinates */
|
||||||
PyObject *blocks = NULL;
|
|
||||||
PyObject *blocklight = NULL;
|
|
||||||
int local_x = x, local_y = y, local_z = z;
|
|
||||||
unsigned char block, blocklevel;
|
unsigned char block, blocklevel;
|
||||||
unsigned int average_count = 0, average_gather = 0, coeff = 0;
|
unsigned int average_count = 0, average_gather = 0, coeff = 0;
|
||||||
|
|
||||||
@@ -110,36 +107,7 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
if (authoratative)
|
if (authoratative)
|
||||||
*authoratative = 0;
|
*authoratative = 0;
|
||||||
|
|
||||||
/* find out what chunk we're in, and translate accordingly */
|
block = get_data(state, BLOCKS, x, y, z);
|
||||||
if (x >= 0 && y < 16) {
|
|
||||||
blocks = state->blocks;
|
|
||||||
blocklight = self->blocklight;
|
|
||||||
} else if (x < 0) {
|
|
||||||
local_x += 16;
|
|
||||||
blocks = state->left_blocks;
|
|
||||||
blocklight = self->left_blocklight;
|
|
||||||
} else if (y >= 16) {
|
|
||||||
local_y -= 16;
|
|
||||||
blocks = state->right_blocks;
|
|
||||||
blocklight = self->right_blocklight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure we have correctly-ranged coordinates */
|
|
||||||
if (!(local_x >= 0 && local_x < 16 &&
|
|
||||||
local_y >= 0 && local_y < 16 &&
|
|
||||||
local_z >= 0 && local_z < 128)) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* also, make sure we have enough info to correctly calculate lighting */
|
|
||||||
if (blocks == NULL ||
|
|
||||||
blocklight == NULL) {
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
block = getArrayByte3D(blocks, local_x, local_y, local_z);
|
|
||||||
|
|
||||||
if (authoratative == NULL) {
|
if (authoratative == NULL) {
|
||||||
int auth;
|
int auth;
|
||||||
@@ -149,16 +117,8 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
for (dx = -1; dx <= 1; dx += 2) {
|
for (dx = -1; dx <= 1; dx += 2) {
|
||||||
for (dy = -1; dy <= 1; dy += 2) {
|
for (dy = -1; dy <= 1; dy += 2) {
|
||||||
for (dz = -1; dz <= 1; dz += 2) {
|
for (dz = -1; dz <= 1; dz += 2) {
|
||||||
|
|
||||||
/* skip if block is out of range */
|
|
||||||
if (x+dx < 0 || x+dx >= 16 ||
|
|
||||||
y+dy < 0 || y+dy >= 16 ||
|
|
||||||
z+dz < 0 || z+dz >= 128) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth);
|
coeff = estimate_blocklevel(self, state, x+dx, y+dy, z+dz, &auth);
|
||||||
local_block = getArrayByte3D(blocks, x+dx, y+dy, z+dz);
|
local_block = get_data(state, BLOCKS, x+dx, y+dy, z+dz);
|
||||||
/* only add if the block is transparent, this seems to look better than
|
/* only add if the block is transparent, this seems to look better than
|
||||||
using every block */
|
using every block */
|
||||||
if (auth && is_transparent(local_block)) {
|
if (auth && is_transparent(local_block)) {
|
||||||
@@ -175,7 +135,7 @@ estimate_blocklevel(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
return average_gather / average_count;
|
return average_gather / average_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z);
|
blocklevel = get_data(state, BLOCKLIGHT, x, y, z);
|
||||||
|
|
||||||
/* no longer a guess */
|
/* no longer a guess */
|
||||||
if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109) && authoratative) {
|
if (!(block == 44 || block == 53 || block == 67 || block == 108 || block == 109) && authoratative) {
|
||||||
@@ -191,78 +151,26 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
unsigned char *r, unsigned char *g, unsigned char *b) {
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
|
||||||
/* placeholders for later data arrays, coordinates */
|
/* placeholders for later data arrays, coordinates */
|
||||||
PyObject *blocks = NULL;
|
|
||||||
PyObject *skylight = NULL;
|
|
||||||
PyObject *blocklight = NULL;
|
|
||||||
int local_x = x, local_y = y, local_z = z;
|
|
||||||
unsigned char block, skylevel, blocklevel;
|
unsigned char block, skylevel, blocklevel;
|
||||||
|
|
||||||
/* find out what chunk we're in, and translate accordingly */
|
block = get_data(state, BLOCKS, x, y, z);
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16) {
|
skylevel = get_data(state, SKYLIGHT, x, y, z);
|
||||||
blocks = state->blocks;
|
blocklevel = get_data(state, BLOCKLIGHT, x, y, z);
|
||||||
skylight = self->skylight;
|
|
||||||
blocklight = self->blocklight;
|
|
||||||
} else if (x < 0) {
|
|
||||||
local_x += 16;
|
|
||||||
blocks = state->left_blocks;
|
|
||||||
skylight = self->left_skylight;
|
|
||||||
blocklight = self->left_blocklight;
|
|
||||||
} else if (y >= 16) {
|
|
||||||
local_y -= 16;
|
|
||||||
blocks = state->right_blocks;
|
|
||||||
skylight = self->right_skylight;
|
|
||||||
blocklight = self->right_blocklight;
|
|
||||||
} else if (y < 0) {
|
|
||||||
local_y += 16;
|
|
||||||
blocks = state->up_left_blocks;
|
|
||||||
skylight = self->up_left_skylight;
|
|
||||||
blocklight = self->up_left_blocklight;
|
|
||||||
} else if (x >= 16) {
|
|
||||||
local_x -= 16;
|
|
||||||
blocks = state->up_right_blocks;
|
|
||||||
skylight = self->up_right_skylight;
|
|
||||||
blocklight = self->up_right_blocklight;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure we have correctly-ranged coordinates */
|
|
||||||
if (!(local_x >= 0 && local_x < 16 &&
|
|
||||||
local_y >= 0 && local_y < 16 &&
|
|
||||||
local_z >= 0 && local_z < 128)) {
|
|
||||||
|
|
||||||
self->calculate_light_color(self, 15, 0, r, g, b);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* also, make sure we have enough info to correctly calculate lighting */
|
|
||||||
if (!blocks ||
|
|
||||||
!skylight ||
|
|
||||||
!blocklight) {
|
|
||||||
|
|
||||||
self->calculate_light_color(self, 15, 0, r, g, b);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
block = getArrayByte3D(blocks, local_x, local_y, local_z);
|
|
||||||
skylevel = getArrayByte3D(skylight, local_x, local_y, local_z);
|
|
||||||
blocklevel = getArrayByte3D(blocklight, local_x, local_y, local_z);
|
|
||||||
|
|
||||||
/* special half-step handling, stairs handling */
|
/* special half-step handling, stairs handling */
|
||||||
if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114) {
|
if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114) {
|
||||||
unsigned int upper_block;
|
unsigned int upper_block;
|
||||||
|
|
||||||
/* stairs and half-blocks take the skylevel from the upper block if it's transparent */
|
/* stairs and half-blocks take the skylevel from the upper block if it's transparent */
|
||||||
if (local_z != 127) {
|
|
||||||
int upper_counter = 0;
|
int upper_counter = 0;
|
||||||
/* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */
|
/* but if the upper_block is one of these special half-steps, we need to look at *its* upper_block */
|
||||||
do {
|
do {
|
||||||
upper_counter++;
|
upper_counter++;
|
||||||
upper_block = getArrayByte3D(blocks, local_x, local_y, local_z + upper_counter);
|
upper_block = get_data(state, BLOCKS, x, y + upper_counter, z);
|
||||||
} while ((upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109) && local_z < 127);
|
} while (upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109 || upper_block == 114);
|
||||||
if (is_transparent(upper_block)) {
|
if (is_transparent(upper_block)) {
|
||||||
skylevel = getArrayByte3D(skylight, local_x, local_y, local_z + upper_counter);
|
skylevel = get_data(state, SKYLIGHT, x, y + upper_counter, z);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
upper_block = 0;
|
|
||||||
skylevel = 15;
|
skylevel = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,24 +195,15 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state,
|
|||||||
inline int
|
inline int
|
||||||
lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z) {
|
lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z) {
|
||||||
/* first, check for occlusion if the block is in the local chunk */
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 16) {
|
||||||
unsigned char block = getArrayByte3D(state->blocks, x, y, z);
|
unsigned short block = getArrayShort3D(state->blocks, x, y, z);
|
||||||
|
|
||||||
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
|
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
|
||||||
/* this face isn't visible, so don't draw anything */
|
/* this face isn't visible, so don't draw anything */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else if (skip_sides && (x == -1) && (state->left_blocks != NULL)) {
|
} else if (skip_sides) {
|
||||||
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, state->z);
|
unsigned short block = get_data(state, BLOCKS, x, y, z);
|
||||||
if (!is_transparent(block)) {
|
|
||||||
/* the same thing but for adjacent chunks, this solves an
|
|
||||||
ugly black doted line between chunks in night rendermode.
|
|
||||||
This wouldn't be necessary if the textures were truly
|
|
||||||
tessellate-able */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else if (skip_sides && (y == 16) && (state->right_blocks != NULL)) {
|
|
||||||
unsigned char block = getArrayByte3D(state->right_blocks, state->x, 0, state->z);
|
|
||||||
if (!is_transparent(block)) {
|
if (!is_transparent(block)) {
|
||||||
/* the same thing but for adjacent chunks, this solves an
|
/* the same thing but for adjacent chunks, this solves an
|
||||||
ugly black doted line between chunks in night rendermode.
|
ugly black doted line between chunks in night rendermode.
|
||||||
@@ -343,8 +242,8 @@ lighting_start(void *data, RenderState *state, PyObject *support) {
|
|||||||
RenderPrimitiveLighting* self;
|
RenderPrimitiveLighting* self;
|
||||||
self = (RenderPrimitiveLighting *)data;
|
self = (RenderPrimitiveLighting *)data;
|
||||||
|
|
||||||
/* don't skip sides by default */
|
/* skip sides by default */
|
||||||
self->skip_sides = 0;
|
self->skip_sides = 1;
|
||||||
|
|
||||||
if (!render_mode_parse_option(support, "strength", "f", &(self->strength)))
|
if (!render_mode_parse_option(support, "strength", "f", &(self->strength)))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -359,17 +258,6 @@ lighting_start(void *data, RenderState *state, PyObject *support) {
|
|||||||
self->facemasks[1] = PyTuple_GetItem(self->facemasks_py, 1);
|
self->facemasks[1] = PyTuple_GetItem(self->facemasks_py, 1);
|
||||||
self->facemasks[2] = PyTuple_GetItem(self->facemasks_py, 2);
|
self->facemasks[2] = PyTuple_GetItem(self->facemasks_py, 2);
|
||||||
|
|
||||||
self->skylight = get_chunk_data(state, CURRENT, SKYLIGHT, 1);
|
|
||||||
self->blocklight = get_chunk_data(state, CURRENT, BLOCKLIGHT, 1);
|
|
||||||
self->left_skylight = get_chunk_data(state, DOWN_LEFT, SKYLIGHT, 1);
|
|
||||||
self->left_blocklight = get_chunk_data(state, DOWN_LEFT, BLOCKLIGHT, 1);
|
|
||||||
self->right_skylight = get_chunk_data(state, DOWN_RIGHT, SKYLIGHT, 1);
|
|
||||||
self->right_blocklight = get_chunk_data(state, DOWN_RIGHT, BLOCKLIGHT, 1);
|
|
||||||
self->up_left_skylight = get_chunk_data(state, UP_LEFT, SKYLIGHT, 1);
|
|
||||||
self->up_left_blocklight = get_chunk_data(state, UP_LEFT, BLOCKLIGHT, 1);
|
|
||||||
self->up_right_skylight = get_chunk_data(state, UP_RIGHT, SKYLIGHT, 1);
|
|
||||||
self->up_right_blocklight = get_chunk_data(state, UP_RIGHT, BLOCKLIGHT, 1);
|
|
||||||
|
|
||||||
if (self->night) {
|
if (self->night) {
|
||||||
self->calculate_light_color = calculate_light_color_night;
|
self->calculate_light_color = calculate_light_color_night;
|
||||||
} else {
|
} else {
|
||||||
@@ -401,17 +289,6 @@ lighting_finish(void *data, RenderState *state) {
|
|||||||
RenderPrimitiveLighting *self = (RenderPrimitiveLighting *)data;
|
RenderPrimitiveLighting *self = (RenderPrimitiveLighting *)data;
|
||||||
|
|
||||||
Py_DECREF(self->facemasks_py);
|
Py_DECREF(self->facemasks_py);
|
||||||
|
|
||||||
Py_DECREF(self->skylight);
|
|
||||||
Py_DECREF(self->blocklight);
|
|
||||||
Py_XDECREF(self->left_skylight);
|
|
||||||
Py_XDECREF(self->left_blocklight);
|
|
||||||
Py_XDECREF(self->right_skylight);
|
|
||||||
Py_XDECREF(self->right_blocklight);
|
|
||||||
Py_XDECREF(self->up_left_skylight);
|
|
||||||
Py_XDECREF(self->up_left_blocklight);
|
|
||||||
Py_XDECREF(self->up_right_skylight);
|
|
||||||
Py_XDECREF(self->up_right_blocklight);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -427,13 +304,13 @@ lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyO
|
|||||||
* blocks that are transparent for occlusion calculations and
|
* blocks that are transparent for occlusion calculations and
|
||||||
* need per-face shading if the face is drawn. */
|
* need per-face shading if the face is drawn. */
|
||||||
if ((state->block_pdata & 16) == 16) {
|
if ((state->block_pdata & 16) == 16) {
|
||||||
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[0]);
|
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[0]);
|
||||||
}
|
}
|
||||||
if ((state->block_pdata & 2) == 2) { /* bottom left */
|
if ((state->block_pdata & 2) == 2) { /* bottom left */
|
||||||
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
|
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
|
||||||
}
|
}
|
||||||
if ((state->block_pdata & 4) == 4) { /* bottom right */
|
if ((state->block_pdata & 4) == 4) { /* bottom right */
|
||||||
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[2]);
|
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[2]);
|
||||||
}
|
}
|
||||||
/* leaves are transparent for occlusion calculations but they
|
/* leaves are transparent for occlusion calculations but they
|
||||||
* per face-shading to look as in game */
|
* per face-shading to look as in game */
|
||||||
@@ -442,9 +319,9 @@ lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyO
|
|||||||
do_shading_with_mask(self, state, x, y, z, mask_light);
|
do_shading_with_mask(self, state, x, y, z, mask_light);
|
||||||
} else {
|
} else {
|
||||||
/* opaque: do per-face shading */
|
/* opaque: do per-face shading */
|
||||||
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[0]);
|
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[0]);
|
||||||
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
|
do_shading_with_mask(self, state, x-1, y, z, self->facemasks[1]);
|
||||||
do_shading_with_mask(self, state, x, y+1, z, self->facemasks[2]);
|
do_shading_with_mask(self, state, x, y, z+1, self->facemasks[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,6 @@ typedef struct {
|
|||||||
PyObject *facemasks_py;
|
PyObject *facemasks_py;
|
||||||
PyObject *facemasks[3];
|
PyObject *facemasks[3];
|
||||||
|
|
||||||
/* extra data, loaded off the chunk class */
|
|
||||||
PyObject *skylight, *blocklight;
|
|
||||||
PyObject *left_skylight, *left_blocklight;
|
|
||||||
PyObject *right_skylight, *right_blocklight;
|
|
||||||
PyObject *up_left_skylight, *up_left_blocklight;
|
|
||||||
PyObject *up_right_skylight, *up_right_blocklight;
|
|
||||||
|
|
||||||
/* light color image, loaded if color_light is True */
|
/* light color image, loaded if color_light is True */
|
||||||
PyObject *lightcolor;
|
PyObject *lightcolor;
|
||||||
|
|
||||||
|
|||||||
@@ -69,53 +69,53 @@ static struct SmoothLightingFace lighting_rules[] = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* top */
|
/* top */
|
||||||
{0, 0, 1, {
|
{0, 1, 0, {
|
||||||
{0, 6,
|
{0, 6,
|
||||||
-1, 0, 0,
|
-1, 0, 0,
|
||||||
0, -1, 0},
|
0, 0, -1},
|
||||||
{12, 0,
|
{12, 0,
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, -1, 0},
|
0, 0, -1},
|
||||||
{24, 6,
|
{24, 6,
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 1, 0},
|
0, 0, 1},
|
||||||
{12, 12,
|
{12, 12,
|
||||||
-1, 0, 0,
|
-1, 0, 0,
|
||||||
0, 1, 0},
|
0, 0, 1},
|
||||||
},
|
},
|
||||||
top_touchups, 3},
|
top_touchups, 3},
|
||||||
|
|
||||||
/* left */
|
/* left */
|
||||||
{-1, 0, 0, {
|
{-1, 0, 0, {
|
||||||
{0, 18,
|
{0, 18,
|
||||||
0, -1, 0,
|
0, 0, -1,
|
||||||
0, 0, -1},
|
0, -1, 0},
|
||||||
{0, 6,
|
{0, 6,
|
||||||
0, -1, 0,
|
0, 0, -1,
|
||||||
0, 0, 1},
|
0, 1, 0},
|
||||||
{12, 12,
|
{12, 12,
|
||||||
0, 1, 0,
|
0, 0, 1,
|
||||||
0, 0, 1},
|
0, 1, 0},
|
||||||
{12, 24,
|
{12, 24,
|
||||||
0, 1, 0,
|
0, 0, 1,
|
||||||
0, 0, -1},
|
0, -1, 0},
|
||||||
},
|
},
|
||||||
NULL, 0},
|
NULL, 0},
|
||||||
|
|
||||||
/* right */
|
/* right */
|
||||||
{0, 1, 0, {
|
{0, 0, 1, {
|
||||||
{24, 6,
|
{24, 6,
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 0, 1},
|
0, 1, 0},
|
||||||
{12, 12,
|
{12, 12,
|
||||||
-1, 0, 0,
|
-1, 0, 0,
|
||||||
0, 0, 1},
|
0, 1, 0},
|
||||||
{12, 24,
|
{12, 24,
|
||||||
-1, 0, 0,
|
-1, 0, 0,
|
||||||
0, 0, -1},
|
0, -1, 0},
|
||||||
{24, 18,
|
{24, 18,
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 0, -1},
|
0, -1, 0},
|
||||||
},
|
},
|
||||||
NULL, 0},
|
NULL, 0},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user