/* * Copyright 2012 Benjamin Glatzel <benjamin.glatzel@me.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.terasology.model.structures; import java.util.Arrays; /** * A fast 3D array for efficient storage of 4-bit values. * * @author Benjamin Glatzel <benjamin.glatzel@me.com> */ public class TeraSmartArray { private final byte _array[]; private final int _lX, _lY, _lZ; private final int _size, _halfSize; /** * Init. a new 3D array with the given dimensions. */ public TeraSmartArray(int x, int y, int z) { _lX = x; _lY = y; _lZ = z; _size = _lX * _lY * _lZ; _array = new byte[_halfSize = _size / 2]; } public TeraSmartArray(TeraSmartArray other) { _lX = other._lX; _lY = other._lY; _lZ = other._lZ; _size = _lX * _lY * _lZ; _halfSize = _size / 2; _array = Arrays.copyOf(other._array, other._array.length); } /** * Returns the byte value at the given position. */ public byte get(int x, int y, int z) { int pos = (x * _lX * _lY) + (y * _lX) + z; if (x >= _lX || y >= _lY || z >= _lZ || x < 0 || y < 0 || z < 0) { throw new IndexOutOfBoundsException(String.format("(%d, %d, %d)", x, y, z)); } if (pos < _halfSize) { int bArray = _array[pos] & 0xFF; return (byte) ((bArray & 0x0F) & 0xFF); } int bArray = _array[pos % _halfSize] & 0xFF; return (byte) (bArray >> 4); } /** * Sets the byte value for the given position. */ public byte set(int x, int y, int z, byte b) { int pos = (x * _lX * _lY) + (y * _lX) + z; assert (x < _lX || y < _lY || z < _lZ || x >= 0 || y >= 0 || z >= 0); if (pos < _halfSize) { int bArray = _array[pos] & 0xFF; byte old = (byte) ((bArray & 0x0F) & 0xFF); int bInput = b & 0xFF; _array[pos] = (byte) ((bInput & 0x0F) | (bArray & 0xF0)); return old; } int bArray = _array[pos % _halfSize] & 0xFF; byte old = (byte) (bArray >> 4); int bInput = b & 0xFF; _array[pos % _halfSize] = (byte) ((bArray & 0x0F) | (bInput << 4) & 0xFF); return old; } /** * Sets the byte value for the given position. */ public byte set(int x, int y, int z, byte b, byte oldB) { int pos = (x * _lX * _lY) + (y * _lX) + z; if (x >= _lX || y >= _lY || z >= _lZ || x < 0 || y < 0 || z < 0) return 0; if (pos < _halfSize) { int bArray = _array[pos] & 0xFF; byte old = (byte) ((bArray & 0x0F) & 0xFF); if (old == oldB) { int bInput = b & 0xFF; _array[pos] = (byte) ((bInput & 0x0F) | (bArray & 0xF0)); } return old; } int bArray = _array[pos % _halfSize] & 0xFF; byte old = (byte) (bArray >> 4); int bInput = b & 0xFF; _array[pos % _halfSize] = (byte) ((bArray & 0x0F) | (bInput << 4) & 0xFF); return old; } /** * Returns the raw byte at the given index. */ public byte getRawByte(int i) { return _array[i]; } /** * Sets the raw byte for the given index. */ public void setRawByte(int i, byte b) { _array[i] = b; } /** * Returns the size of this array. */ public int size() { return _size; } /** * Returns the packed size of this array. */ public int sizePacked() { return _halfSize; } }