rendered paste bodydiff --git a/src/mmap/GridMapManager.cpp b/src/mmap/GridMapManager.cppindex e891b2b..8f4982d 100644--- a/src/mmap/GridMapManager.cpp+++ b/src/mmap/GridMapManager.cpp@@ -2,6 +2,403 @@ namespace VMAP {+ + GridMap::GridMap()+ {+ m_flags = 0;+ // Area data+ m_gridArea = 0;+ m_area_map = NULL;+ // Height level data+ m_gridHeight = -100000.0f;+ m_gridGetHeight = &GridMap::getHeightFromFlat;+ m_V9 = NULL;+ m_V8 = NULL;+ // Liquid data+ m_liquidType = 0;+ m_liquid_offX = 0;+ m_liquid_offY = 0;+ m_liquid_width = 0;+ m_liquid_height = 0;+ m_liquidLevel = -100000.0f;+ m_liquid_type = NULL;+ m_liquid_map = NULL;+ }++ GridMap::~GridMap()+ {+ unloadData();+ }++ bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 /*size*/)+ {+ map_areaHeader header;+ fseek(in, offset, SEEK_SET);+ fread(&header, sizeof(header), 1, in);+ if (header.fourcc != *((uint32 const*)(MAP_AREA_MAGIC)))+ return false;++ m_gridArea = header.gridArea;+ if (!(header.flags & MAP_AREA_NO_AREA))+ {+ m_area_map = new uint16 [16*16];+ fread(m_area_map, sizeof(uint16), 16*16, in);+ }+ return true;+ }++ bool GridMap::loadHeightData(FILE *in, uint32 offset, uint32 /*size*/)+ {+ map_heightHeader header;+ fseek(in, offset, SEEK_SET);+ fread(&header, sizeof(header), 1, in);+ if (header.fourcc != *((uint32 const*)(MAP_HEIGHT_MAGIC)))+ return false;++ m_gridHeight = header.gridHeight;+ if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))+ {+ if ((header.flags & MAP_HEIGHT_AS_INT16))+ {+ m_uint16_V9 = new uint16 [129*129];+ m_uint16_V8 = new uint16 [128*128];+ fread(m_uint16_V9, sizeof(uint16), 129*129, in);+ fread(m_uint16_V8, sizeof(uint16), 128*128, in);+ m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;+ m_gridGetHeight = &GridMap::getHeightFromUint16;+ }+ else if ((header.flags & MAP_HEIGHT_AS_INT8))+ {+ m_uint8_V9 = new uint8 [129*129];+ m_uint8_V8 = new uint8 [128*128];+ fread(m_uint8_V9, sizeof(uint8), 129*129, in);+ fread(m_uint8_V8, sizeof(uint8), 128*128, in);+ m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;+ m_gridGetHeight = &GridMap::getHeightFromUint8;+ }+ else+ {+ m_V9 = new float [129*129];+ m_V8 = new float [128*128];+ fread(m_V9, sizeof(float), 129*129, in);+ fread(m_V8, sizeof(float), 128*128, in);+ m_gridGetHeight = &GridMap::getHeightFromFloat;+ }+ }+ else+ m_gridGetHeight = &GridMap::getHeightFromFlat;+ return true;+ }++ bool GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 /*size*/)+ {+ map_liquidHeader header;+ fseek(in, offset, SEEK_SET);+ fread(&header, sizeof(header), 1, in);+ if (header.fourcc != *((uint32 const*)(MAP_LIQUID_MAGIC)))+ return false;++ m_liquidType = header.liquidType;+ m_liquid_offX = header.offsetX;+ m_liquid_offY = header.offsetY;+ m_liquid_width = header.width;+ m_liquid_height= header.height;+ m_liquidLevel = header.liquidLevel;++ if (!(header.flags & MAP_LIQUID_NO_TYPE))+ {+ m_liquid_type = new uint8 [16*16];+ fread(m_liquid_type, sizeof(uint8), 16*16, in);+ }+ if (!(header.flags & MAP_LIQUID_NO_HEIGHT))+ {+ m_liquid_map = new float [m_liquid_width*m_liquid_height];+ fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in);+ }+ return true;+ }++ float GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const+ {+ return m_gridHeight;+ }++ float GridMap::getHeightFromFloat(float x, float y) const+ {+ if (!m_V8 || !m_V9)+ return m_gridHeight;++ x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);+ y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);++ int x_int = (int)x;+ int y_int = (int)y;+ x -= x_int;+ y -= y_int;+ x_int&=(MAP_RESOLUTION - 1);+ y_int&=(MAP_RESOLUTION - 1);++ // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid+ // +--------------> X+ // | h1-------h2 Coordinates is:+ // | | \ 1 / | h1 0,0+ // | | \ / | h2 0,1+ // | | 2 h5 3 | h3 1,0+ // | | / \ | h4 1,1+ // | | / 4 \ | h5 1/2,1/2+ // | h3-------h4+ // V Y+ // For find height need+ // 1 - detect triangle+ // 2 - solve linear equation from triangle points+ // Calculate coefficients for solve h = a*x + b*y + c++ float a,b,c;+ // Select triangle:+ if (x+y < 1)+ {+ if (x > y)+ {+ // 1 triangle (h1, h2, h5 points)+ float h1 = m_V9[(x_int )*129 + y_int];+ float h2 = m_V9[(x_int+1)*129 + y_int];+ float h5 = 2 * m_V8[x_int*128 + y_int];+ a = h2-h1;+ b = h5-h1-h2;+ c = h1;+ }+ else+ {+ // 2 triangle (h1, h3, h5 points)+ float h1 = m_V9[x_int*129 + y_int ];+ float h3 = m_V9[x_int*129 + y_int+1];+ float h5 = 2 * m_V8[x_int*128 + y_int];+ a = h5 - h1 - h3;+ b = h3 - h1;+ c = h1;+ }+ }+ else+ {+ if (x > y)+ {+ // 3 triangle (h2, h4, h5 points)+ float h2 = m_V9[(x_int+1)*129 + y_int ];+ float h4 = m_V9[(x_int+1)*129 + y_int+1];+ float h5 = 2 * m_V8[x_int*128 + y_int];+ a = h2 + h4 - h5;+ b = h4 - h2;+ c = h5 - h4;+ }+ else+ {+ // 4 triangle (h3, h4, h5 points)+ float h3 = m_V9[(x_int )*129 + y_int+1];+ float h4 = m_V9[(x_int+1)*129 + y_int+1];+ float h5 = 2 * m_V8[x_int*128 + y_int];+ a = h4 - h3;+ b = h3 + h4 - h5;+ c = h5 - h4;+ }+ }+ // Calculate height+ return a * x + b * y + c;+ }++ float GridMap::getHeightFromUint8(float x, float y) const+ {+ if (!m_uint8_V8 || !m_uint8_V9)+ return m_gridHeight;++ x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);+ y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);++ int x_int = (int)x;+ int y_int = (int)y;+ x -= x_int;+ y -= y_int;+ x_int&=(MAP_RESOLUTION - 1);+ y_int&=(MAP_RESOLUTION - 1);++ int32 a, b, c;+ uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int];+ if (x+y < 1)+ {+ if (x > y)+ {+ // 1 triangle (h1, h2, h5 points)+ int32 h1 = V9_h1_ptr[ 0];+ int32 h2 = V9_h1_ptr[129];+ int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];+ a = h2-h1;+ b = h5-h1-h2;+ c = h1;+ }+ else+ {+ // 2 triangle (h1, h3, h5 points)+ int32 h1 = V9_h1_ptr[0];+ int32 h3 = V9_h1_ptr[1];+ int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];+ a = h5 - h1 - h3;+ b = h3 - h1;+ c = h1;+ }+ }+ else+ {+ if (x > y)+ {+ // 3 triangle (h2, h4, h5 points)+ int32 h2 = V9_h1_ptr[129];+ int32 h4 = V9_h1_ptr[130];+ int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];+ a = h2 + h4 - h5;+ b = h4 - h2;+ c = h5 - h4;+ }+ else+ {+ // 4 triangle (h3, h4, h5 points)+ int32 h3 = V9_h1_ptr[ 1];+ int32 h4 = V9_h1_ptr[130];+ int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];+ a = h4 - h3;+ b = h3 + h4 - h5;+ c = h5 - h4;+ }+ }+ // Calculate height+ return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;+ }++ float GridMap::getHeightFromUint16(float x, float y) const+ {+ if (!m_uint16_V8 || !m_uint16_V9)+ return m_gridHeight;++ x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);+ y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);++ int x_int = (int)x;+ int y_int = (int)y;+ x -= x_int;+ y -= y_int;+ x_int&=(MAP_RESOLUTION - 1);+ y_int&=(MAP_RESOLUTION - 1);++ int32 a, b, c;+ uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int];+ if (x+y < 1)+ {+ if (x > y)+ {+ // 1 triangle (h1, h2, h5 points)+ int32 h1 = V9_h1_ptr[ 0];+ int32 h2 = V9_h1_ptr[129];+ int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];+ a = h2-h1;+ b = h5-h1-h2;+ c = h1;+ }+ else+ {+ // 2 triangle (h1, h3, h5 points)+ int32 h1 = V9_h1_ptr[0];+ int32 h3 = V9_h1_ptr[1];+ int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];+ a = h5 - h1 - h3;+ b = h3 - h1;+ c = h1;+ }+ }+ else+ {+ if (x > y)+ {+ // 3 triangle (h2, h4, h5 points)+ int32 h2 = V9_h1_ptr[129];+ int32 h4 = V9_h1_ptr[130];+ int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];+ a = h2 + h4 - h5;+ b = h4 - h2;+ c = h5 - h4;+ }+ else+ {+ // 4 triangle (h3, h4, h5 points)+ int32 h3 = V9_h1_ptr[ 1];+ int32 h4 = V9_h1_ptr[130];+ int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];+ a = h4 - h3;+ b = h3 + h4 - h5;+ c = h5 - h4;+ }+ }+ // Calculate height+ return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;+ }++ bool GridMap::loadData(char *filename)+ {+ // Unload old data if exist+ unloadData();++ map_fileheader header;+ // Not return error if file not found+ FILE *in = fopen(filename, "rb");+ if (!in)+ return true;+ fread(&header, sizeof(header),1,in);+ if (header.mapMagic == *((uint32 const*)(MAP_MAGIC)) &&+ header.versionMagic == *((uint32 const*)(MAP_VERSION_MAGIC)) ) // ||+ //!IsAcceptableClientBuild(header.buildMagic))+ {+ // loadup area data+ if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))+ {+ printf("Error loading map area data\n");+ fclose(in);+ return false;+ }+ // loadup height data+ if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize))+ {+ printf("Error loading map height data\n");+ fclose(in);+ return false;+ }+ // loadup liquid data+ if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))+ {+ printf("Error loading map liquids data\n");+ fclose(in);+ return false;+ }+ fclose(in);+ printf("Map file %s loaded.\n",filename);+ return true;+ }+ printf("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.", filename);+ fclose(in);+ return false;+ }++ void GridMap::unloadData()+ {+ if (m_area_map) delete[] m_area_map;+ if (m_V9) delete[] m_V9;+ if (m_V8) delete[] m_V8;+ if (m_liquid_type) delete[] m_liquid_type;+ if (m_liquid_map) delete[] m_liquid_map;+ m_area_map = NULL;+ m_V9 = NULL;+ m_V8 = NULL;+ m_liquid_type = NULL;+ m_liquid_map = NULL;+ m_gridGetHeight = &GridMap::getHeightFromFlat;+ }+ //================================================ GridMapManager::GridMapManager (const char* pBasePath, unsigned int pMapId)@@ -28,29 +425,27 @@ namespace VMAP bool GridMapManager::loadMap (int pX, int pY) {- bool result = true;- if (!iGridMaps[pX][pY] && iMapExist[pX][pY])- {- result = false;- int len = 500;- char* tmp = new char[len];- sprintf (tmp, (iBasePath + "/maps/%03u%02u%02u.map").c_str (), iMapId, pX, pY);- // loading data- FILE *pf = fopen (tmp, "rb");- if (pf)- {- char magic[8];- fread (magic, 1, 8, pf);- GridMap * buf = new GridMap;- fread (buf, 1, sizeof (GridMap), pf);- fclose (pf);- iGridMaps[pX][pY] = buf;- result = true;- }- else- iMapExist[pX][pY] = false;- delete [] tmp;- }+ bool result = true;+ if (!iGridMaps[pX][pY] && iMapExist[pX][pY])+ {+ result = false;+ int len = 500;+ char* tmp = new char[len];+ sprintf (tmp, (iBasePath + "/maps/%03u%02u%02u.map").c_str (), iMapId, pX, pY);+ // loading data+ FILE *pf = fopen (tmp, "rb");+ if (pf)+ {+ iGridMaps[pX][pY] = new GridMap();+ if (!iGridMaps[pX][pY]->loadData(tmp))+ {+ iMapExist[pX][pY] = false;+ }+ }+ else+ iMapExist[pX][pY] = false;+ delete [] tmp;+ } return result; } @@ -59,11 +454,11 @@ namespace VMAP void GridMapManager::unloadMap (int pX, int pY) {- if (!iGridMaps[pX][pY])- {- delete iGridMaps[pX][pY];- iGridMaps[pX][pY] = 0;- }+ if (!iGridMaps[pX][pY])+ {+ delete iGridMaps[pX][pY];+ iGridMaps[pX][pY] = NULL;+ } } //================================================@@ -71,25 +466,17 @@ namespace VMAP float GridMapManager::getHeight (float pX, float pY) {-- float lx, ly;- int gx, gy;-- gx = (int) (32 - pX / SIZE_OF_GRIDS); //grid x- gy = (int) (32 - pY / SIZE_OF_GRIDS); //grid y-- if (!iGridMaps[gx][gy]) //this map is not loaded- loadMap (gx, gy);-- if (!iMapExist[gx][gy])- return -100000.0f;-- lx = MAP_RESOLUTION * (32 - pX / SIZE_OF_GRIDS - gx);- ly = MAP_RESOLUTION * (32 - pY / SIZE_OF_GRIDS - gy);-- int lx_int = (int) lx;- int ly_int = (int) ly;- return iGridMaps[gx][gy]->Z[lx_int][ly_int];+ int gx, gy;+ gx = (int) (32 - pX / SIZE_OF_GRIDS); //grid x+ gy = (int) (32 - pY / SIZE_OF_GRIDS); //grid y++ if (!iGridMaps[gx][gy]) //this map is not loaded+ loadMap (gx, gy);++ if (!iMapExist[gx][gy])+ return -100000.0f;++ return iGridMaps[gx][gy]->getHeight(pX,pY); } //================================================ }diff --git a/src/mmap/GridMapManager.h b/src/mmap/GridMapManager.hindex cf45653..b8a6fdf 100644--- a/src/mmap/GridMapManager.h+++ b/src/mmap/GridMapManager.h@@ -1,7 +1,8 @@ #ifndef _GRIDMAPMANAGER_H #define _GRIDMAPMANAGER_H -#include <string>+#include <string>+#include <cstdio> namespace VMAP {@@ -29,13 +30,146 @@ namespace VMAP //================================================ - typedef struct- {- unsigned short area_flag[16][16];- unsigned char terrain_type[16][16];- float liquid_level[128][128];- float Z[MAP_RESOLUTION][MAP_RESOLUTION];- } GridMap;+ static char const* MAP_MAGIC = "MAPS";+ static char const* MAP_VERSION_MAGIC = "v1.1";+ static char const* MAP_AREA_MAGIC = "AREA";+ static char const* MAP_HEIGHT_MAGIC = "MHGT";+ static char const* MAP_LIQUID_MAGIC = "MLIQ";+ + typedef unsigned int uint32;+ typedef unsigned short uint16;+ typedef unsigned char uint8;+ typedef signed int int32;+ + struct map_fileheader+ {+ uint32 mapMagic;+ uint32 versionMagic;+ uint32 buildMagic;+ uint32 areaMapOffset;+ uint32 areaMapSize;+ uint32 heightMapOffset;+ uint32 heightMapSize;+ uint32 liquidMapOffset;+ uint32 liquidMapSize;+ };+ + #define MAP_AREA_NO_AREA 0x0001+ + struct map_areaHeader+ {+ uint32 fourcc;+ uint16 flags;+ uint16 gridArea;+ };+ + #define MAP_HEIGHT_NO_HEIGHT 0x0001+ #define MAP_HEIGHT_AS_INT16 0x0002+ #define MAP_HEIGHT_AS_INT8 0x0004+ + struct map_heightHeader+ {+ uint32 fourcc;+ uint32 flags;+ float gridHeight;+ float gridMaxHeight;+ };+ + #define MAP_LIQUID_NO_TYPE 0x0001+ #define MAP_LIQUID_NO_HEIGHT 0x0002+ + struct map_liquidHeader+ {+ uint32 fourcc;+ uint16 flags;+ uint16 liquidType;+ uint8 offsetX;+ uint8 offsetY;+ uint8 width;+ uint8 height;+ float liquidLevel;+ };+ + enum ZLiquidStatus+ {+ LIQUID_MAP_NO_WATER = 0x00000000,+ LIQUID_MAP_ABOVE_WATER = 0x00000001,+ LIQUID_MAP_WATER_WALK = 0x00000002,+ LIQUID_MAP_IN_WATER = 0x00000004,+ LIQUID_MAP_UNDER_WATER = 0x00000008+ };+ + #define MAP_LIQUID_TYPE_NO_WATER 0x00+ #define MAP_LIQUID_TYPE_WATER 0x01+ #define MAP_LIQUID_TYPE_OCEAN 0x02+ #define MAP_LIQUID_TYPE_MAGMA 0x04+ #define MAP_LIQUID_TYPE_SLIME 0x08+ + #define MAP_ALL_LIQUIDS (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME)+ + #define MAP_LIQUID_TYPE_DARK_WATER 0x10+ #define MAP_LIQUID_TYPE_WMO_WATER 0x20+ + struct LiquidData+ {+ uint32 type;+ float level;+ float depth_level;+ };+ + class GridMap+ {+ uint32 m_flags;+ // Area data+ uint16 m_gridArea;+ uint16 *m_area_map;+ // Height level data+ float m_gridHeight;+ float m_gridIntHeightMultiplier;+ union{+ float *m_V9;+ uint16 *m_uint16_V9;+ uint8 *m_uint8_V9;+ };+ union{+ float *m_V8;+ uint16 *m_uint16_V8;+ uint8 *m_uint8_V8;+ };+ // Liquid data+ uint16 m_liquidType;+ uint8 m_liquid_offX;+ uint8 m_liquid_offY;+ uint8 m_liquid_width;+ uint8 m_liquid_height;+ float m_liquidLevel;+ uint8 *m_liquid_type;+ float *m_liquid_map;+ + bool loadAreaData(FILE *in, uint32 offset, uint32 size);+ bool loadHeightData(FILE *in, uint32 offset, uint32 size);+ bool loadLiquidData(FILE *in, uint32 offset, uint32 size);+ + // Get height functions and pointers+ typedef float (GridMap::*pGetHeightPtr) (float x, float y) const;+ pGetHeightPtr m_gridGetHeight;+ float getHeightFromFloat(float x, float y) const;+ float getHeightFromUint16(float x, float y) const;+ float getHeightFromUint8(float x, float y) const;+ float getHeightFromFlat(float x, float y) const;+ + public:+ GridMap();+ ~GridMap();+ bool loadData(char *filaname);+ void unloadData();+ + //uint16 getArea(float x, float y);+ inline float getHeight(float x, float y) {return (this->*m_gridGetHeight)(x, y);}+ //float getLiquidLevel(float x, float y);+ //uint8 getTerrainType(float x, float y);+ //ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0);+ }; //================================================ diff --git a/src/mmap/MoveMapAreaFinder.h b/src/mmap/MoveMapAreaFinder.hindex e63c1b0..9f6c8b6 100644--- a/src/mmap/MoveMapAreaFinder.h+++ b/src/mmap/MoveMapAreaFinder.h@@ -2,7 +2,7 @@ #define _MOVEMAPAREAFINDER_H #include "PositionControlArray.h"-+#include <limits.h> #include <G3D/Array.h> using namespace G3D;diff --git a/src/mmap/MoveMapBoxContainer.cpp b/src/mmap/MoveMapBoxContainer.cppindex 9cb8165..3430c47 100644--- a/src/mmap/MoveMapBoxContainer.cpp+++ b/src/mmap/MoveMapBoxContainer.cpp@@ -349,7 +349,7 @@ namespace VMAP } char filename[1024]; sprintf (filename, "grid_cnx_%03u_%02u_%02u_%02u_%02u.tmp", MapId, mapx, mapy, x_val, y_val);- printf("Processing %s", filename);+ printf("Processing %s\n", filename); nName = startCoordsPath + "/" + std::string(filename); ((MoveZoneContainerGenerator*)iMoveZoneContainer)->saveGridCnx(nName.c_str (),direction); }@@ -358,7 +358,7 @@ namespace VMAP void MoveMapContainer::save (const char* pDir, const Vector3& pInnerLow, const Vector3& pInnerHigh, const Vector3& oriLow, const Vector3& oriHigh, unsigned int MapId, unsigned int mapx, unsigned int mapy, bool GenCoords) {- char mmapname[15];+ char mmapname[25]; sprintf (mmapname, "/%03u_%02u_%02u.mmap", MapId, mapx, mapy); std::string nName, nName2; nName = pDir + (std::string)mmapname;diff --git a/src/mmap/MoveZone.h b/src/mmap/MoveZone.hindex 5217521..3cb6d5d 100644--- a/src/mmap/MoveZone.h+++ b/src/mmap/MoveZone.h@@ -5,6 +5,7 @@ #include <G3D/AABox.h> #include <G3D/Table.h>+#include <limits.h> #include "MoveLayer.h" diff --git a/src/viewer/ModelContainerView.cpp b/src/viewer/ModelContainerView.cppindex 26c4039..9886631 100644--- a/src/viewer/ModelContainerView.cpp+++ b/src/viewer/ModelContainerView.cpp@@ -59,7 +59,7 @@ namespace VMAP iShowPortals = false; iShowPath = false; - iVARAreaRef = VARArea::create (settings.window.width * settings.window.height * 60 * 40); // thats huge !+ iVARAreaRef = VARArea::create (settings.window.width * settings.window.height * 60); // thats huge ! iMap = mapId; ix = x;