001package net.minecraft.util;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005
006public class Vec3
007{
008    /**
009     * A global Vec3Pool that always creates new vectors instead of reusing them and is thread-safe.
010     */
011    public static final Vec3Pool fakePool = new Vec3Pool(-1, -1);
012    public final Vec3Pool myVec3LocalPool;
013
014    /** X coordinate of Vec3D */
015    public double xCoord;
016
017    /** Y coordinate of Vec3D */
018    public double yCoord;
019
020    /** Z coordinate of Vec3D */
021    public double zCoord;
022
023    /**
024     * Static method for creating a new Vec3D given the three x,y,z values. This is only called from the other static
025     * method which creates and places it in the list.
026     */
027    public static Vec3 createVectorHelper(double par0, double par2, double par4)
028    {
029        return new Vec3(fakePool, par0, par2, par4);
030    }
031
032    protected Vec3(Vec3Pool par1Vec3Pool, double par2, double par4, double par6)
033    {
034        if (par2 == -0.0D)
035        {
036            par2 = 0.0D;
037        }
038
039        if (par4 == -0.0D)
040        {
041            par4 = 0.0D;
042        }
043
044        if (par6 == -0.0D)
045        {
046            par6 = 0.0D;
047        }
048
049        this.xCoord = par2;
050        this.yCoord = par4;
051        this.zCoord = par6;
052        this.myVec3LocalPool = par1Vec3Pool;
053    }
054
055    /**
056     * Sets the x,y,z components of the vector as specified.
057     */
058    protected Vec3 setComponents(double par1, double par3, double par5)
059    {
060        this.xCoord = par1;
061        this.yCoord = par3;
062        this.zCoord = par5;
063        return this;
064    }
065
066    @SideOnly(Side.CLIENT)
067
068    /**
069     * Returns a new vector with the result of the specified vector minus this.
070     */
071    public Vec3 subtract(Vec3 par1Vec3)
072    {
073        return this.myVec3LocalPool.getVecFromPool(par1Vec3.xCoord - this.xCoord, par1Vec3.yCoord - this.yCoord, par1Vec3.zCoord - this.zCoord);
074    }
075
076    /**
077     * Normalizes the vector to a length of 1 (except if it is the zero vector)
078     */
079    public Vec3 normalize()
080    {
081        double d0 = (double)MathHelper.sqrt_double(this.xCoord * this.xCoord + this.yCoord * this.yCoord + this.zCoord * this.zCoord);
082        return d0 < 1.0E-4D ? this.myVec3LocalPool.getVecFromPool(0.0D, 0.0D, 0.0D) : this.myVec3LocalPool.getVecFromPool(this.xCoord / d0, this.yCoord / d0, this.zCoord / d0);
083    }
084
085    public double dotProduct(Vec3 par1Vec3)
086    {
087        return this.xCoord * par1Vec3.xCoord + this.yCoord * par1Vec3.yCoord + this.zCoord * par1Vec3.zCoord;
088    }
089
090    @SideOnly(Side.CLIENT)
091
092    /**
093     * Returns a new vector with the result of this vector x the specified vector.
094     */
095    public Vec3 crossProduct(Vec3 par1Vec3)
096    {
097        return this.myVec3LocalPool.getVecFromPool(this.yCoord * par1Vec3.zCoord - this.zCoord * par1Vec3.yCoord, this.zCoord * par1Vec3.xCoord - this.xCoord * par1Vec3.zCoord, this.xCoord * par1Vec3.yCoord - this.yCoord * par1Vec3.xCoord);
098    }
099
100    /**
101     * Adds the specified x,y,z vector components to this vector and returns the resulting vector. Does not change this
102     * vector.
103     */
104    public Vec3 addVector(double par1, double par3, double par5)
105    {
106        return this.myVec3LocalPool.getVecFromPool(this.xCoord + par1, this.yCoord + par3, this.zCoord + par5);
107    }
108
109    /**
110     * Euclidean distance between this and the specified vector, returned as double.
111     */
112    public double distanceTo(Vec3 par1Vec3)
113    {
114        double d0 = par1Vec3.xCoord - this.xCoord;
115        double d1 = par1Vec3.yCoord - this.yCoord;
116        double d2 = par1Vec3.zCoord - this.zCoord;
117        return (double)MathHelper.sqrt_double(d0 * d0 + d1 * d1 + d2 * d2);
118    }
119
120    /**
121     * The square of the Euclidean distance between this and the specified vector.
122     */
123    public double squareDistanceTo(Vec3 par1Vec3)
124    {
125        double d0 = par1Vec3.xCoord - this.xCoord;
126        double d1 = par1Vec3.yCoord - this.yCoord;
127        double d2 = par1Vec3.zCoord - this.zCoord;
128        return d0 * d0 + d1 * d1 + d2 * d2;
129    }
130
131    /**
132     * The square of the Euclidean distance between this and the vector of x,y,z components passed in.
133     */
134    public double squareDistanceTo(double par1, double par3, double par5)
135    {
136        double d3 = par1 - this.xCoord;
137        double d4 = par3 - this.yCoord;
138        double d5 = par5 - this.zCoord;
139        return d3 * d3 + d4 * d4 + d5 * d5;
140    }
141
142    /**
143     * Returns the length of the vector.
144     */
145    public double lengthVector()
146    {
147        return (double)MathHelper.sqrt_double(this.xCoord * this.xCoord + this.yCoord * this.yCoord + this.zCoord * this.zCoord);
148    }
149
150    /**
151     * Returns a new vector with x value equal to the second parameter, along the line between this vector and the
152     * passed in vector, or null if not possible.
153     */
154    public Vec3 getIntermediateWithXValue(Vec3 par1Vec3, double par2)
155    {
156        double d1 = par1Vec3.xCoord - this.xCoord;
157        double d2 = par1Vec3.yCoord - this.yCoord;
158        double d3 = par1Vec3.zCoord - this.zCoord;
159
160        if (d1 * d1 < 1.0000000116860974E-7D)
161        {
162            return null;
163        }
164        else
165        {
166            double d4 = (par2 - this.xCoord) / d1;
167            return d4 >= 0.0D && d4 <= 1.0D ? this.myVec3LocalPool.getVecFromPool(this.xCoord + d1 * d4, this.yCoord + d2 * d4, this.zCoord + d3 * d4) : null;
168        }
169    }
170
171    /**
172     * Returns a new vector with y value equal to the second parameter, along the line between this vector and the
173     * passed in vector, or null if not possible.
174     */
175    public Vec3 getIntermediateWithYValue(Vec3 par1Vec3, double par2)
176    {
177        double d1 = par1Vec3.xCoord - this.xCoord;
178        double d2 = par1Vec3.yCoord - this.yCoord;
179        double d3 = par1Vec3.zCoord - this.zCoord;
180
181        if (d2 * d2 < 1.0000000116860974E-7D)
182        {
183            return null;
184        }
185        else
186        {
187            double d4 = (par2 - this.yCoord) / d2;
188            return d4 >= 0.0D && d4 <= 1.0D ? this.myVec3LocalPool.getVecFromPool(this.xCoord + d1 * d4, this.yCoord + d2 * d4, this.zCoord + d3 * d4) : null;
189        }
190    }
191
192    /**
193     * Returns a new vector with z value equal to the second parameter, along the line between this vector and the
194     * passed in vector, or null if not possible.
195     */
196    public Vec3 getIntermediateWithZValue(Vec3 par1Vec3, double par2)
197    {
198        double d1 = par1Vec3.xCoord - this.xCoord;
199        double d2 = par1Vec3.yCoord - this.yCoord;
200        double d3 = par1Vec3.zCoord - this.zCoord;
201
202        if (d3 * d3 < 1.0000000116860974E-7D)
203        {
204            return null;
205        }
206        else
207        {
208            double d4 = (par2 - this.zCoord) / d3;
209            return d4 >= 0.0D && d4 <= 1.0D ? this.myVec3LocalPool.getVecFromPool(this.xCoord + d1 * d4, this.yCoord + d2 * d4, this.zCoord + d3 * d4) : null;
210        }
211    }
212
213    public String toString()
214    {
215        return "(" + this.xCoord + ", " + this.yCoord + ", " + this.zCoord + ")";
216    }
217
218    /**
219     * Rotates the vector around the x axis by the specified angle.
220     */
221    public void rotateAroundX(float par1)
222    {
223        float f1 = MathHelper.cos(par1);
224        float f2 = MathHelper.sin(par1);
225        double d0 = this.xCoord;
226        double d1 = this.yCoord * (double)f1 + this.zCoord * (double)f2;
227        double d2 = this.zCoord * (double)f1 - this.yCoord * (double)f2;
228        this.xCoord = d0;
229        this.yCoord = d1;
230        this.zCoord = d2;
231    }
232
233    /**
234     * Rotates the vector around the y axis by the specified angle.
235     */
236    public void rotateAroundY(float par1)
237    {
238        float f1 = MathHelper.cos(par1);
239        float f2 = MathHelper.sin(par1);
240        double d0 = this.xCoord * (double)f1 + this.zCoord * (double)f2;
241        double d1 = this.yCoord;
242        double d2 = this.zCoord * (double)f1 - this.xCoord * (double)f2;
243        this.xCoord = d0;
244        this.yCoord = d1;
245        this.zCoord = d2;
246    }
247
248    @SideOnly(Side.CLIENT)
249
250    /**
251     * Rotates the vector around the z axis by the specified angle.
252     */
253    public void rotateAroundZ(float par1)
254    {
255        float f1 = MathHelper.cos(par1);
256        float f2 = MathHelper.sin(par1);
257        double d0 = this.xCoord * (double)f1 + this.yCoord * (double)f2;
258        double d1 = this.yCoord * (double)f1 - this.xCoord * (double)f2;
259        double d2 = this.zCoord;
260        this.xCoord = d0;
261        this.yCoord = d1;
262        this.zCoord = d2;
263    }
264}