Login  Register

Re: 3D loaders - 2 questions

Posted by jfpauly on Nov 10, 2024; 5:00pm
URL: https://forum.jogamp.org/3D-loaders-2-questions-tp4043577p4043615.html

This is the code which convert c3d to  java3D. I cannot show only the code I added or changed . Sorry for my
lazyness about comments I should have made, for sure...

/**
 *

 3ds to java converter Copyright (C) 2003 Pieter Bos.

___________________
 * <p>Changes (jfp 02/2017, 02/2019)
 * <p>
 * This library has been merged in Cliper with few changes.
 * <ul><li>MipMap option has been removed to be more simple because I had some
 * difficulties with textures.
 * <li>I use my own code to build Texture2D object
 * <li>Code has been added to scale models and allow shapes picking and
 * appearance to be changed
 * <li>readShape() has been changed to use GeometryArray.ALLOW_COORDINATE_WRITE
 * line 180 (03/02/2022)
 * <li>line 359 | access == F3DS added (url null if | access == F3DS not coded
 * (03/02/2022))
 * </ul>
 * <p>
 * To get textures files, they may be in a directory called textures.
 * <br>For instance :
 * <pre>
 *          /------------+
 *          | models     | ________/------------+
 *          +------------+         |  modelname | ______ modelname.c3d
 *                                 +------------+ ______/------------+
 *                                                      | textures   | ___ xxx.JPG
 *                                                      +------------+      V
 *                                                                         .....
 * </pre>
 */
public class Loader3d extends javax.swing.JPanel {

    String textureDir;
    boolean moreData;
    BufferedReader file;
    LinkedList<Shape3D> shapeList;
    SomeTools tools;
    UniverseAndMaster univers;

    /**
     * Constructor
     *
     * @param universe simple universe for all classes
     */
    public Loader3d(UniverseAndMaster universe) {
        univers = universe;
        shapeList = new LinkedList<>();
        tools = new SomeTools(univers);
    }

