Browse Source

Merge pull request #456 from tonihele/new-tangent-generator

Use the newer tangent generator, fixes the shiny sphere template
Toni Helenius 2 years ago
parent
commit
0e007f1c6d

+ 2 - 1
jme3-codepalette/src/com/jme3/gde/codepalette/scene/JmePaletteShinySphere.java

@@ -47,10 +47,11 @@ public class JmePaletteShinySphere implements ActiveEditorDrop {
 
     private String createBody() {
 
-        String body = "/** Illuminated bumpy rock with shiny effect. \n *  Uses Texture from jme3-test-data library! Needs light source! */\nSphere sphereMesh = new Sphere(32,32, 2f);\nGeometry shinyGeo = new Geometry(\"Shiny rock\", sphereMesh);\nrock.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres\nTangentBinormalGenerator.generate(rock);   // for lighting effect\nMaterial shinyMat = new Material( assetManager, \"Common/MatDefs/Light/Lighting.j3md\");\nshinyMat.setTexture(\"DiffuseMap\", assetManager.loadTexture(\"Textures/Terrain/Pond/Pond.png\"));\nshinyMat.setTexture(\"NormalMap\",  assetManager.loadTexture(\"Textures/Terrain/Pond/Pond_normal.png\"));\n//shinyMat.setTexture(\"GlowMap\", assetManager.loadTexture(\"Textures/glowmap.png\")); // requires glow filter!\nshinyMat.setBoolean(\"UseMaterialColors\",true);  // needed for shininess\nshinyMat.setColor(\"Specular\", ColorRGBA.White); // needed for shininess\nshinyMat.setColor(\"Diffuse\",  ColorRGBA.White); // needed for shininess\nshinyMat.setFloat(\"Shininess\", 5f); // shininess from 1-128\nshinyGeo.setMaterial(shinyMat);\nrootNode.attachChild(shinyGeo);";
+        String body = "/** Illuminated bumpy rock with shiny effect. \n *  Uses Texture from jme3-test-data library! Needs light source! */\nSphere sphereMesh = new Sphere(32,32, 2f);\nGeometry shinyGeo = new Geometry(\"Shiny rock\", sphereMesh);\nsphereMesh.setTextureMode(Sphere.TextureMode.Projected); // better quality on spheres\nMikktspaceTangentGenerator.generate(shinyGeo);   // for lighting effect\nMaterial shinyMat = new Material( assetManager, \"Common/MatDefs/Light/Lighting.j3md\");\nshinyMat.setTexture(\"DiffuseMap\", assetManager.loadTexture(\"Textures/Terrain/Pond/Pond.jpg\"));\nshinyMat.setTexture(\"NormalMap\",  assetManager.loadTexture(\"Textures/Terrain/Pond/Pond_normal.png\"));\n//shinyMat.setTexture(\"GlowMap\", assetManager.loadTexture(\"Textures/glowmap.png\")); // requires glow filter!\nshinyMat.setBoolean(\"UseMaterialColors\",true);  // needed for shininess\nshinyMat.setColor(\"Specular\", ColorRGBA.White); // needed for shininess\nshinyMat.setColor(\"Diffuse\",  ColorRGBA.White); // needed for shininess\nshinyMat.setFloat(\"Shininess\", 5f); // shininess from 1-128\nshinyGeo.setMaterial(shinyMat);\nrootNode.attachChild(shinyGeo);";
         return body;
     }
 
+    @Override
     public boolean handleTransfer(JTextComponent targetComponent) {
         String body = createBody();
         try {

+ 0 - 2
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties

@@ -1,8 +1,6 @@
 NewCustomControlVisualPanel1.jTextField1.text=com.mycompany.mygame.MyControl
 NewCustomControlVisualPanel1.jLabel1.text=Class Name:
 AtlasBatchGeometryVisualPanel1.jTextArea1.text=Note that all the textures of the batched geometry have to fit in the atlas texture, else not all will be added to the atlas. There is no scaling happening!\n\nAlso note that when batching geometry with normal maps you have to make sure the current normal map and color/diffuse map etc. match in size for each geometry. \nE.g. a model with a diffuse map of 256x256 has to use a normal map with 256x256 pixels as well.
-GenerateTangentsVisualPanel1.jTextPane1.text=Warning this will likely modify the mesh by adding vertices.\nUse this if your normal map has mirrored parts.
-GenerateTangentsVisualPanel1.splitMirrored.text=Split vertices with mirrored UVs
 GenerateLODVisualPanel1.jPanel1.border.title=Reduction method
 GenerateLODVisualPanel1.jPanel2.border.title=Reduction values
 GenerateLODVisualPanel1.jLabel1.text=Type a value for each desired level

+ 8 - 54
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsTool.java

@@ -34,27 +34,18 @@ package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
 import com.jme3.gde.core.sceneexplorer.nodes.AbstractSceneExplorerNode;
 import com.jme3.gde.core.sceneexplorer.nodes.JmeGeometry;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractToolAction;
-import com.jme3.gde.core.sceneexplorer.nodes.actions.AbstractToolWizardAction;
 import com.jme3.gde.core.sceneexplorer.nodes.actions.ToolAction;
 import com.jme3.scene.Geometry;
 import com.jme3.scene.Mesh;
 import com.jme3.scene.VertexBuffer.Type;
-import com.jme3.util.TangentBinormalGenerator;
-import java.awt.Component;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-import javax.swing.JComponent;
-import org.openide.DialogDisplayer;
-import org.openide.WizardDescriptor;
-import org.openide.nodes.Node;
+import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
 
 /**
  *
  * @author normenhansen
  */
 @org.openide.util.lookup.ServiceProvider(service = ToolAction.class)
-public class GenerateTangentsTool extends AbstractToolWizardAction {
+public class GenerateTangentsTool extends AbstractToolAction {
 
     public GenerateTangentsTool() {
         name = "Generate Tangents";
@@ -75,55 +66,18 @@ public class GenerateTangentsTool extends AbstractToolWizardAction {
         }
     }
 
+    @Override
     public Class<?> getNodeClass() {
         return JmeGeometry.class;
     }
 
     @Override
-    protected Object showWizard(Node node) {
-         List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<WizardDescriptor.Panel<WizardDescriptor>>();
-        panels.add(new GenerateTangentsWizardPanel1());
-        for (int i = 0; i < panels.size(); i++) {
-            Component c = panels.get(i).getComponent();
-            if (c instanceof JComponent) { // assume Swing components
-                JComponent jc = (JComponent) c;
-                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, i);
-                jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, true);
-                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, true);
-                jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, true);
-            }
-        }
-        WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<WizardDescriptor>(panels));
-        // {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
-        wiz.setTitleFormat(new MessageFormat("{0}"));
-        wiz.setTitle("Generate tangents for this model");
-        if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
-            // do something
-            return wiz;
-        } 
-        return null;
-    }
-
-    @Override
-    protected Object doApplyTool(AbstractSceneExplorerNode rootNode, Object settings) {
-        WizardDescriptor wiz = (WizardDescriptor)settings;
+    protected Object doApplyTool(AbstractSceneExplorerNode rootNode) {
         Geometry geom = rootNode.getLookup().lookup(Geometry.class);
-        boolean splitMirrored = (Boolean)wiz.getProperties().get("splitMirrored");
-        
-        Mesh mesh = geom.getMesh();
-        Mesh keptMesh = null;
-        if (mesh != null) {
-            if(splitMirrored){
-                keptMesh  = mesh.deepClone();
-            }
-            TangentBinormalGenerator.generate(geom, splitMirrored);
-            
-        }
-        if(keptMesh == null){
-            return splitMirrored;
-        }else{
-            return keptMesh;
-        }
+
+        MikktspaceTangentGenerator.generate(geom);
+
+        return false;
     }
 
 }

