diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java index 35296d415..5870132a3 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/BaseHandler.java @@ -13,7 +13,9 @@ import net.sf.openrocket.file.rocksim.RocksimCommonConstants; import net.sf.openrocket.file.rocksim.RocksimDensityType; import net.sf.openrocket.file.simplesax.AbstractElementHandler; import net.sf.openrocket.material.Material; +import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.rocketcomponent.SymmetricComponent; import org.xml.sax.SAXException; @@ -50,6 +52,8 @@ public abstract class BaseHandler extends AbstractEle */ private String materialName = ""; + private RockSimAppearanceBuilder appearanceBuilder = new RockSimAppearanceBuilder(); + /** * The SAX method called when the closing element tag is reached. * @@ -85,6 +89,8 @@ public abstract class BaseHandler extends AbstractEle if (RocksimCommonConstants.DENSITY_TYPE.equals(element)) { densityType = RocksimDensityType.fromCode(Integer.parseInt(content)); } + + appearanceBuilder.processElement(element, content, warnings); } catch (NumberFormatException nfe) { warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number."); } @@ -101,6 +107,17 @@ public abstract class BaseHandler extends AbstractEle */ density = computeDensity(densityType, density); RocketComponent component = getComponent(); + + //TODO - What RockSim components can have Appearances? + if ( component instanceof ExternalComponent ){ + //If a symmetric component is set to PreventSeam then it is repeated + //twice as many times around the rocket. + if ( component instanceof SymmetricComponent && appearanceBuilder.isPreventSeam() ){ + appearanceBuilder.setScaleU(appearanceBuilder.getScaleU()*2); + } + component.setAppearance(appearanceBuilder.getAppearance()); + } + updateComponentMaterial(component, materialName, getMaterialType(), density); } diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java b/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java index 01b49030d..b57612c88 100644 --- a/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java +++ b/core/src/net/sf/openrocket/file/rocksim/importt/FinSetHandler.java @@ -139,6 +139,8 @@ class FinSetHandler extends AbstractElementHandler { */ private Double calcCg = 0d; + private RockSimAppearanceBuilder appearanceBuilder = new RockSimAppearanceBuilder(); + /** * Constructor. @@ -238,6 +240,8 @@ class FinSetHandler extends AbstractElementHandler { if (RocksimCommonConstants.CALC_CG.equals(element)) { calcCg = Double.parseDouble(content) / RocksimCommonConstants.ROCKSIM_TO_OPENROCKET_LENGTH; } + + appearanceBuilder.processElement(element, content, warnings); } catch (NumberFormatException nfe) { warnings.add("Could not convert " + element + " value of " + content + ". It is expected to be a number."); @@ -249,6 +253,9 @@ class FinSetHandler extends AbstractElementHandler { String content, WarningSet warnings) throws SAXException { //Create the fin set and correct for overrides and actual material densities final FinSet finSet = asOpenRocket(warnings); + + finSet.setAppearance(appearanceBuilder.getAppearance()); + if (component.isCompatible(finSet)) { BaseHandler.setOverride(finSet, override, mass, cg); if (!override && finSet.getCrossSection().equals(FinSet.CrossSection.AIRFOIL)) { diff --git a/core/src/net/sf/openrocket/file/rocksim/importt/RockSimAppearanceBuilder.java b/core/src/net/sf/openrocket/file/rocksim/importt/RockSimAppearanceBuilder.java new file mode 100644 index 000000000..225fa8cc3 --- /dev/null +++ b/core/src/net/sf/openrocket/file/rocksim/importt/RockSimAppearanceBuilder.java @@ -0,0 +1,154 @@ +package net.sf.openrocket.file.rocksim.importt; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.MalformedURLException; + +import net.sf.openrocket.aerodynamics.WarningSet; +import net.sf.openrocket.appearance.Appearance; +import net.sf.openrocket.appearance.AppearanceBuilder; +import net.sf.openrocket.appearance.Decal.EdgeMode; +import net.sf.openrocket.file.rocksim.RocksimCommonConstants; +import net.sf.openrocket.util.Color; + +public class RockSimAppearanceBuilder extends AppearanceBuilder { + private double specularW = 1, ambientW = 1, diffuseW = 1; + private boolean oneColor; + boolean preventSeam = false; + boolean repeat = false; + + @Override + public Appearance getAppearance() { + if (oneColor) { + setDiffuse(weight(getDiffuse(), diffuseW)); + setAmbient(weight(getDiffuse(), ambientW)); + setSpecular(weight(getDiffuse(), specularW)); + } else { + setDiffuse(weight(getDiffuse(), diffuseW)); + setAmbient(weight(getAmbient(), ambientW)); + setSpecular(weight(getSpecular(), specularW)); + } + + + + return super.getAppearance(); + } + + public void processElement(String element, String content, WarningSet warnings) { + try { + if (RocksimCommonConstants.TEXTURE.equals(element)) { + parseTexture(content); + } else if ("Ambient".equals(element)) { + ambientW = Double.parseDouble(content); + } else if ("Diffuse".equals(element)) { + diffuseW = Double.parseDouble(content); + } else if ("Specular".equals(element)) { + specularW = Double.parseDouble(content); + } else if ("AbientColor".equals(element)) { + setAmbient(parseColor(content)); + } else if ("DiffuseColor".equals(element)) { + setDiffuse(parseColor(content)); + } else if ("SpecularColor".equals(element)) { + setSpecular(parseColor(content)); + } else if ("UseSingleColor".equals(element)) { + if ("1".equals(content)) { + oneColor = true; + } + } + } catch (Exception e) { + warnings.add("Could not convert " + element + " value of " + content + ": " + e.getMessage()); + } + } + + private void parseTexture(String s) throws FileNotFoundException, MalformedURLException { + final String[] parts = s.trim().split("\\|"); + + boolean interpolate = false; + boolean flipr = false; + boolean flips = false; + boolean flipt = false; + + + for (String part : parts) { + // Sometimes it is name=(value) and sometimes name(value) + final String name = part.substring(0, part.indexOf("(")).replace("=", ""); + + final String value = part.substring(part.indexOf("(") + 1, part.length() - 1); + + if ("file".equals(name)) { + if (value.length() > 0){ + final File f = new File(value); + if (!f.exists()) { + //Find out how to get path of current rocksim file + //so I can look in it's directory + } + setImage(f.toURI().toURL()); + } + } else if ("repeat".equals(name)) { + repeat = "1".equals(value); + } else if ("interpolate".equals(name)) { + interpolate = "1".equals(value); + } else if ("flipr".equals(name)) { + flipr = "1".equals(value); + } else if ("flips".equals(name)) { + flips = "1".equals(value); + } else if ("flipt".equals(name)) { + flipt = "1".equals(value); + } else if ("preventseam".equals(name)) { + preventSeam = "1".equals(value); + } else if ("position".equals(name)) { + String[] c = value.split(","); + setOffset(-1 - Double.parseDouble(c[0]), -1 - Double.parseDouble(c[1])); + } else if ("origin".equals(name)) { + String[] c = value.split(","); + setCenter(Double.parseDouble(c[0]), Double.parseDouble(c[1])); + } else if ("scale".equals(name)) { + String[] c = value.split(","); + setScale(-Double.parseDouble(c[0]), -Double.parseDouble(c[1])); + } + } + + if ( repeat ){ + setEdgeMode(EdgeMode.REPEAT); + } + + if ( preventSeam ){ + setEdgeMode(EdgeMode.MIRROR); + } + + //TODO Make use of these values + System.out.println("Interpolate: " + interpolate); + System.out.println("FlipR: " + flipr); + System.out.println("FlipS: " + flips); + System.out.println("FlipT: " + flipt);; + + } + + static Color weight(Color c, double w) { + return new Color((int) (c.getRed() * w), (int) (c.getGreen() * w), (int) (c.getBlue() * w), c.getAlpha()); + } + + static Color parseColor(String s) { + s = s.replace("rgb(", ""); + s = s.replace(")", ""); + String ss[] = s.split(","); + return new Color(Integer.parseInt(ss[0]), Integer.parseInt(ss[1]), Integer.parseInt(ss[2])); + } + + public boolean isPreventSeam() { + return preventSeam; + } + + public void setPreventSeam(boolean preventSeam) { + this.preventSeam = preventSeam; + } + + public boolean isRepeat() { + return repeat; + } + + public void setRepeat(boolean repeat) { + this.repeat = repeat; + } + +}