Image.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. /*
  2. * Copyright (c) 2009-2010 jMonkeyEngine
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. *
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. */
  32. package com.jme3.texture;
  33. import com.jme3.export.*;
  34. import com.jme3.renderer.Caps;
  35. import com.jme3.renderer.Renderer;
  36. import com.jme3.util.NativeObject;
  37. import java.io.IOException;
  38. import java.nio.ByteBuffer;
  39. import java.util.ArrayList;
  40. import java.util.Arrays;
  41. import java.util.List;
  42. /**
  43. * <code>Image</code> defines a data format for a graphical image. The image
  44. * is defined by a format, a height and width, and the image data. The width and
  45. * height must be greater than 0. The data is contained in a byte buffer, and
  46. * should be packed before creation of the image object.
  47. *
  48. * @author Mark Powell
  49. * @author Joshua Slack
  50. * @version $Id: Image.java 4131 2009-03-19 20:15:28Z blaine.dev $
  51. */
  52. public class Image extends NativeObject implements Savable /*, Cloneable*/ {
  53. public enum Format {
  54. /**
  55. * 8-bit alpha
  56. */
  57. Alpha8(8),
  58. /**
  59. * 16-bit alpha
  60. */
  61. Alpha16(16),
  62. /**
  63. * 8-bit grayscale/luminance.
  64. */
  65. Luminance8(8),
  66. /**
  67. * 16-bit grayscale/luminance.
  68. */
  69. Luminance16(16),
  70. /**
  71. * half-precision floating-point grayscale/luminance.
  72. */
  73. Luminance16F(16,true),
  74. /**
  75. * single-precision floating-point grayscale/luminance.
  76. */
  77. Luminance32F(32,true),
  78. /**
  79. * 8-bit luminance/grayscale and 8-bit alpha.
  80. */
  81. Luminance8Alpha8(16),
  82. /**
  83. * 16-bit luminance/grayscale and 16-bit alpha.
  84. */
  85. Luminance16Alpha16(32),
  86. /**
  87. * half-precision floating-point grayscale/luminance and alpha.
  88. */
  89. Luminance16FAlpha16F(32,true),
  90. Intensity8(8),
  91. Intensity16(16),
  92. /**
  93. * 8-bit blue, green, and red.
  94. */
  95. BGR8(24), // BGR and ABGR formats are often used on windows systems
  96. /**
  97. * 8-bit red, green, and blue.
  98. */
  99. RGB8(24),
  100. /**
  101. * 10-bit red, green, and blue.
  102. */
  103. RGB10(30),
  104. /**
  105. * 16-bit red, green, and blue.
  106. */
  107. RGB16(48),
  108. /**
  109. * 5-bit red, 6-bit green, and 5-bit blue.
  110. */
  111. RGB565(16),
  112. /**
  113. * 4-bit alpha, red, green, and blue. Used on Android only.
  114. */
  115. ARGB4444(16),
  116. /**
  117. * 5-bit red, green, and blue with 1-bit alpha.
  118. */
  119. RGB5A1(16),
  120. /**
  121. * 8-bit red, green, blue, and alpha.
  122. */
  123. RGBA8(32),
  124. /**
  125. * 8-bit alpha, blue, green, and red.
  126. */
  127. ABGR8(32),
  128. /**
  129. * 16-bit red, green, blue and alpha
  130. */
  131. RGBA16(64),
  132. /**
  133. * S3TC compression DXT1.
  134. * Called BC1 in DirectX10.
  135. */
  136. DXT1(4,false,true, false),
  137. /**
  138. * S3TC compression DXT1 with 1-bit alpha.
  139. */
  140. DXT1A(4,false,true, false),
  141. /**
  142. * S3TC compression DXT3 with 4-bit alpha.
  143. * Called BC2 in DirectX10.
  144. */
  145. DXT3(8,false,true, false),
  146. /**
  147. * S3TC compression DXT5 with interpolated 8-bit alpha.
  148. * Called BC3 in DirectX10.
  149. */
  150. DXT5(8,false,true, false),
  151. /**
  152. * Luminance-Alpha Texture Compression.
  153. * Called BC5 in DirectX10.
  154. */
  155. LATC(8, false, true, false),
  156. /**
  157. * Arbitrary depth format. The precision is chosen by the video
  158. * hardware.
  159. */
  160. Depth(0,true,false,false),
  161. /**
  162. * 16-bit depth.
  163. */
  164. Depth16(16,true,false,false),
  165. /**
  166. * 24-bit depth.
  167. */
  168. Depth24(24,true,false,false),
  169. /**
  170. * 32-bit depth.
  171. */
  172. Depth32(32,true,false,false),
  173. /**
  174. * single-precision floating point depth.
  175. */
  176. Depth32F(32,true,false,true),
  177. /**
  178. * Texture data is stored as {@link Format#RGB16F} in system memory,
  179. * but will be converted to {@link Format#RGB111110F} when sent
  180. * to the video hardware.
  181. */
  182. RGB16F_to_RGB111110F(48,true),
  183. /**
  184. * unsigned floating-point red, green and blue that uses 32 bits.
  185. */
  186. RGB111110F(32,true),
  187. /**
  188. * Texture data is stored as {@link Format#RGB16F} in system memory,
  189. * but will be converted to {@link Format#RGB9E5} when sent
  190. * to the video hardware.
  191. */
  192. RGB16F_to_RGB9E5(48,true),
  193. /**
  194. * 9-bit red, green and blue with 5-bit exponent.
  195. */
  196. RGB9E5(32,true),
  197. /**
  198. * half-precision floating point red, green, and blue.
  199. */
  200. RGB16F(48,true),
  201. /**
  202. * half-precision floating point red, green, blue, and alpha.
  203. */
  204. RGBA16F(64,true),
  205. /**
  206. * single-precision floating point red, green, and blue.
  207. */
  208. RGB32F(96,true),
  209. /**
  210. * single-precision floating point red, green, blue and alpha.
  211. */
  212. RGBA32F(128,true),
  213. /**
  214. * Luminance/grayscale texture compression.
  215. * Called BC4 in DirectX10.
  216. */
  217. LTC(4, false, true, false),
  218. /**
  219. * 24-bit depth with 8-bit stencil.
  220. * Check the cap {@link Caps#PackedDepthStencilBuffer}.
  221. */
  222. Depth24Stencil8(32, true, false, false);
  223. private int bpp;
  224. private boolean isDepth;
  225. private boolean isCompressed;
  226. private boolean isFloatingPoint;
  227. private Format(int bpp){
  228. this.bpp = bpp;
  229. }
  230. private Format(int bpp, boolean isFP){
  231. this(bpp);
  232. this.isFloatingPoint = isFP;
  233. }
  234. private Format(int bpp, boolean isDepth, boolean isCompressed, boolean isFP){
  235. this(bpp, isFP);
  236. this.isDepth = isDepth;
  237. this.isCompressed = isCompressed;
  238. }
  239. /**
  240. * @return bits per pixel.
  241. */
  242. public int getBitsPerPixel(){
  243. return bpp;
  244. }
  245. /**
  246. * @return True if this format is a depth format, false otherwise.
  247. */
  248. public boolean isDepthFormat(){
  249. return isDepth;
  250. }
  251. /**
  252. * @return True if this is a compressed image format, false if
  253. * uncompressed.
  254. */
  255. public boolean isCompressed() {
  256. return isCompressed;
  257. }
  258. /**
  259. * @return True if this image format is in floating point,
  260. * false if it is an integer format.
  261. */
  262. public boolean isFloatingPont(){
  263. return isFloatingPoint;
  264. }
  265. }
  266. // image attributes
  267. protected Format format;
  268. protected int width, height, depth;
  269. protected int[] mipMapSizes;
  270. protected ArrayList<ByteBuffer> data;
  271. protected transient Object efficientData;
  272. protected int multiSamples = 1;
  273. // protected int mipOffset = 0;
  274. // attributes relating to GL object
  275. protected boolean mipsWereGenerated = false;
  276. protected boolean needGeneratedMips = false;
  277. /**
  278. * Internal use only.
  279. * The renderer marks which images have generated mipmaps in VRAM
  280. * and which do not, so it can generate them as needed.
  281. *
  282. * @param generated If mipmaps were generated or not.
  283. */
  284. public void setMipmapsGenerated(boolean generated) {
  285. this.mipsWereGenerated = generated;
  286. }
  287. /**
  288. * Internal use only.
  289. * Check if the renderer has generated mipmaps for this image in VRAM
  290. * or not.
  291. *
  292. * @return If mipmaps were generated already.
  293. */
  294. public boolean isMipmapsGenerated() {
  295. return mipsWereGenerated;
  296. }
  297. /**
  298. * (Package private) Called by {@link Texture} when
  299. * {@link #isMipmapsGenerated() } is false in order to generate
  300. * mipmaps for this image.
  301. */
  302. void setNeedGeneratedMipmaps() {
  303. needGeneratedMips = true;
  304. }
  305. /**
  306. * @return True if the image needs to have mipmaps generated
  307. * for it (as requested by the texture).
  308. */
  309. public boolean isGeneratedMipmapsRequired() {
  310. return needGeneratedMips;
  311. }
  312. @Override
  313. public void resetObject() {
  314. this.id = -1;
  315. this.mipsWereGenerated = false;
  316. setUpdateNeeded();
  317. }
  318. @Override
  319. public void deleteObject(Object rendererObject) {
  320. ((Renderer)rendererObject).deleteImage(this);
  321. }
  322. @Override
  323. public NativeObject createDestructableClone() {
  324. return new Image(id);
  325. }
  326. /**
  327. * @return A shallow clone of this image. The data is not cloned.
  328. */
  329. @Override
  330. public Image clone(){
  331. Image clone = (Image) super.clone();
  332. clone.mipMapSizes = mipMapSizes != null ? mipMapSizes.clone() : null;
  333. clone.data = data != null ? new ArrayList<ByteBuffer>(data) : null;
  334. clone.setUpdateNeeded();
  335. return clone;
  336. }
  337. /**
  338. * Constructor instantiates a new <code>Image</code> object. All values
  339. * are undefined.
  340. */
  341. public Image() {
  342. super(Image.class);
  343. data = new ArrayList<ByteBuffer>(1);
  344. }
  345. protected Image(int id){
  346. super(Image.class, id);
  347. }
  348. /**
  349. * Constructor instantiates a new <code>Image</code> object. The
  350. * attributes of the image are defined during construction.
  351. *
  352. * @param format
  353. * the data format of the image.
  354. * @param width
  355. * the width of the image.
  356. * @param height
  357. * the height of the image.
  358. * @param data
  359. * the image data.
  360. * @param mipMapSizes
  361. * the array of mipmap sizes, or null for no mipmaps.
  362. */
  363. public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data,
  364. int[] mipMapSizes) {
  365. this();
  366. if (mipMapSizes != null && mipMapSizes.length <= 1) {
  367. mipMapSizes = null;
  368. }
  369. setFormat(format);
  370. this.width = width;
  371. this.height = height;
  372. this.data = data;
  373. this.depth = depth;
  374. this.mipMapSizes = mipMapSizes;
  375. }
  376. /**
  377. * Constructor instantiates a new <code>Image</code> object. The
  378. * attributes of the image are defined during construction.
  379. *
  380. * @param format
  381. * the data format of the image.
  382. * @param width
  383. * the width of the image.
  384. * @param height
  385. * the height of the image.
  386. * @param data
  387. * the image data.
  388. * @param mipMapSizes
  389. * the array of mipmap sizes, or null for no mipmaps.
  390. */
  391. public Image(Format format, int width, int height, ByteBuffer data,
  392. int[] mipMapSizes) {
  393. this();
  394. if (mipMapSizes != null && mipMapSizes.length <= 1) {
  395. mipMapSizes = null;
  396. }
  397. setFormat(format);
  398. this.width = width;
  399. this.height = height;
  400. if (data != null){
  401. this.data = new ArrayList<ByteBuffer>(1);
  402. this.data.add(data);
  403. }
  404. this.mipMapSizes = mipMapSizes;
  405. }
  406. /**
  407. * Constructor instantiates a new <code>Image</code> object. The
  408. * attributes of the image are defined during construction.
  409. *
  410. * @param format
  411. * the data format of the image.
  412. * @param width
  413. * the width of the image.
  414. * @param height
  415. * the height of the image.
  416. * @param data
  417. * the image data.
  418. */
  419. public Image(Format format, int width, int height, int depth, ArrayList<ByteBuffer> data) {
  420. this(format, width, height, depth, data, null);
  421. }
  422. /**
  423. * Constructor instantiates a new <code>Image</code> object. The
  424. * attributes of the image are defined during construction.
  425. *
  426. * @param format
  427. * the data format of the image.
  428. * @param width
  429. * the width of the image.
  430. * @param height
  431. * the height of the image.
  432. * @param data
  433. * the image data.
  434. */
  435. public Image(Format format, int width, int height, ByteBuffer data) {
  436. this(format, width, height, data, null);
  437. }
  438. /**
  439. * @return The number of samples (for multisampled textures).
  440. * @see Image#setMultiSamples(int)
  441. */
  442. public int getMultiSamples() {
  443. return multiSamples;
  444. }
  445. /**
  446. * @param multiSamples Set the number of samples to use for this image,
  447. * setting this to a value higher than 1 turns this image/texture
  448. * into a multisample texture (on OpenGL3.1 and higher).
  449. */
  450. public void setMultiSamples(int multiSamples) {
  451. if (multiSamples <= 0)
  452. throw new IllegalArgumentException("multiSamples must be > 0");
  453. if (getData(0) != null)
  454. throw new IllegalArgumentException("Cannot upload data as multisample texture");
  455. if (hasMipmaps())
  456. throw new IllegalArgumentException("Multisample textures do not support mipmaps");
  457. this.multiSamples = multiSamples;
  458. }
  459. /**
  460. * <code>setData</code> sets the data that makes up the image. This data
  461. * is packed into an array of <code>ByteBuffer</code> objects.
  462. *
  463. * @param data
  464. * the data that contains the image information.
  465. */
  466. public void setData(ArrayList<ByteBuffer> data) {
  467. this.data = data;
  468. setUpdateNeeded();
  469. }
  470. /**
  471. * <code>setData</code> sets the data that makes up the image. This data
  472. * is packed into a single <code>ByteBuffer</code>.
  473. *
  474. * @param data
  475. * the data that contains the image information.
  476. */
  477. public void setData(ByteBuffer data) {
  478. this.data = new ArrayList<ByteBuffer>(1);
  479. this.data.add(data);
  480. setUpdateNeeded();
  481. }
  482. public void addData(ByteBuffer data) {
  483. if (this.data == null)
  484. this.data = new ArrayList<ByteBuffer>(1);
  485. this.data.add(data);
  486. setUpdateNeeded();
  487. }
  488. public void setData(int index, ByteBuffer data) {
  489. if (index >= 0) {
  490. while (this.data.size() <= index) {
  491. this.data.add(null);
  492. }
  493. this.data.set(index, data);
  494. setUpdateNeeded();
  495. } else {
  496. throw new IllegalArgumentException("index must be greater than or equal to 0.");
  497. }
  498. }
  499. /**
  500. * Set the efficient data representation of this image.
  501. * <p>
  502. * Some system implementations are more efficient at operating
  503. * on data other than ByteBuffers, in that case, this method can be used.
  504. *
  505. * @param efficientData
  506. */
  507. public void setEfficentData(Object efficientData){
  508. this.efficientData = efficientData;
  509. setUpdateNeeded();
  510. }
  511. /**
  512. * @return The efficient data representation of this image.
  513. * @see Image#setEfficentData(java.lang.Object)
  514. */
  515. public Object getEfficentData(){
  516. return efficientData;
  517. }
  518. /**
  519. * Sets the mipmap sizes stored in this image's data buffer. Mipmaps are
  520. * stored sequentially, and the first mipmap is the main image data. To
  521. * specify no mipmaps, pass null and this will automatically be expanded
  522. * into a single mipmap of the full
  523. *
  524. * @param mipMapSizes
  525. * the mipmap sizes array, or null for a single image map.
  526. */
  527. public void setMipMapSizes(int[] mipMapSizes) {
  528. if (mipMapSizes != null && mipMapSizes.length <= 1)
  529. mipMapSizes = null;
  530. this.mipMapSizes = mipMapSizes;
  531. setUpdateNeeded();
  532. }
  533. /**
  534. * <code>setHeight</code> sets the height value of the image. It is
  535. * typically a good idea to try to keep this as a multiple of 2.
  536. *
  537. * @param height
  538. * the height of the image.
  539. */
  540. public void setHeight(int height) {
  541. this.height = height;
  542. setUpdateNeeded();
  543. }
  544. /**
  545. * <code>setDepth</code> sets the depth value of the image. It is
  546. * typically a good idea to try to keep this as a multiple of 2. This is
  547. * used for 3d images.
  548. *
  549. * @param depth
  550. * the depth of the image.
  551. */
  552. public void setDepth(int depth) {
  553. this.depth = depth;
  554. setUpdateNeeded();
  555. }
  556. /**
  557. * <code>setWidth</code> sets the width value of the image. It is
  558. * typically a good idea to try to keep this as a multiple of 2.
  559. *
  560. * @param width
  561. * the width of the image.
  562. */
  563. public void setWidth(int width) {
  564. this.width = width;
  565. setUpdateNeeded();
  566. }
  567. /**
  568. * <code>setFormat</code> sets the image format for this image.
  569. *
  570. * @param format
  571. * the image format.
  572. * @throws NullPointerException
  573. * if format is null
  574. * @see Format
  575. */
  576. public void setFormat(Format format) {
  577. if (format == null) {
  578. throw new NullPointerException("format may not be null.");
  579. }
  580. this.format = format;
  581. setUpdateNeeded();
  582. }
  583. /**
  584. * <code>getFormat</code> returns the image format for this image.
  585. *
  586. * @return the image format.
  587. * @see Format
  588. */
  589. public Format getFormat() {
  590. return format;
  591. }
  592. /**
  593. * <code>getWidth</code> returns the width of this image.
  594. *
  595. * @return the width of this image.
  596. */
  597. public int getWidth() {
  598. return width;
  599. }
  600. /**
  601. * <code>getHeight</code> returns the height of this image.
  602. *
  603. * @return the height of this image.
  604. */
  605. public int getHeight() {
  606. return height;
  607. }
  608. /**
  609. * <code>getDepth</code> returns the depth of this image (for 3d images).
  610. *
  611. * @return the depth of this image.
  612. */
  613. public int getDepth() {
  614. return depth;
  615. }
  616. /**
  617. * <code>getData</code> returns the data for this image. If the data is
  618. * undefined, null will be returned.
  619. *
  620. * @return the data for this image.
  621. */
  622. public List<ByteBuffer> getData() {
  623. return data;
  624. }
  625. /**
  626. * <code>getData</code> returns the data for this image. If the data is
  627. * undefined, null will be returned.
  628. *
  629. * @return the data for this image.
  630. */
  631. public ByteBuffer getData(int index) {
  632. if (data.size() > index)
  633. return data.get(index);
  634. else
  635. return null;
  636. }
  637. /**
  638. * Returns whether the image data contains mipmaps.
  639. *
  640. * @return true if the image data contains mipmaps, false if not.
  641. */
  642. public boolean hasMipmaps() {
  643. return mipMapSizes != null;
  644. }
  645. /**
  646. * Returns the mipmap sizes for this image.
  647. *
  648. * @return the mipmap sizes for this image.
  649. */
  650. public int[] getMipMapSizes() {
  651. return mipMapSizes;
  652. }
  653. @Override
  654. public String toString(){
  655. StringBuilder sb = new StringBuilder();
  656. sb.append(getClass().getSimpleName());
  657. sb.append("[size=").append(width).append("x").append(height);
  658. if (depth > 1)
  659. sb.append("x").append(depth);
  660. sb.append(", format=").append(format.name());
  661. if (hasMipmaps())
  662. sb.append(", mips");
  663. if (getId() >= 0)
  664. sb.append(", id=").append(id);
  665. sb.append("]");
  666. return sb.toString();
  667. }
  668. @Override
  669. public boolean equals(Object other) {
  670. if (other == this) {
  671. return true;
  672. }
  673. if (!(other instanceof Image)) {
  674. return false;
  675. }
  676. Image that = (Image) other;
  677. if (this.getFormat() != that.getFormat())
  678. return false;
  679. if (this.getWidth() != that.getWidth())
  680. return false;
  681. if (this.getHeight() != that.getHeight())
  682. return false;
  683. if (this.getData() != null && !this.getData().equals(that.getData()))
  684. return false;
  685. if (this.getData() == null && that.getData() != null)
  686. return false;
  687. if (this.getMipMapSizes() != null
  688. && !Arrays.equals(this.getMipMapSizes(), that.getMipMapSizes()))
  689. return false;
  690. if (this.getMipMapSizes() == null && that.getMipMapSizes() != null)
  691. return false;
  692. if (this.getMultiSamples() != that.getMultiSamples())
  693. return false;
  694. return true;
  695. }
  696. @Override
  697. public int hashCode() {
  698. int hash = 7;
  699. hash = 97 * hash + (this.format != null ? this.format.hashCode() : 0);
  700. hash = 97 * hash + this.width;
  701. hash = 97 * hash + this.height;
  702. hash = 97 * hash + this.depth;
  703. hash = 97 * hash + Arrays.hashCode(this.mipMapSizes);
  704. hash = 97 * hash + (this.data != null ? this.data.hashCode() : 0);
  705. hash = 97 * hash + this.multiSamples;
  706. return hash;
  707. }
  708. public void write(JmeExporter e) throws IOException {
  709. OutputCapsule capsule = e.getCapsule(this);
  710. capsule.write(format, "format", Format.RGBA8);
  711. capsule.write(width, "width", 0);
  712. capsule.write(height, "height", 0);
  713. capsule.write(depth, "depth", 0);
  714. capsule.write(mipMapSizes, "mipMapSizes", null);
  715. capsule.write(multiSamples, "multiSamples", 1);
  716. capsule.writeByteBufferArrayList(data, "data", null);
  717. }
  718. public void read(JmeImporter e) throws IOException {
  719. InputCapsule capsule = e.getCapsule(this);
  720. format = capsule.readEnum("format", Format.class, Format.RGBA8);
  721. width = capsule.readInt("width", 0);
  722. height = capsule.readInt("height", 0);
  723. depth = capsule.readInt("depth", 0);
  724. mipMapSizes = capsule.readIntArray("mipMapSizes", null);
  725. multiSamples = capsule.readInt("multiSamples", 1);
  726. data = (ArrayList<ByteBuffer>) capsule.readByteBufferArrayList("data", null);
  727. }
  728. }