+ 0 - 66
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsVisualPanel1.form

@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
-  <AuxValues>
-    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
-    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
-    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
-    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
-    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
-  </AuxValues>
-
-  <Layout>
-    <DimensionLayout dim="0">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="0" attributes="0">
-              <EmptySpace max="-2" attributes="0"/>
-              <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="jScrollPane1" pref="380" max="32767" attributes="0"/>
-                  <Component id="splitMirrored" max="32767" attributes="0"/>
-              </Group>
-              <EmptySpace max="-2" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-    <DimensionLayout dim="1">
-      <Group type="103" groupAlignment="0" attributes="0">
-          <Group type="102" alignment="0" attributes="0">
-              <EmptySpace min="-2" pref="15" max="-2" attributes="0"/>
-              <Component id="splitMirrored" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="-2" attributes="0"/>
-              <Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
-              <EmptySpace max="32767" attributes="0"/>
-          </Group>
-      </Group>
-    </DimensionLayout>
-  </Layout>
-  <SubComponents>
-    <Component class="javax.swing.JCheckBox" name="splitMirrored">
-      <Properties>
-        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-          <ResourceString bundle="com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties" key="GenerateTangentsVisualPanel1.splitMirrored.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-        </Property>
-      </Properties>
-    </Component>
-    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
-      <AuxValues>
-        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
-      </AuxValues>
-
-      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
-      <SubComponents>
-        <Component class="javax.swing.JTextPane" name="jTextPane1">
-          <Properties>
-            <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
-              <ResourceString bundle="com/jme3/gde/core/sceneexplorer/nodes/actions/impl/Bundle.properties" key="GenerateTangentsVisualPanel1.jTextPane1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
-            </Property>
-          </Properties>
-        </Component>
-      </SubComponents>
-    </Container>
-  </SubComponents>
-</Form>

