const char *ceiling(int x, int y) { struct rm *loc = &level->locations[x][y]; const char *what; /* other room types will no longer exist when we're interested -- * see check_special_room() */ if (*in_rooms(level, x, y, VAULT)) what = "vault's ceiling"; else if (*in_rooms(level, x, y, TEMPLE)) what = "temple's ceiling"; else if (*in_rooms(level, x, y, SHOPBASE)) what = "shop's ceiling"; else if (IS_AIR(loc->typ)) what = "sky"; else if (Underwater) what = "water's surface"; else if ((IS_ROOM(loc->typ) && !Is_earthlevel(&u.uz)) || IS_WALL(loc->typ) || IS_DOOR(loc->typ) || loc->typ == SDOOR) what = "ceiling"; else what = "rock above"; return what; }
const char *surface(int x, int y) { struct rm *loc = &level->locations[x][y]; if ((x == u.ux) && (y == u.uy) && u.uswallow && is_animal(u.ustuck->data)) return "maw"; else if (IS_AIR(loc->typ) && Is_airlevel(&u.uz)) return "air"; else if (is_pool(level, x, y)) return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : "water"; else if (is_ice(level, x, y)) return "ice"; else if (is_lava(level, x, y)) return "lava"; else if (loc->typ == DRAWBRIDGE_DOWN) return "bridge"; else if (IS_ALTAR(level->locations[x][y].typ)) return "altar"; else if (IS_GRAVE(level->locations[x][y].typ)) return "headstone"; else if (IS_FOUNTAIN(level->locations[x][y].typ)) return "fountain"; else if ((IS_ROOM(loc->typ) && !Is_earthlevel(&u.uz)) || IS_WALL(loc->typ) || IS_DOOR(loc->typ) || loc->typ == SDOOR) return "floor"; else return "ground"; }
static void trv_door_startopen (void) { FAR struct trv_rect_data_s *rect; /* Check if a door is already opening */ if (g_opendoor.state == DOOR_IDLE) { /* Test if there is a door within three steps in front of the player */ /* Try the X planes first */ rect = trv_ray_test_xplane(&g_player, 3*STEP_DISTANCE, g_player.yaw, g_player_height); /* If there is no X door in front of the player, then try the Y Planes * (it is assumed that there would not be doors this close in both * planes!) */ if (!rect || !IS_DOOR(rect)) { rect = trv_ray_test_yplane(&g_player, 3*STEP_DISTANCE, g_player.yaw, g_player_height); } /* Check if we found a door in either the X or Y plane. */ if (rect && IS_DOOR(rect)) { /* We now have found a door to open. Set the door open sequence * in motion */ g_opendoor.rect = rect; g_opendoor.state = DOOR_OPENING; g_opendoor.zbottom = rect->vstart; g_opendoor.zdist = 0; /* Mark the door's attribute to indicate that it is in motion */ rect->attribute |= MOVING_DOOR_PLANE; } } }
// Pretty-prints the tile at the given position. static void display_tile(Coords pos) { Tile *tile = &TILE(pos); int light = shadowed(pos) ? 0 : L2(pos - player.pos) <= player.radius ? 7777 : min(tile->light, 7777); printf("\033[38;5;%dm", 232 + light / 338); print_at(pos, tile_glyphs[tile->type]); if (IS_DIGGABLE(pos) && !IS_DOOR(pos)) display_wall(pos); if (IS_WIRE(pos) && !IS_DOOR(pos)) display_wire(pos); if (tile->item) print_at(pos, item_glyphs[tile->item]); if (!tile->revealed) print_at(pos, " "); }
STATIC_OVL boolean iswall(int x, int y) { register int type; if (!isok(x,y)) return FALSE; type = levl[x][y].typ; return (IS_WALL(type) || IS_DOOR(type) || type == SDOOR || type == IRONBARS); }
STATIC_OVL boolean iswall_or_stone(int x, int y) { register int type; /* out of bounds = stone */ if (!isok(x,y)) return TRUE; type = levl[x][y].typ; return (type == STONE || IS_WALL(type) || IS_DOOR(type) || type == SDOOR || type == IRONBARS); }
bool nexttodoor (int sx, int sy) { int dx, dy; struct rm *lev; for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) { if(!isok(sx+dx, sy+dy)) continue; if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) || lev->typ == SDOOR) return(true); } return(false); }
boolean nexttodoor(struct level * lev, int sx, int sy) { int dx, dy; struct rm *loc; for (dx = -1; dx <= 1; dx++) for (dy = -1; dy <= 1; dy++) { if (!isok(sx + dx, sy + dy)) continue; if (IS_DOOR((loc = &lev->locations[sx + dx][sy + dy])->typ) || loc->typ == SDOOR) return TRUE; } return FALSE; }
/* * use a flooding algorithm to find all locations that should * have the same rm number as the current location. * if anyroom is TRUE, use IS_ROOM to check room membership instead of * exactly matching level->locations[sx][sy].typ and walls are included as well. */ void flood_fill_rm(struct level *lev, int sx, int sy, int rmno, boolean lit, boolean anyroom) { int i; int nx; schar fg_typ = lev->locations[sx][sy].typ; /* back up to find leftmost uninitialized location */ while (sx >= 0 && (anyroom ? IS_ROOM(lev->locations[sx][sy].typ) : lev->locations[sx][sy].typ == fg_typ) && (int)lev->locations[sx][sy].roomno != rmno) sx--; sx++; /* compensate for extra decrement */ /* assume sx,sy is valid */ if (sx < min_rx) min_rx = sx; if (sy < min_ry) min_ry = sy; for (i = sx; i <= WIDTH && lev->locations[i][sy].typ == fg_typ; i++) { lev->locations[i][sy].roomno = rmno; lev->locations[i][sy].lit = lit; if (anyroom) { /* add walls to room as well */ int ii, jj; for (ii = (i == sx ? i - 1 : i); ii <= i + 1; ii++) for (jj = sy - 1; jj <= sy + 1; jj++) if (isok(ii, jj) && (IS_WALL(lev->locations[ii][jj].typ) || IS_DOOR(lev->locations[ii][jj].typ))) { lev->locations[ii][jj].edge = 1; if (lit) lev->locations[ii][jj].lit = lit; if ((int)lev->locations[ii][jj].roomno != rmno) lev->locations[ii][jj].roomno = SHARED; } } n_loc_filled++; } nx = i; if (isok(sx, sy - 1)) { for (i = sx; i < nx; i++) if (lev->locations[i][sy - 1].typ == fg_typ) { if ((int)lev->locations[i][sy - 1].roomno != rmno) flood_fill_rm(lev, i, sy - 1, rmno, lit, anyroom); } else { if ((i > sx || isok(i - 1, sy - 1)) && lev->locations[i - 1][sy - 1].typ == fg_typ) { if ((int)lev->locations[i - 1][sy - 1].roomno != rmno) flood_fill_rm(lev, i - 1, sy - 1, rmno, lit, anyroom); } if ((i < nx - 1 || isok(i + 1, sy - 1)) && lev->locations[i + 1][sy - 1].typ == fg_typ) { if ((int)lev->locations[i + 1][sy - 1].roomno != rmno) flood_fill_rm(lev, i + 1, sy - 1, rmno, lit, anyroom); } } } if (isok(sx, sy + 1)) { for (i = sx; i < nx; i++) if (lev->locations[i][sy + 1].typ == fg_typ) { if ((int)lev->locations[i][sy + 1].roomno != rmno) flood_fill_rm(lev, i, sy + 1, rmno, lit, anyroom); } else { if ((i > sx || isok(i - 1, sy + 1)) && lev->locations[i - 1][sy + 1].typ == fg_typ) { if ((int)lev->locations[i - 1][sy + 1].roomno != rmno) flood_fill_rm(lev, i - 1, sy + 1, rmno, lit, anyroom); } if ((i < nx - 1 || isok(i + 1, sy + 1)) && lev->locations[i + 1][sy + 1].typ == fg_typ) { if ((int)lev->locations[i + 1][sy + 1].roomno != rmno) flood_fill_rm(lev, i + 1, sy + 1, rmno, lit, anyroom); } } } if (nx > max_rx) max_rx = nx - 1; /* nx is just past valid region */ if (sy > max_ry) max_ry = sy; }
/* try to close a door */ int doclose(const struct nh_cmd_arg *arg) { struct rm *door; struct monst *mtmp; coord cc; schar dx, dy, dz; if (nohands(youmonst.data)) { pline(msgc_cancelled, "You can't close anything -- you have no hands!"); return 0; } if (u.utrap && u.utraptype == TT_PIT) { pline(msgc_cancelled, "You can't reach over the edge of the pit."); return 0; } if (!getargdir(arg, NULL, &dx, &dy, &dz)) return 0; cc.x = youmonst.mx + dx; cc.y = youmonst.my + dy; if (!isok(cc.x, cc.y)) return 0; if ((cc.x == youmonst.mx) && (cc.y == youmonst.my)) { pline(msgc_cancelled1, "You are in the way!"); return 1; } if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE && (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp, dx, dy); return 1; } door = &level->locations[cc.x][cc.y]; if (!IS_DOOR(door->typ)) { if (door->typ == DRAWBRIDGE_DOWN) pline(msgc_cancelled, "There is no obvious way to close the drawbridge."); else pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see"); return 0; } if (door->doormask == D_NODOOR) { pline(msgc_cancelled, "This doorway has no door."); return 0; } if (obstructed(cc.x, cc.y, msgc_cancelled)) return 0; if (door->doormask == D_BROKEN) { pline(msgc_cancelled, "This door is broken."); return 0; } if (door->doormask & (D_CLOSED | D_LOCKED)) { pline(msgc_cancelled, "This door is already closed."); return 0; } if (door->doormask == D_ISOPEN) { if (verysmall(youmonst.data) && !u.usteed) { pline(msgc_cancelled, "You're too small to push the door closed."); return 0; } if (u.usteed || rn2(25) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) { pline(msgc_actionok, "The door closes."); door->doormask = D_CLOSED; door->mem_door_l = 1; /* map_background here sets the mem_door flags correctly; and it's redundant to both feel_location and newsym with a door. Exception: if we remember an invisible monster on the door square, but in this case, we want to set the memory of a door there anyway because we know there's a door there because we just closed it, and in Nitro this doesn't clash with keeping the I there. */ map_background(cc.x, cc.y, TRUE); if (Blind) feel_location(cc.x, cc.y); /* the hero knows she closed it */ else newsym(cc.x, cc.y); block_point(cc.x, cc.y); /* vision: no longer see there */ } else { exercise(A_STR, TRUE); pline(msgc_failrandom, "The door resists!"); } } return 1; }
/* try to open a door */ int doopen(const struct nh_cmd_arg *arg) { coord cc; struct rm *door; struct monst *mtmp; schar dx, dy, dz; if (nohands(youmonst.data)) { pline(msgc_cancelled, "You can't open, close, or unlock anything " "-- you have no hands!"); return 0; } if (u.utrap && u.utraptype == TT_PIT) { pline(msgc_cancelled, "You can't reach over the edge of the pit."); return 0; } if (!getargdir(arg, NULL, &dx, &dy, &dz)) return 0; cc.x = youmonst.mx + dx; cc.y = youmonst.my + dy; if (!isok(cc.x, cc.y)) return 0; if ((cc.x == youmonst.mx) && (cc.y == youmonst.my)) return 0; if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE && (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp, cc.x - youmonst.mx, cc.y - youmonst.my); return 1; } door = &level->locations[cc.x][cc.y]; if (!IS_DOOR(door->typ)) { if (is_db_wall(cc.x, cc.y)) { pline(msgc_cancelled, "There is no obvious way to open the drawbridge."); return 0; } pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see"); return 0; } if (door->doormask == D_ISOPEN) { struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); return doclose(&newarg); } if (!(door->doormask & D_CLOSED)) { const char *mesg; switch (door->doormask) { case D_BROKEN: mesg = " is broken"; break; case D_NODOOR: mesg = "way has no door"; break; case D_ISOPEN: mesg = " is already open"; break; default: if (last_command_was("open") && door->mem_door_l) { /* With the "open" command given explicitly (rather than implicitly via doorbumping), unlock the door. */ struct obj *bestpick = get_current_unlock_tool(); struct nh_cmd_arg newarg; arg_from_delta(dx, dy, dz, &newarg); if (!bestpick) pline(msgc_cancelled, "You have nothing to unlock that with."); else if (!bestpick->lastused) /* not msgc_controlhelp, or many players would get no message */ pline(msgc_hint, "Use an unlocking tool manually so I know " "which one you want to use."); else return pick_lock(bestpick, &newarg); } door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); mesg = " is locked"; break; } pline(msgc_cancelled, "This door%s.", mesg); if (Blind) feel_location(cc.x, cc.y); return 0; } if (verysmall(youmonst.data)) { pline(msgc_cancelled, "You're too small to pull the door open."); return 0; } /* door is known to be CLOSED */ if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) { pline(msgc_actionok, "The door opens."); if (door->doormask & D_TRAPPED) { b_trapped("door", FINGER); door->doormask = D_NODOOR; if (*in_rooms(level, cc.x, cc.y, SHOPBASE)) add_damage(cc.x, cc.y, 0L); } else door->doormask = D_ISOPEN; if (Blind) feel_location(cc.x, cc.y); /* the hero knows she opened it */ else newsym(cc.x, cc.y); unblock_point(cc.x, cc.y); /* vision: new see through there */ } else { exercise(A_STR, TRUE); door->mem_door_l = 1; map_background(cc.x, cc.y, TRUE); pline(msgc_failrandom, "The door resists!"); } return 1; }
/* pick a lock on a chest or door with a given object */ int pick_lock(struct obj *pick, const struct nh_cmd_arg *arg) { int picktyp, c; coord cc; schar dx, dy, dz; struct rm *door; struct obj *otmp; const char *qbuf; if (!getargdir(arg, NULL, &dx, &dy, &dz)) return 0; cc.x = youmonst.mx + dx; cc.y = youmonst.my + dy; if (!isok(cc.x, cc.y)) return 0; picktyp = pick->otyp; pick->lastused = moves; /* Check whether we're resuming an interrupted previous attempt. For a floor pick, we have u.utracked[tos_lock] as a non-zeroobj and dx and dy as 0. For a door, we have u.utracked_location[tl_lock] specifying the location and u.utracked[tos_lock] as &zeroobj. */ if (u.uoccupation_progress[tos_lock] && ((u.utracked_location[tl_lock].x == cc.x && u.utracked_location[tl_lock].y == cc.y && u.utracked[tos_lock] == &zeroobj) || (dx == 0 && dy == 0 && u.utracked[tos_lock] != &zeroobj))) { static const char no_longer[] = "Unfortunately, you can no longer %s %s."; if (nohands(youmonst.data)) { const char *what = (picktyp == LOCK_PICK) ? "pick" : "key"; if (picktyp == CREDIT_CARD) what = "card"; pline(msgc_interrupted, no_longer, "hold the", what); return reset_pick(); } else if (u.utracked[tos_lock] != &zeroobj && !can_reach_floor()) { pline(msgc_interrupted, no_longer, "reach the", "lock"); return reset_pick(); } else { const char *action = lock_action(); if (turnstate.continue_message) pline(msgc_occstart, "You resume your attempt at %s.", action); one_occupation_turn(picklock, "picking the lock", occ_lock); return 1; } } if (nohands(youmonst.data)) { pline(msgc_cancelled, "You can't hold %s -- you have no hands!", doname(pick)); return 0; } if ((picktyp != LOCK_PICK && picktyp != CREDIT_CARD && picktyp != SKELETON_KEY)) { impossible("picking lock with object %d?", picktyp); return 0; } if (!dx && !dy) { /* pick lock on a container */ const char *verb; boolean it; int count; if (dz < 0) { pline(msgc_cancelled, "There isn't any sort of lock up %s.", Levitation ? "here" : "there"); return 0; } else if (is_lava(level, youmonst.mx, youmonst.my)) { pline(msgc_cancelled, "Doing that would probably melt your %s.", xname(pick)); return 0; } else if (is_pool(level, youmonst.mx, youmonst.my) && !Underwater) { /* better YAFM - AIS */ pline(msgc_cancelled, "Canals might have locks, but this water doesn't."); return 0; } count = 0; c = 'n'; /* in case there are no boxes here */ for (otmp = level->objects[cc.x][cc.y]; otmp; otmp = otmp->nexthere) if (Is_box(otmp)) { ++count; if (!can_reach_floor()) { pline(msgc_cancelled, "You can't reach %s from up here.", the(xname(otmp))); return 0; } it = 0; if (otmp->obroken) verb = "fix"; else if (!otmp->olocked) verb = "lock", it = 1; else if (picktyp != LOCK_PICK) verb = "unlock", it = 1; else verb = "pick"; qbuf = msgprintf( "There is %s here, %s %s?", safe_qbuf("", sizeof ("There is here, unlock its lock?"), doname(otmp), an(simple_typename(otmp->otyp)), "a box"), verb, it ? "it" : "its lock"); c = ynq(qbuf); if (c == 'q') return 0; if (c == 'n') continue; if (otmp->obroken) { pline(msgc_cancelled, "You can't fix its broken lock with %s.", doname(pick)); return 0; } else if (picktyp == CREDIT_CARD && !otmp->olocked) { /* credit cards are only good for unlocking */ pline(msgc_cancelled, "You can't do that with %s.", doname(pick)); return 0; } u.utracked[tos_lock] = otmp; u.uoccupation_progress[tos_lock] = 0; break; } if (c != 'y') { if (!count) pline(msgc_cancelled, "There doesn't seem to be any sort of lock here."); return 0; /* decided against all boxes */ } } else { /* pick the lock in a door */ struct monst *mtmp; if (u.utrap && u.utraptype == TT_PIT) { pline(msgc_cancelled, "You can't reach over the edge of the pit."); return 0; } door = &level->locations[cc.x][cc.y]; if ((mtmp = m_at(level, cc.x, cc.y)) && canseemon(mtmp)) { if (picktyp == CREDIT_CARD && (mx_eshk(mtmp) || mtmp->data == &mons[PM_ORACLE])) verbalize(msgc_npcvoice, "No checks, no credit, no problem."); else pline(msgc_mispaste, "I don't think %s would appreciate that.", mon_nam(mtmp)); return 0; } if (mtmp && (mtmp->m_ap_type == M_AP_FURNITURE) && (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) && !Protection_from_shape_changers) { stumble_onto_mimic(mtmp, dx, dy); return 1; } if (!IS_DOOR(door->typ)) { if (is_drawbridge_wall(cc.x, cc.y) >= 0) pline(msgc_cancelled, "You %s no lock on the drawbridge.", Blind ? "feel" : "see"); else pline(msgc_mispaste, "You %s no door there.", Blind ? "feel" : "see"); return 0; } switch (door->doormask) { case D_NODOOR: pline(msgc_cancelled, "This doorway has no door."); return 0; case D_ISOPEN: pline(msgc_cancelled, "You cannot lock an open door."); return 0; case D_BROKEN: pline(msgc_cancelled, "This door is broken."); return 0; default: /* credit cards are only good for unlocking */ if (picktyp == CREDIT_CARD && !(door->doormask & D_LOCKED)) { pline(msgc_cancelled, "You can't lock a door with a credit card."); return 0; } /* At this point, the player knows that the door is a door, and whether it's locked, but not whether it's trapped; to do this, we set the mem_door_l flag and call map_background, which will clear it if necessary (i.e. not a door after all). */ level->locations[cc.x][cc.y].mem_door_l = 1; map_background(cc.x, cc.y, TRUE); u.utracked[tos_lock] = &zeroobj; u.utracked_location[tl_lock] = cc; u.uoccupation_progress[tos_lock] = 0; } } one_occupation_turn(picklock, "picking the lock", occ_lock); return 1; }
/* when attacking "priest" in his temple */ void ghod_hitsu(struct monst *priest) { int x, y, ax, ay, roomno = (int)temple_occupied(u.urooms); struct mkroom *troom; if (!roomno || !has_shrine(priest)) return; ax = x = CONST_EPRI(priest)->shrpos.x; ay = y = CONST_EPRI(priest)->shrpos.y; troom = &level->rooms[roomno - ROOMOFFSET]; if ((u.ux == x && u.uy == y) || !linedup(u.ux, u.uy, x, y)) { if (IS_DOOR(level->locations[u.ux][u.uy].typ)) { if (u.ux == troom->lx - 1) { x = troom->hx; y = u.uy; } else if (u.ux == troom->hx + 1) { x = troom->lx; y = u.uy; } else if (u.uy == troom->ly - 1) { x = u.ux; y = troom->hy; } else if (u.uy == troom->hy + 1) { x = u.ux; y = troom->ly; } } else { switch (rn2(4)) { case 0: x = u.ux; y = troom->ly; break; case 1: x = u.ux; y = troom->hy; break; case 2: x = troom->lx; y = u.uy; break; default: x = troom->hx; y = u.uy; break; } } if (!linedup(u.ux, u.uy, x, y)) return; } switch (rn2(3)) { case 0: pline("%s roars in anger: \"Thou shalt suffer!\"", a_gname_at(ax, ay)); break; case 1: pline("%s voice booms: \"How darest thou harm my servant!\"", s_suffix(a_gname_at(ax, ay))); break; default: pline("%s roars: \"Thou dost profane my shrine!\"", a_gname_at(ax, ay)); break; } /* bolt of lightning */ buzz(-10 - (AD_ELEC - 1), 6, x, y, sgn(tbx), sgn(tby), 0); }
void noegnud_render_map_tile () { int x, y; int xs,xe,xd; int ys,ye,yd; GLfloat current_alpha; float nx, ny; float realangle; GLfloat light_position[4]; ys=0; ye=MAX_MAP_Y; yd=1; xs=0; xe=MAX_MAP_X; xd=1; realangle=(noegnud_options_render_opengl_view_angle_x_current->value+(noegnud_activetileset->iso?0:noegnud_render_bullettime_angle)); while (realangle>=360) realangle-=360; while (realangle<0) realangle+=360; if ((realangle>=90)&&(realangle<270)) { ys=MAX_MAP_Y-1; ye=-1; yd=-1; } if ((realangle<=180)) { xs=MAX_MAP_X-1; xe=-1; xd=-1; } if (noegnud_render_selection_busy) { glDisable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_BLEND); } if (noegnud_activetileset->iso) { glEnable (GL_BLEND); glDisable (GL_DEPTH_TEST); } else { glDisable (GL_BLEND); if (noegnud_options_render_features_cardboardcutout->value&&noegnud_activetileset->isalphatileset) { glEnable (GL_DEPTH_TEST); } else glDisable (GL_DEPTH_TEST); } if (noegnud_options_render_opengl_lighting_method->value==NOEGNUD_RENDER_LIGHTING_METHOD_CHEAP) { glEnable(GL_LIGHTING); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHT0); if ((noegnud_options_input_mouse_3d_light->value)&&noegnud_render_mouse_map_x!=-1) { glEnable(GL_LIGHT1); } else { glDisable(GL_LIGHT1); } } x=noegnud_clip_x; y=noegnud_clip_y; ny = -(y - (noegnud_render_middle_y)); nx = x - (noegnud_render_middle_x); light_position[0]=noegnud_activetileset->glwidth/2; light_position[1]=noegnud_activetileset->glheight*3/2; light_position[2]=noegnud_activetileset->glheight; light_position[3]=1; glTranslatef ( (noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x, 0, -((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y); glLightfv(GL_LIGHT0,GL_POSITION,light_position); if (noegnud_options_input_mouse_3d_light->value) { ny = -(noegnud_render_mouse_map_y - (noegnud_render_middle_y)); nx = (noegnud_render_mouse_map_x-1) - (noegnud_render_middle_x); light_position[0]+=(noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x; light_position[2]+=-((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y; glLightfv(GL_LIGHT1,GL_POSITION,light_position); } for (y = 0; y < MAX_MAP_Y; y++) { ny = -(y - (noegnud_render_middle_y)); for (x = 0; x < MAX_MAP_X; x++) { nx = x - (noegnud_render_middle_x); glPopMatrix (); glPushMatrix (); glTranslatef ( (noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x, 0, -((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y); glLoadName(y*256+x); glBegin(GL_LINES); glEnd(); /* if (noegnud_options_input_mouse_3d_light->value&&((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glLightfv(GL_LIGHT1,GL_POSITION,light_position); } */ if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.25,1.0,0.25,1.0); } else if ((x == noegnud_clip_x) && (y == noegnud_clip_y)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,1.0); } else if ((!noegnud_activetileset->isalphatileset)&&iflags.hilite_pet&&(noegnud_map[x][y].glyph_primary!=MAX_GLYPH)&&(noegnud_map[x][y].special_primary & MG_PET)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,1.0); } else glColor4f(1.0,1.0,1.0,1.0); if (noegnud_render_selection_busy) { noegnud_render_map_single_selection_tile (noegnud_map[x][y].tile_primary,1); } else if (noegnud_options_mode_tileset_caverns->value&&(!noegnud_activetileset->iso)&&noegnud_image_dungeon&&(noegnud_map[x][y].glyph_primary==MAX_GLYPH||(glyph_to_cmap(noegnud_map[x][y].glyph_primary)==S_stone&&levl[x+1][y].lit))) { if (levl[x+1][y].seenv) { if (noegnud_options_render_features_cardboardcutout->value && noegnud_options_mode_tileset_caverns_cutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value&&(!IS_ROOM(levl[x+1][y].typ))) { glPushMatrix (); noegnud_render_map_single_tile_raised_walls_texture( noegnud_image_dungeon->block[0][0]->image, noegnud_options_render_features_cardboardcutout_wall_height->value, current_alpha, !((y>0)&&noegnud_map[x][y-1].high), !((y<MAX_MAP_Y-1)&&noegnud_map[x][y+1].high), !((x>0)&&noegnud_map[x-1][y].high), !((x<MAX_MAP_X-1)&&noegnud_map[x+1][y].high)); glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_wall_height->value,0); } if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.25,1.0,0.25,1.0); } else { glColor4f(1.0,1.0,1.0,current_alpha); } } else { if (noegnud_options_render_features_cardboardcutout->value && noegnud_options_mode_tileset_caverns_cutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_wall_height->value,0); } if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.125,0.5,0.125,1.0); } else glColor4f(0.5,0.5,0.5,current_alpha); } if (levl[x+1][y].seenv) { if (IS_ROOM(levl[x+1][y].typ)) { } else { glBindTexture (GL_TEXTURE_2D, noegnud_image_dungeon->block[0][0]->image); glBegin (GL_QUADS); glNormal3f(0,1,0); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx1, noegnud_image_dungeon->block[0][0]->fy2); glVertex3f (0, 0, noegnud_activetileset->glheight); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx2, noegnud_image_dungeon->block[0][0]->fy2); glVertex3f (noegnud_activetileset->glwidth, 0, noegnud_activetileset->glheight); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx2, noegnud_image_dungeon->block[0][0]->fy1); glVertex3f (noegnud_activetileset->glwidth, 0, 0); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx1, noegnud_image_dungeon->block[0][0]->fy1); glVertex3f (0, 0, 0); glEnd (); } } else { if (noegnud_options_mode_tileset_caverns_unexplored->value) { glBindTexture (GL_TEXTURE_2D, noegnud_image_dungeon->block[0][0]->image); glBegin (GL_QUADS); glNormal3f(0,1,0); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx1, noegnud_image_dungeon->block[0][0]->fy2); glVertex3f (0, 0, noegnud_activetileset->glheight); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx2, noegnud_image_dungeon->block[0][0]->fy2); glVertex3f (noegnud_activetileset->glwidth, 0, noegnud_activetileset->glheight); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx2, noegnud_image_dungeon->block[0][0]->fy1); glVertex3f (noegnud_activetileset->glwidth, 0, 0); glTexCoord2f (noegnud_image_dungeon->block[0][0]->fx1, noegnud_image_dungeon->block[0][0]->fy1); glVertex3f (0, 0, 0); glEnd (); } } if (levl[x+1][y].seenv) { if (noegnud_options_render_features_cardboardcutout->value && noegnud_options_mode_tileset_caverns_cutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value&&(!IS_ROOM(levl[x+1][y].typ))) { glPopMatrix (); } } } if ( ((!noegnud_activetileset->isalphatileset) && (noegnud_map[x][y].glyph_primary!=MAX_GLYPH))) { noegnud_render_map_single_tile (noegnud_map[x][y].tile_primary,1); if ((((x == noegnud_clip_x) && (y == noegnud_clip_y))||(((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y))) || // if (((x == noegnud_clip_x) && (y == noegnud_clip_y)) || (noegnud_map[x][y].glyph_primary!=MAX_GLYPH&&iflags.hilite_pet&&(noegnud_map[x][y].special_primary & MG_PET))) { glEnable (GL_BLEND); noegnud_render_map_tile_highlight_block (); glDisable (GL_BLEND); } } else if (noegnud_activetileset->isalphatileset) { if ( noegnud_options_render_features_cardboardcutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value && noegnud_map[x][y].low && (!noegnud_activetileset->iso)) { if ((noegnud_map[x][y].glyph_primary!=MAX_GLYPH)||(noegnud_map[x][y].glyph_primary==MAX_GLYPH&&noegnud_options_mode_tileset_caverns_cutout->value)) glTranslatef(0,-noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); } if ( noegnud_map[x][y].glyph_back != MAX_GLYPH && (!noegnud_map[x][y].high)) noegnud_render_map_single_tile (noegnud_map[x][y].tile_back,1); if ((!noegnud_render_selection_busy)&&noegnud_options_render_features_cardboardcutout->value&&noegnud_options_render_features_cardboardcutout_raise_walls->value&&(!noegnud_activetileset->iso)&&noegnud_map[x][y].low) { //glTranslatef(0,-noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); noegnud_render_map_single_tile_sunken_walls ( noegnud_map[x][y].tile_back, noegnud_options_render_features_cardboardcutout_hole_depth->value, current_alpha, !((y>0)&&noegnud_map[x][y-1].low), !((y<MAX_MAP_Y-1)&&noegnud_map[x][y+1].low), !((x>0)&&noegnud_map[x-1][y].low), !((x<MAX_MAP_X-1)&&noegnud_map[x][y].low)); } } } } if (noegnud_render_selection_busy) return; glEnable (GL_BLEND); if (noegnud_activetileset->isalphatileset) for (y = 0; y < MAX_MAP_Y; y++) { ny = -(y - (noegnud_render_middle_y)); for (x = 0; x < MAX_MAP_X; x++) { nx = x - (noegnud_render_middle_x); if ( ( ((noegnud_activetileset->iso)) /*|| (noegnud_options_render_features_cardboardcutout->value&&noegnud_activetileset->isalphatileset&&(!noegnud_activetileset->iso)) */ )&& (y >= noegnud_clip_y)&& (!((x == noegnud_clip_x) && (y == noegnud_clip_y)))&& (!glyph_is_object(noegnud_map[x][y].glyph_primary))&& (!glyph_is_monster(noegnud_map[x][y].glyph_primary))&& (!glyph_is_trap(noegnud_map[x][y].glyph_primary))&& (sqrt((noegnud_clip_y-y)*(noegnud_clip_y-y)+(noegnud_clip_x-x)*(noegnud_clip_x-x))<3) ) { current_alpha=noegnud_options_mode_tileset_iso_opacity->value; } else { current_alpha=1.0; } glPopMatrix (); glPushMatrix (); glTranslatef ((noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x, 0, -((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y); glBegin(GL_LINES); glEnd(); if (noegnud_image_dungeon&&(noegnud_map[x][y].glyph_primary==MAX_GLYPH||(glyph_to_cmap(noegnud_map[x][y].glyph_primary)==S_stone&&levl[x+1][y].lit))) { if (levl[x+1][y].seenv) { if (noegnud_options_render_features_cardboardcutout->value && noegnud_options_mode_tileset_caverns_cutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value&&(!IS_ROOM(levl[x+1][y].typ))) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_wall_height->value,0); } } else { if (noegnud_options_render_features_cardboardcutout->value && noegnud_options_mode_tileset_caverns_cutout->value && noegnud_options_render_features_cardboardcutout_raise_walls->value) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_wall_height->value,0);} } } else if (noegnud_map[x][y].glyph_primary!=MAX_GLYPH&&noegnud_options_render_features_cardboardcutout->value&&noegnud_options_render_features_cardboardcutout_raise_walls->value&&noegnud_activetileset->isalphatileset&&(!noegnud_activetileset->iso)) { if (noegnud_map[x][y].high) { if (IS_DOOR(level.locations[x+1][y].typ)) { noegnud_render_map_single_tile_raised_walls ( noegnud_map[x][y].tile_middle, noegnud_options_render_features_cardboardcutout_wall_height->value, current_alpha, !((y>0)&&noegnud_map[x][y-1].high), !((y<MAX_MAP_Y-1)&&noegnud_map[x][y+1].high), !((x>0)&&noegnud_map[x-1][y].high), !((x<MAX_MAP_X-1)&&noegnud_map[x+1][y].high)); } else { noegnud_render_map_single_tile_raised_walls ( noegnud_map[x][y].tile_back, noegnud_options_render_features_cardboardcutout_wall_height->value, current_alpha, !((y>0)&&noegnud_map[x][y-1].high), !((y<MAX_MAP_Y-1)&&noegnud_map[x][y+1].high), !((x>0)&&noegnud_map[x-1][y].high), !((x<MAX_MAP_X-1)&&noegnud_map[x+1][y].high)); } glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_wall_height->value,0); } else if (noegnud_map[x][y].low) { glTranslatef(0,-noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); if (noegnud_map[x][y].translucent) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value*noegnud_options_render_features_cardboardcutout_liquid_depth->value,0); current_alpha=0.5; } } } if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.25,1.0,0.25,1.0); } else if ((x == noegnud_clip_x) && (y == noegnud_clip_y)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,current_alpha); } else if (iflags.hilite_pet&&(noegnud_map[x][y].glyph_primary!=MAX_GLYPH)&&(noegnud_map[x][y].special_primary & MG_PET)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,current_alpha); } else { glColor4f(1.0,1.0,1.0,current_alpha); } if (noegnud_activetileset->isalphatileset) { if (noegnud_map[x][y].glyph_middle != MAX_GLYPH) { noegnud_render_map_single_tile (noegnud_map[x][y].tile_middle,1); } if (noegnud_activetileset->iso&&noegnud_map[x][y].glyph_fore != MAX_GLYPH) { noegnud_render_map_single_tile (noegnud_map[x][y].tile_fore,1); } if (((x == noegnud_clip_x) && (y == noegnud_clip_y)) || (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) || (noegnud_map[x][y].glyph_primary!=MAX_GLYPH&&iflags.hilite_pet&&(noegnud_map[x][y].special_primary & MG_PET))) { if (noegnud_options_render_features_cardboardcutout->value) glTranslatef(0,0.02,0); noegnud_render_map_tile_highlight_block (); } } } } if ((noegnud_activetileset->isalphatileset)&&(!noegnud_activetileset->iso)) { if (noegnud_options_render_features_cardboardcutout->value) glDisable(GL_CULL_FACE); if (noegnud_options_render_features_cardboardcutout->value&&noegnud_options_render_features_cardboardcutout_wall_translucency_current->value>0) { glDisable(GL_DEPTH_TEST); for (y = ys; y != ye; y+=yd) { ny = -(y - (noegnud_render_middle_y)); for (x = xs; x != xe; x+=xd) { nx = x - (noegnud_render_middle_x); glPopMatrix (); glPushMatrix (); if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.25,1.0,0.25,noegnud_options_render_features_cardboardcutout_wall_translucency_current->value); } else { glColor4f(1.0,1.0,1.0,noegnud_options_render_features_cardboardcutout_wall_translucency_current->value); } glTranslatef ((noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x, 0, -((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y); glBegin(GL_LINES); glEnd(); if (!(noegnud_map[x][y].high||noegnud_map[x][y].low)) { if (noegnud_map[x][y].glyph_back!=MAX_GLYPH) { if (noegnud_options_render_opengl_lighting_method->value==NOEGNUD_RENDER_LIGHTING_METHOD_CHEAP) { glEnable(GL_LIGHTING); } noegnud_render_map_single_tile (noegnud_map[x][y].tile_back,1); if (noegnud_options_render_opengl_lighting_method->value==NOEGNUD_RENDER_LIGHTING_METHOD_CHEAP) { glDisable(GL_LIGHTING); } } if (noegnud_map[x][y].glyph_middle!=MAX_GLYPH) { noegnud_render_map_single_tile (noegnud_map[x][y].tile_middle,1); } } if (noegnud_map[x][y].glyph_fore != MAX_GLYPH) { if ((x==(u.ux-1)&&y==u.uy)&&Levitation) { if (noegnud_map[x][y].low) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); } glTranslatef(0,noegnud_activetileset->glheight/2,0); } if (noegnud_map[x][y].low) glTranslatef(0,-noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); if (((glyph_is_monster(noegnud_map[x][y].glyph_fore)&&noegnud_options_render_features_cardboardcutout_raise_monsters->value)||(glyph_is_object(noegnud_map[x][y].glyph_fore)&&noegnud_options_render_features_cardboardcutout_raise_objects->value))) { glTranslatef (0,noegnud_activetileset->glheight,noegnud_activetileset->glheight/2); glRotatef (90, 1, 0, 0); if (noegnud_options_render_features_autoface->value) { glTranslatef ( noegnud_activetileset->glwidth/2, 0,0); glRotatef ((noegnud_options_render_opengl_view_angle_x_current->value+noegnud_render_bullettime_angle), 0, 0, 1); glTranslatef ( -noegnud_activetileset->glwidth/2, 0,0); } glRotatef (-20, 1, 0, 0); } noegnud_render_map_single_tile (noegnud_map[x][y].tile_fore,1); } } } glEnable(GL_DEPTH_TEST); } if (noegnud_options_render_opengl_lighting_method->value==NOEGNUD_RENDER_LIGHTING_METHOD_CHEAP) { glDisable(GL_LIGHTING); } for (y = ys; y != ye; y+=yd) { ny = -(y - (noegnud_render_middle_y)); for (x = xs; x != xe; x+=xd) { nx = x - (noegnud_render_middle_x); if ((noegnud_activetileset->iso)&&(y >= noegnud_clip_y)&&(!((x == noegnud_clip_x) && (y == noegnud_clip_y)))&&(!glyph_is_object(noegnud_map[x][y].glyph_primary))&&(!glyph_is_monster(noegnud_map[x][y].glyph_primary))&&(sqrt((noegnud_clip_y-y)*(noegnud_clip_y-y)+(noegnud_clip_x-x)*(noegnud_clip_x-x))<3)) { current_alpha=0.3; } else { current_alpha=1.0; } glPopMatrix (); glPushMatrix (); glTranslatef ((noegnud_activetileset->xdeltax) * (nx) + (noegnud_activetileset->ydeltax) * (ny) + noegnud_render_offset_x, 0, -((noegnud_activetileset->xdeltay) * (nx) + (noegnud_activetileset->ydeltay) * (ny)) + noegnud_render_offset_y); glBegin(GL_LINES); glEnd(); if (((noegnud_render_mouse_map_x-1)==x)&&(noegnud_render_mouse_map_y==y)) { glColor4f(0.25,1.0,0.25,1.0); } else if ((x == noegnud_clip_x) && (y == noegnud_clip_y)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,current_alpha); } else if (iflags.hilite_pet&&(noegnud_map[x][y].glyph_primary!=MAX_GLYPH)&&(noegnud_map[x][y].special_primary & MG_PET)) { glColor4f(noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,noegnud_render_highlight_strobe/2+0.5,current_alpha); } else { glColor4f(1.0,1.0,1.0,current_alpha); } if (noegnud_map[x][y].glyph_fore != MAX_GLYPH) { if ((x==(u.ux-1)&&y==u.uy)&&(!noegnud_activetileset->iso)&&Levitation) { if (noegnud_map[x][y].low) { glTranslatef(0,noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); } glTranslatef(0,noegnud_activetileset->glheight/2,0); } if (noegnud_map[x][y].low&&(!noegnud_activetileset->iso)) glTranslatef(0,-noegnud_activetileset->glheight*noegnud_options_render_features_cardboardcutout_hole_depth->value,0); if (noegnud_options_render_features_cardboardcutout->value&&((glyph_is_monster(noegnud_map[x][y].glyph_fore)&&noegnud_options_render_features_cardboardcutout_raise_monsters->value)||(glyph_is_object(noegnud_map[x][y].glyph_fore)&&noegnud_options_render_features_cardboardcutout_raise_objects->value))) { glTranslatef (0,noegnud_activetileset->glheight,noegnud_activetileset->glheight/2); glRotatef (90, 1, 0, 0); if (noegnud_options_render_features_autoface->value) { glTranslatef ( noegnud_activetileset->glwidth/2, 0,0); glRotatef ((noegnud_options_render_opengl_view_angle_x_current->value+noegnud_render_bullettime_angle), 0, 0, 1); glTranslatef ( -noegnud_activetileset->glwidth/2, 0,0); } glRotatef (-20, 1, 0, 0); } noegnud_render_map_single_tile (noegnud_map[x][y].tile_fore,1); } } } if (noegnud_options_render_features_cardboardcutout->value) glEnable(GL_CULL_FACE); } else { if (noegnud_options_render_opengl_lighting_method->value==NOEGNUD_RENDER_LIGHTING_METHOD_CHEAP) { glDisable(GL_LIGHTING); } } }
static void trv_ray_ycaster34(FAR struct trv_raycast_s *result) { struct trv_rect_list_s *list; /* Points to the current P plane rectangle */ struct trv_rect_data_s *rect; /* Points to the rectangle data */ trv_coord_t rely; /* Relative position of the Y plane */ trv_coord_t absx; /* Absolute X position at rely given yaw */ trv_coord_t absz; /* Absolute Z position at rely given pitch */ trv_coord_t lastrely1 = -1; /* Last relative Y position processed */ trv_coord_t lastrely2 = -1; /* Last relative Y position processed */ int32_t dxdy; /* Rate of change of X wrt Y (double) */ int32_t dzdy; /* Rate of change of Z wrt Y (double) */ /* At a viewing angle of 180 degrees, no intersections with the line x = bXi * are possible! */ if (g_camera.yaw == ANGLE_180) { return; } /* Pre-calculate the rate of change of X and Z with respect to Y */ /* The negative inverted tangent is equal to the rate of change of X with * respect to the Y-axis. The cotangent is stored at double the the * "normal" scaling. */ dxdy = -g_cot_table(g_camera.yaw - ANGLE_180); /* Determine the rate of change of the Z with respect to Y. The tangent * is "double" precision; the cosecant is "double" precision. dzdy will * be retained as "double" precision. */ dzdy = qTOd(g_adj_tanpitch * ABS(g_csc_table[g_camera.yaw])); /* Look at every rectangle lying in a Y plane */ /* This logic should be improved at some point so that non-visible planes * are "pruned" from the list prior to ray casting! */ for (list = g_ray_yplane.tail; list; list = list->blink) { rect = &list->d; /* Search for a rectangle which lies "before" the current camera * position */ if (rect->plane < g_camera.y) { /* get the Y distance to the plane */ rely = g_camera.y - rect->plane; /* g_ray_yplane is an ordered list, if we have already hit something * closer, then we can abort the casting now. */ if (rely > result->ydist) { return; } /* Calculate the Y position at this relative X position. We can skip * this step if we are processing another rectangle at the same relx * distance. */ if (rely != lastrely1) { int32_t deltax; /* Scale == "triple" */ /* The dxdy is stored at double the"normal" scaling -- so deltax * is "triple" precision */ deltax = dxdy * ((int32_t) rely); absx = tTOs(deltax) + g_camera.x; /* back to "single" */ lastrely1 = rely; } /* Check if this X position intersects the rectangle */ if (absx >= rect->hstart && absx <= rect->hend) { /* The X position lies in the rectangle. Now, calculate the * Z position at this relative X position. We can skip this * step if we are processing another rectangle at the same * relx distance. */ if (rely != lastrely2) { int32_t deltaz; /* Scale == TRIPLE */ /* The dzdy is stored at double the"normal" scaling -- so * deltaz is "triple" precision */ deltaz = dzdy * ((int32_t) rely); absz = tTOs(deltaz) + g_camera.z; /* Back to single */ lastrely2 = rely; } /* Check if this Z position intersects the rectangle */ if (absz >= rect->vstart && absz <= rect->vend) { /* We've got a potential hit, let's see what it is */ /* Check if we just hit an ordinary opaque wall */ if (IS_NORMAL(rect)) { /* Yes..Save the parameters associated with the normal * wall hit */ result->rect = rect; result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT); result->xpos = absx; result->ypos = absz; result->xdist = ABS(absx - g_camera.x); result->ydist = rely; result->zdist = ABS(absz - g_camera.z); /* Terminate Y casting */ return; } else if (IS_DOOR(rect)) { /* Check if the door is in motion. */ if (!IS_MOVING_DOOR(rect)) { /* Save the parameters associated with the normal * door hit */ result->rect = rect; result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT); result->xpos = absx; result->ypos = absz; result->xdist = ABS(absx - g_camera.x); result->ydist = rely; result->zdist = ABS(absz - g_camera.z); /* Terminate Y casting */ return; } /* The door is in motion, the Z-position to see if we can * see under the door */ else if (absz > g_opendoor.zbottom) { /* Save the parameters associated with the moving * door hit */ result->rect = rect; result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT); result->xpos = absx; result->ypos = absz - g_opendoor.zdist; result->xdist = ABS(absx - g_camera.x); result->ydist = rely; result->zdist = ABS(absz - g_camera.z); /* Terminate Y casting */ return; } } /* Otherwise, it must be a transparent wall. We'll need to * make our decision based upon the pixel that we hit */ /* Check if the pixel at this location is visible */ else if (GET_BACK_PIXEL(rect, absx, absz) != INVISIBLE_PIXEL) { /* Its visible, save the parameters associated with the * transparent wall hit */ result->rect = rect; result->type = MK_HIT_TYPE(BACK_HIT, Y_HIT); result->xpos = absx; result->ypos = absz; result->xdist = ABS(absx - g_camera.x); result->ydist = rely; result->zdist = ABS(absz - g_camera.z); /* Terminate Y casting */ return; } } } } } }
static void trv_ray_xcaster14(FAR struct trv_raycast_s *result) { struct trv_rect_list_s *list; /* Points to the current X plane rectangle */ struct trv_rect_data_s *rect; /* Points to the rectangle data */ trv_coord_t relx; /* Relative position of the X plane */ trv_coord_t absy; /* Absolute Y position at relx given yaw */ trv_coord_t absz; /* Absolute Z position at relx given pitch */ trv_coord_t lastrelx1 = -1; /* Last relative X position processed */ trv_coord_t lastrelx2 = -1; /* Last relative X position processed */ int32_t dydx; /* Rate of change of Y wrt X (double) */ int32_t dzdx; /* Rate of change of Z wrt X (double) */ /* At a viewing angle of 270 degrees, no intersections with the g_ray_xplanes * are possible! */ if (g_camera.yaw == ANGLE_270) { return; } /* Pre-calculate the rate of change of Y and Z with respect to X */ /* The tangent is equal to the rate of change of Y with respect to the * X-axis. The tangent is stored at double the "normal" scaling. */ dydx = TAN(g_camera.yaw); /* Determine the rate of change of the Z with respect to X. The tangent is * "double" precision; the secant is "double" precision. dzdx will be * retained as "double" precision. */ dzdx = qTOd(g_adj_tanpitch * ABS(g_sec_table[g_camera.yaw])); /* Look at every rectangle lying in the X plane */ /* This logic should be improved at some point so that non-visible planes * are "pruned" from the list prior to ray casting! */ for (list = g_ray_xplane.head; list; list = list->flink) { rect = &list->d; /* Search for a rectangle which lies "beyond" the current camera * position */ if (rect->plane > g_camera.x) { /* get the X distance to the plane */ relx = rect->plane - g_camera.x; #if 0 /* g_ray_xplane is an ordered list, if we have already hit something * closer, then we can abort the casting now. */ if (relx > result->xdist) { return; } #endif /* Calculate the Y position at this relative X position. We can skip * this step if we are processing another rectangle at the same relx * distance. */ if (relx != lastrelx1) { int32_t deltay; /* Scale == "triple" */ /* The dydx is stored at double the"normal" scaling -- so * deltay is "triple" precision */ deltay = dydx * ((int32_t) relx); absy = tTOs(deltay) + g_camera.y; /* back to "single" */ lastrelx1 = relx; } /* Check if this Y position intersects the rectangle */ if (absy >= rect->hstart && absy <= rect->hend) { /* The Y position lies in the rectangle. Now, calculate the * theZ position at this relative X position. We can skip * this step if we are processing another rectangle at the * same relx distance. */ if (relx != lastrelx2) { int32_t deltaz; /* Scale == TRIPLE */ /* The dzdx is stored at double the"normal" scaling -- so * deltaz is "triple" precision */ deltaz = dzdx * ((int32_t) relx); absz = tTOs(deltaz) + g_camera.z; /* Back to single */ lastrelx2 = relx; } /* Check if this Z position intersects the rectangle */ if (absz >= rect->vstart && absz <= rect->vend) { /* We've got a potential hit, let's see what it is */ /* Check if we just hit an ordinary opaque wall */ if (IS_NORMAL(rect)) { /* Yes..Save the parameters associated with the normal * wall hit */ result->rect = rect; result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT); result->xpos = absy; result->ypos = absz; result->xdist = relx; result->ydist = ABS(absy - g_camera.y); result->zdist = ABS(absz - g_camera.z); /* Terminate X casting */ return; } else if (IS_DOOR(rect)) { /* Check if the door is in motion. */ if (!IS_MOVING_DOOR(rect)) { /* Save the parameters associated with the normal * door hit */ result->rect = rect; result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT); result->xpos = absy; result->ypos = absz; result->xdist = relx; result->ydist = ABS(absy - g_camera.y); result->zdist = ABS(absz - g_camera.z); /* Terminate X casting */ return; } /* The door is in motion, the Z-position to see if we can * see under the door */ else if (absz > g_opendoor.zbottom) { /* Save the parameters associated with the moving * door hit */ result->rect = rect; result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT); result->xpos = absy; result->ypos = absz - g_opendoor.zdist; result->xdist = relx; result->ydist = ABS(absy - g_camera.y); result->zdist = ABS(absz - g_camera.z); /* Terminate X casting */ return; } } /* Otherwise, it must be a transparent wall. We'll need to * make our decision based upon the pixel that we hit */ /* Check if the pixel at this location is visible */ else if (GET_FRONT_PIXEL(rect, absy, absz) != INVISIBLE_PIXEL) { /* Its visible, save the parameters associated with the * transparent wall hit */ result->rect = rect; result->type = MK_HIT_TYPE(FRONT_HIT, X_HIT); result->xpos = absy; result->ypos = absz; result->xdist = relx; result->ydist = ABS(absy - g_camera.y); result->zdist = ABS(absz - g_camera.z); /* Terminate X casting */ return; } } } } } }