    /**
     * open a c3d file.
     * <p>
     * C3D files are intermediate file format made by 3ds2java program which is
     * part of the original package.
     *
     * @param tg the tg to which shapes will be added
     * @param model Model name
     * @throws java.io.IOException pb in c3d
     */
    public void readC3d(TransformGroup tg, String model) throws IOException {
        moreData = true;
            textureDir = model.substring(0, model.lastIndexOf('\\')) + "\\";        // search pictures in root
            try {   // read file
                FileInputStream fileStream = new FileInputStream(model);
                InputStreamReader inputStream = new InputStreamReader(fileStream);
                file = new BufferedReader(inputStream, 50000);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(this, "file " + model + " could not be read!",
                        "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

        //______________________________
        //read shapes until no more data
        //______________________________
        while (moreData) {
            Shape3D shape = readShape(file);
            if (shape != null) {
                tg.addChild(shape);
                shapeList.push(shape);
            } else {
                moreData = false;
            }
        }
        resize();
        //________
        // cleanup|
        //________|
        try {
            file.close();
            shapeList.clear();
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "file " + model + " could not be closed!",
                    "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * make a geometry and an appearance.
     * <p>
     * Compute model span to make it smaller (soyuz for instance)
     *
     * @param file to be processed
     * @return a shape3D
     */
    public Shape3D readShape(BufferedReader file) {
        GeometryInfo geometry = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
        float[] coords, normals;
        Appearance appear;
        coords = readArray(file);   // read coordinates_______
        if (coords == null) {
            return null;
        }
        normals = readArray(file);              // read normals___________
        if (normals == null) {
            JOptionPane.showMessageDialog(this, "no normals!", "Error", JOptionPane.ERROR_MESSAGE);
            return null;
        }
        setTextureCoords(file, geometry);
        geometry.setNormals(normals);
        geometry.setCoordinates(coords);
        appear = readAppearance(file);
        GeometryArray result = geometry.getGeometryArray();
        result.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
        Shape3D shape = new Shape3D(result, appear);
        shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);    // to allow picking color hil$à_t
        GeometryArray geoArray = (GeometryArray) shape.getGeometry();
        // Create Texture Coordinates if not already present
        if ((geoArray.getVertexFormat() & GeometryArray.TEXTURE_COORDINATE_2) == 0) {
            TexCoordGeneration tcg = new TexCoordGeneration();
            appear.setTexCoordGeneration(tcg);
        }
        return shape;
    }

    /**
     * Center the object and resize.
     * <br>This code was based on objloader code from Sun.
     * <br>It has been changed in some ways.
     */
    void resize() {
        Point3d center = new Point3d();
        Point3d upPt = new Point3d();
        Point3d loPt = new Point3d();
        double spanBig = 0, span;
        int numShapes = shapeList.size();
        float xShift = 0, yShift = 0, zShift = 0;   // components for offset vector
        for (int i = 0; i < numShapes; i++) {       // for all shapes get boundingSphere center and radius
            BoundingBox box = (BoundingBox) shapeList.get(i).getBounds();
            box.getCenter(center);
            xShift = +(float) center.x;
            yShift = +(float) center.y;
            zShift = +(float) center.z;
            box.getLower(loPt);
            box.getUpper(upPt);
            span = loPt.distance(upPt);
            if (span > spanBig) {
                spanBig = span;
            }
        }
        xShift = xShift / numShapes;
        yShift = yShift / numShapes;
        zShift = zShift / numShapes;
        Vector3f offset = new Vector3f(-xShift, -yShift, -zShift);       // vector to offset vertices coords
        for (int i = 0; i < numShapes; i++) {                               // apply scale and offset to vertices coords
            Shape3D shape = shapeList.get(i);                               // get a shape
            GeometryArray geoArray = (GeometryArray) shape.getGeometry();   // get it's Geometry
            int vtxCnt = geoArray.getVertexCount();                         // vertices count
            Point3f[] coords3f = new Point3f[vtxCnt];                       // array for vertices coordinates
            for (int j = 0; j < vtxCnt; j++) {                              // populate array
                coords3f[j] = new Point3f();
            }
            geoArray.getCoordinates(0, coords3f);                 // put shape's geometry vertices in array
            for (int vtxCtr = 0; vtxCtr < vtxCnt; vtxCtr++) {     // Change vertices coordinates and set in geoArray
                Point3f cur_vtx = coords3f[vtxCtr];               // get a vertex
                cur_vtx.add(cur_vtx, offset);                     // shift it
                cur_vtx.x /= spanBig;                             // scale it
                cur_vtx.y /= spanBig;
                cur_vtx.z /= spanBig;
            }
            geoArray.setCoordinates(0, coords3f);                 // update geometry with new values
        }   // go to next shape
        //____________________________________________________________________
        // find model shapes BoundingBox centers medium Y  value to set graph |
        // transform and make model visible (sometimes too high)              |  
        //____________________________________________________________________|
        for (int i = 0; i < numShapes; i++) {       // for all shapes get boundingSphere center and radius
            BoundingBox box = (BoundingBox) shapeList.get(i).getBounds();
            box.getCenter(center);
            yShift = yShift + (float) center.y;
        }
        yShift = yShift / numShapes;
        tools.shiftCoord(Y, -yShift, 0);    // 0 = add yShift to existing translation
    } // End of resize

    /**
     * read texture coords.
     *
     * @param file the file which is being read
     * @param geometry active geometry
     * @return number of Textures
     */
    public int setTextureCoords(BufferedReader file, GeometryInfo geometry) {
        int numberOfTextures;
        try {
            String line = file.readLine();
            numberOfTextures = Integer.parseInt(line);
        } catch (IOException | NumberFormatException e) {
            return 0;
        }
        //read all the textures__________________________________
        if (numberOfTextures > 0) {
            geometry.setTextureCoordinateParams(numberOfTextures, 2);
            for (int i = 0; i < numberOfTextures; i++) {
                geometry.setTextureCoordinates(i, readArray(file));
            }
        }
        return numberOfTextures;
    }

    /**
     * read lines in c3d file.
     *
     * @param file c3d file.
     * @return a float array
     */
    public float[] readArray(BufferedReader file) {
        float[] values;
        try {
            String line = file.readLine();
            if (line == null) {
                return null;
            }
            int numberOfValues = Integer.parseInt(line);
            values = new float[numberOfValues];
            for (int i = 0; i < numberOfValues; i++) {
                line = file.readLine();
                if (line == null) {
                    return null;
                }
                values[i] = Float.parseFloat(line);
            }
            return values;
        } catch (IOException | NumberFormatException e) {
            return null;
        }
    }

    /**
     * get lights, textures,...
     *
     * @param file c3d file.
     * @return an appearance
     */
    public Appearance readAppearance(BufferedReader file) {
        Appearance appear = new Appearance();
        appear.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
        appear.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
        Color3f ambient, diffuse, specular;
        float shininess, transparency;
        int selfIllum;
        ambient = new Color3f();
        diffuse = new Color3f();
        specular = new Color3f();
        shininess = 0;
        selfIllum = 0;
        transparency = 0;

        try {
            float[] temp = new float[3];
            String line = file.readLine();
            temp[0] = Float.parseFloat(line);
            line = file.readLine();
            temp[1] = Float.parseFloat(line);
            line = file.readLine();
            temp[2] = Float.parseFloat(line);
            ambient.set(temp);

            line = file.readLine();
            selfIllum = Integer.parseInt(line);

            line = file.readLine();
            temp[0] = Float.parseFloat(line);
            line = file.readLine();
            temp[1] = Float.parseFloat(line);
            line = file.readLine();
            temp[2] = Float.parseFloat(line);
            diffuse.set(temp);

            line = file.readLine();
            temp[0] = Float.parseFloat(line);
            line = file.readLine();
            temp[1] = Float.parseFloat(line);
            line = file.readLine();
            temp[2] = Float.parseFloat(line);
            specular.set(temp);

            line = file.readLine();
            shininess = Float.parseFloat(line);

            line = file.readLine();
            transparency = Float.parseFloat(line);

            //if (numberOfTextures > 0)
            line = file.readLine();
            if (!line.equals("")) {
                TextureLoader loader = null;
                //_____________________________________________
                // local access. Build a loader with a filepath
                //_____________________________________________

                    line = textureDir + line;   // path to texture image file
                    File fic = new File(line);
                    if (fic.exists()) {
                        loader = new TextureLoader(line, this);
                    }

                //________________
                // build Texture2D
                //________________
                if (loader != null) {
                    ImageComponent2D image = loader.getImage();
                    Texture2D texture = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGBA, image.getWidth(), image.getHeight());
                    texture.setCapability(Texture2D.ALLOW_IMAGE_WRITE);
                    texture.setImage(0, image);
                    if (appear.getCapability(Appearance.ALLOW_TEXTURE_WRITE) == false) {
                        JOptionPane.showMessageDialog(this, "Appearance", "no capability to set texture", JOptionPane.ERROR_MESSAGE);
                        return null;
                    }
                    appear.setTexture(texture);
                }
            }
        } catch (IOException | NumberFormatException | HeadlessException e) {
            JOptionPane.showMessageDialog(this, "no normals!",
                    "Error", JOptionPane.ERROR_MESSAGE);
        }
        Material mat = new Material(ambient, new Color3f(selfIllum / 100, selfIllum / 100, selfIllum / 100),
                diffuse, specular, shininess);
        mat.setCapability(Material.ALLOW_COMPONENT_WRITE);
        appear.setMaterial(mat);
        if (transparency > 0) {
            TransparencyAttributes transpar = new TransparencyAttributes(
                    TransparencyAttributes.BLENDED,
                    transparency);
            appear.setTransparencyAttributes(transpar);
        }
        return appear;
    }