+ 0 - 97
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsVisualPanel1.java

@@ -1,97 +0,0 @@
-/*
- *  Copyright (c) 2009-2010 jMonkeyEngine
- *  All rights reserved.
- * 
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- * 
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 
- *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
-
-import javax.swing.JPanel;
-
-public final class GenerateTangentsVisualPanel1 extends JPanel {
-
-    /**
-     * Creates new form GenerateTangentsVisualPanel1
-     */
-    public GenerateTangentsVisualPanel1() {
-        initComponents();
-    }
-
-    @Override
-    public String getName() {
-        return "Tangent generation options";
-    }
-     
-    public boolean isSplitMirrored(){
-        return splitMirrored.isSelected();
-    }
-
-    /**
-     * This method is called from within the constructor to initialize the form.
-     * WARNING: Do NOT modify this code. The content of this method is always
-     * regenerated by the Form Editor.
-     */
-    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
-    private void initComponents() {
-
-        splitMirrored = new javax.swing.JCheckBox();
-        jScrollPane1 = new javax.swing.JScrollPane();
-        jTextPane1 = new javax.swing.JTextPane();
-
-        org.openide.awt.Mnemonics.setLocalizedText(splitMirrored, org.openide.util.NbBundle.getMessage(GenerateTangentsVisualPanel1.class, "GenerateTangentsVisualPanel1.splitMirrored.text")); // NOI18N
-
-        jTextPane1.setText(org.openide.util.NbBundle.getMessage(GenerateTangentsVisualPanel1.class, "GenerateTangentsVisualPanel1.jTextPane1.text")); // NOI18N
-        jScrollPane1.setViewportView(jTextPane1);
-
-        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
-        this.setLayout(layout);
-        layout.setHorizontalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addContainerGap()
-                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE)
-                    .addComponent(splitMirrored, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-                .addContainerGap())
-        );
-        layout.setVerticalGroup(
-            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
-            .addGroup(layout.createSequentialGroup()
-                .addGap(15, 15, 15)
-                .addComponent(splitMirrored)
-                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
-                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
-        );
-    }// </editor-fold>//GEN-END:initComponents
-    // Variables declaration - do not modify//GEN-BEGIN:variables
-    private javax.swing.JScrollPane jScrollPane1;
-    private javax.swing.JTextPane jTextPane1;
-    private javax.swing.JCheckBox splitMirrored;
-    // End of variables declaration//GEN-END:variables
-}

+ 0 - 93
jme3-core/src/com/jme3/gde/core/sceneexplorer/nodes/actions/impl/GenerateTangentsWizardPanel1.java

@@ -1,93 +0,0 @@
-/*
- *  Copyright (c) 2009-2010 jMonkeyEngine
- *  All rights reserved.
- * 
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- * 
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 
- *  * Neither the name of 'jMonkeyEngine' nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- * 
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-package com.jme3.gde.core.sceneexplorer.nodes.actions.impl;
-
-import javax.swing.event.ChangeListener;
-import org.openide.WizardDescriptor;
-import org.openide.util.HelpCtx;
-
-public class GenerateTangentsWizardPanel1 implements WizardDescriptor.Panel<WizardDescriptor> {
-
-    /**
-     * The visual component that displays this panel. If you need to access the
-     * component from this class, just use getComponent().
-     */
-    private GenerateTangentsVisualPanel1 component;
-
-    // Get the visual component for the panel. In this template, the component
-    // is kept separate. This can be more efficient: if the wizard is created
-    // but never displayed, or not all panels are displayed, it is better to
-    // create only those which really need to be visible.
-    @Override
-    public GenerateTangentsVisualPanel1 getComponent() {
-        if (component == null) {
-            component = new GenerateTangentsVisualPanel1();
-        }
-        return component;
-    }
-
-    @Override
-    public HelpCtx getHelp() {
-        // Show no Help button for this panel:
-        return HelpCtx.DEFAULT_HELP;
-        // If you have context help:
-        // return new HelpCtx("help.key.here");
-    }
-
-    @Override
-    public boolean isValid() {
-        // If it is always OK to press Next or Finish, then:
-        return true;
-        // If it depends on some condition (form filled out...) and
-        // this condition changes (last form field filled in...) then
-        // use ChangeSupport to implement add/removeChangeListener below.
-        // WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
-    }
-
-    @Override
-    public void addChangeListener(ChangeListener l) {
-    }
-
-    @Override
-    public void removeChangeListener(ChangeListener l) {
-    }
-
-    @Override
-    public void readSettings(WizardDescriptor wiz) {
-        // use wiz.getProperty to retrieve previous panel state
-    }
-
-    @Override
-    public void storeSettings(WizardDescriptor wiz) {
-        wiz.putProperty("splitMirrored", component.isSplitMirrored());
-    }
-}

