Показать сообщение отдельно
Старый 31.03.2010, 15:41   #11
user456
Новичок
 
Регистрация: 31.03.2010
Сообщений: 22
Сказал(а) спасибо: 2
Поблагодарили 23 раз(а) в 8 сообщениях
user456 На верном пути
По умолчанию Как найти Z на терран

Вводная: имеем карту типа Azeroth, где позиция xy = 0:0 посредине. В итоге координаты от -HALF_MAP до +HALF_MAP. 64х64 тайла которые в wdt карты помечены как отсутствующие или в наличии. В тайле 16х16 чанков, каждый делится на сабчанки, где собственно уже есть реальные координаты. Вкратце константы.
Код:
     
     TILE_SIZE            = 533.33333;
     TILES_COUNT          = 64;
     MAX_TILE             = 63;
     HALF_MAP             = 32*TILE_SIZE;
     INSTANCE_QUARTER_MAP = 8*TILE_SIZE;
     CHUNK_COUNT          = 16;
     TILE_CHUNK_COUNT     = 256;
     MAX_CHUNK            = 255;
     CHUNK_SIZE           = TILE_SIZE / CHUNK_COUNT;
     DCHUNK_SIZE          = CHUNK_SIZE*2;
     SUB_CHUNK_FULL_COUNT = 17;
     SUB_CHUNK_LINE_COUNT = 8;
     SUB_CHUNK_POINT_COUNT = 9;
     SUB_CHUNK_SIZE  = CHUNK_SIZE / SUB_CHUNK_LINE_COUNT;
     HALF_SUB_CHUNK_SIZE  = SUB_CHUNK_SIZE/2;
Сначала находим в каком тайле и чанке x и y и выходим если координаты хзгде. Абсолютная позиция от края карты.
Код:
  absX := HALF_MAP - objPos.pos.x;absY := HALF_MAP - objPos.pos.y;
  tileX := trunc(absX / TILE_SIZE);diffX := absX - tileX * TILE_SIZE;
  tileY := trunc(absY / TILE_SIZE);diffY := absY - tileY * TILE_SIZE;

  chunkX := trunc(diffX / CHUNK_SIZE);chunkDiffX := diffX - chunkX * CHUNK_SIZE;
  chunkY := trunc(diffY / CHUNK_SIZE);chunkDiffY := diffY - chunkY * CHUNK_SIZE;

  if OrdinalMapsArray[objPos.mapId, tileY, tileX] = nil then
    exit;
Далее смотрим не попали ли в воду, м2, вмо и т.п., в конце-концов определились что все-таки на карте. Имеем в каждом сабчанке 9х9 точек, что дает нам кучу квадратов. Благодаря второй сетке 8х8 каждый квадрат получает точку в центре и мы имеем уже 4 полигона, что ближе к тригонометрии. Делением получаем тангенс угла, по которому сразу понятно в какой из 4-х полигонов попали. А там уже дело техники: точка сопряжения прямой с полигоном, откуда и имеем Z.
Код:
  { chunk }
  tan1 := subChunkDiffY / subChunkDiffX;
  tan2 := subChunkDiffY / (SUB_CHUNK_SIZE - subChunkDiffX);


  v3.x := HALF_SUB_CHUNK_SIZE;  v3.y := HALF_SUB_CHUNK_SIZE;
  v3.z := lpChunkMap.Z[subChunkX + subChunkY * SUB_CHUNK_FULL_COUNT + SUB_CHUNK_POINT_COUNT];
  p1.x := subChunkDiffY;     p1.y := subChunkDiffX;      p1.z := 0;
  p2.x := subChunkDiffY;     p2.y := subChunkDiffX;      p2.z := 100;
  if tan2 >= 1 then begin
    if tan1 >= 1 then begin //right
      v1.x := SUB_CHUNK_SIZE;    v1.y := 0;
      v2.x := SUB_CHUNK_SIZE;    v2.y := SUB_CHUNK_SIZE;
      v1.z := lpChunkMap.Z[(subChunkX + 1) + subChunkY * SUB_CHUNK_FULL_COUNT];
      v2.z := lpChunkMap.Z[(subChunkX + 1) + (subChunkY + 1) * SUB_CHUNK_FULL_COUNT];
      norm := Normal([v1, v2, v3]);
      mapPositionResult.tilt := abs(Normalize(norm).z);
      dV := IntersectionPoint(p1, p2, norm, PlaneDistance(norm, v3));
      result := baseZ + dV.z;
    end
    else begin //bottom
      v1.x := SUB_CHUNK_SIZE;    v1.y := SUB_CHUNK_SIZE;
      v2.x := 0;                 v2.y := SUB_CHUNK_SIZE;
      v1.z := lpChunkMap.Z[(subChunkX + 1) + (subChunkY + 1) * SUB_CHUNK_FULL_COUNT];
      v2.z := lpChunkMap.Z[subChunkX + (subChunkY + 1) * SUB_CHUNK_FULL_COUNT];
      norm := Normal([v1, v2, v3]);
      mapPositionResult.tilt := abs(Normalize(norm).z);
      dV := IntersectionPoint(p1, p2, norm, PlaneDistance(norm, v3));
      result := baseZ + dV.z;
    end;
  end
  else
  if tan1 >= 1 then begin //top
    v1.x := 0;                 v1.y := 0;
    v2.x := SUB_CHUNK_SIZE;    v2.y := 0;
    v1.z := lpChunkMap.Z[subChunkX + subChunkY * SUB_CHUNK_FULL_COUNT];
    v2.z := lpChunkMap.Z[(subChunkX + 1) + subChunkY * SUB_CHUNK_FULL_COUNT];
    norm := Normal([v1, v2, v3]);
    mapPositionResult.tilt := abs(Normalize(norm).z);
    dV := IntersectionPoint(p1, p2, norm, PlaneDistance(norm, v1));
    result := baseZ + dV.z;
  end
  else begin //left
    v1.x := 0;                 v1.y := SUB_CHUNK_SIZE;
    v2.x := 0;                 v2.y := 0;
    v1.z := lpChunkMap.Z[subChunkX + (subChunkY + 1) * SUB_CHUNK_FULL_COUNT];
    v2.z := lpChunkMap.Z[subChunkX + subChunkY * SUB_CHUNK_FULL_COUNT];
    norm := Normal([v1, v2, v3]);
    mapPositionResult.tilt := abs(Normalize(norm).z);
    dV := IntersectionPoint(p1, p2, norm, PlaneDistance(norm, v2));
    result := baseZ + dV.z;
  end
Код собственно не трогал со времен 1.хх. Не думаю что сильно поменялось. (Edit: эта часть не поменялась и z считается быстро, если не делать для всех мобов одновременно динамически вычисляя передвижения каждые 0.2 ярда как я когда-то делал)

Последний раз редактировалось user456; 31.03.2010 в 23:09. Причина: проверил
user456 вне форума   Ответить с цитированием
4 пользователя(ей) сказали cпасибо:
Chestarfild (12.04.2010), Konctantin (31.03.2010), SilverIce (01.04.2010)