+ 6 - 5
jme3-materialeditor/src/com/jme3/gde/materials/MaterialPreviewRenderer.java

@@ -22,7 +22,7 @@ import com.jme3.scene.Geometry;
 import com.jme3.scene.shape.Box;
 import com.jme3.scene.shape.Quad;
 import com.jme3.scene.shape.Sphere;
-import com.jme3.util.TangentBinormalGenerator;
+import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.logging.Level;
@@ -63,21 +63,22 @@ public class MaterialPreviewRenderer implements SceneListener {
         Sphere sphMesh = new Sphere(32, 32, 2.5f);
         sphMesh.setTextureMode(Sphere.TextureMode.Projected);
         sphMesh.updateGeometry(32, 32, 2.5f, false, false);
-        Logger log = Logger.getLogger(TangentBinormalGenerator.class.getName());
+        Logger log = Logger.getLogger(MikktspaceTangentGenerator.class.getName());
         log.setLevel(Level.SEVERE);
-        TangentBinormalGenerator.generate(sphMesh);
         sphere = new Geometry("previewSphere", sphMesh);
         sphere.setLocalRotation(new Quaternion().fromAngleAxis(FastMath.QUARTER_PI, Vector3f.UNIT_X));
+        MikktspaceTangentGenerator.generate(sphere);
 
         Box boxMesh = new Box(1.75f, 1.75f, 1.75f);
-        TangentBinormalGenerator.generate(boxMesh);
         box = new Geometry("previewBox", boxMesh);
         box.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.DEG_TO_RAD * 30, Vector3f.UNIT_X).multLocal(new Quaternion().fromAngleAxis(FastMath.QUARTER_PI, Vector3f.UNIT_Y)));
+        MikktspaceTangentGenerator.generate(box);
 
         Quad quadMesh = new Quad(4.5f, 4.5f);
-        TangentBinormalGenerator.generate(quadMesh);
         quad = new Geometry("previewQuad", quadMesh);
         quad.setLocalTranslation(new Vector3f(-2.25f, -2.25f, 0));
+        MikktspaceTangentGenerator.generate(quad);
+
         currentGeom = sphere;
         init = true;
     }

+ 18 - 20
jme3-scenecomposer/src/com/jme3/gde/scenecomposer/SceneEditorController.java

@@ -23,14 +23,13 @@ import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
 import com.jme3.scene.AssetLinkNode;
 import com.jme3.scene.Geometry;
-import com.jme3.scene.Mesh;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
 import com.jme3.scene.VertexBuffer.Type;
 import com.jme3.scene.control.Control;
 import com.jme3.util.TangentBinormalGenerator;
+import com.jme3.util.mikktspace.MikktspaceTangentGenerator;
 import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 import java.io.IOException;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -335,29 +334,28 @@ public class SceneEditorController implements NodeListener {
     public void doCreateTangents(Spatial selected) {
         if (selected instanceof Geometry) {
             Geometry geom = (Geometry) selected;
-            Mesh mesh = geom.getMesh();
-            if (mesh != null) {
-                TangentBinormalGenerator.generate(mesh);
-                createTrangentsUndo(mesh);
-            }
+            MikktspaceTangentGenerator.generate(geom);
+            createTangentsUndo(geom);
         }
     }
 
-    private void createTrangentsUndo(final Mesh mesh) {
-        if (mesh != null) {
-            Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() {
+    private void createTangentsUndo(final Geometry geometry) {
+        if (geometry == null) {
+            return;
+        }
 
-                @Override
-                public void sceneUndo() throws CannotUndoException {
-                    mesh.clearBuffer(Type.Tangent);
-                }
+        Lookup.getDefault().lookup(SceneUndoRedoManager.class).addEdit(this, new AbstractUndoableSceneEdit() {
 
-                @Override
-                public void sceneRedo() throws CannotRedoException {
-                    TangentBinormalGenerator.generate(mesh);
-                }
-            });
-        }
+            @Override
+            public void sceneUndo() throws CannotUndoException {
+                geometry.getMesh().clearBuffer(Type.Tangent);
+            }
+
+            @Override
+            public void sceneRedo() throws CannotRedoException {
+                TangentBinormalGenerator.generate(geometry);
+            }
+        });
     }
 
     public void createPhysicsMeshForSelectedSpatial() {