private void decode(XMLDecoder in) throws Exception {
		setProgressMessage("Reading states ......");
		ModelState state = (ModelState) in.readObject();
		model.setElementMass("X1", state.getX1Mass());
		model.setElementMass("X2", state.getX2Mass());
		model.setElementMass("X3", state.getX3Mass());
		model.setElementMass("X4", state.getX4Mass());
		model.setElementSigma("X1", state.getX1Sigma());
		model.setElementSigma("X2", state.getX2Sigma());
		model.setElementSigma("X3", state.getX3Sigma());
		model.setElementSigma("X4", state.getX4Sigma());
		model.setElementEpsilon("X1", state.getX1Epsilon());
		model.setElementEpsilon("X2", state.getX2Epsilon());
		model.setElementEpsilon("X3", state.getX3Epsilon());
		model.setElementEpsilon("X4", state.getX4Epsilon());
		view.setElementArgb("X1", state.getX1Argb());
		view.setElementArgb("X2", state.getX2Argb());
		view.setElementArgb("X3", state.getX3Argb());
		view.setElementArgb("X4", state.getX4Argb());
		view.getViewer().setNavigationMode(state.getNavigationMode());
		if (state.getCameraAtom() < 0) {
			if (state.getCameraPosition() != null) {
				String[] cp = state.getCameraPosition().split("\\s");
				float cpx = Float.parseFloat(cp[0]);
				float cpy = Float.parseFloat(cp[1]);
				float cpz = Float.parseFloat(cp[2]);
				view.getViewer().setCameraPosition(cpx, cpy, cpz);
			}
		}
		else {
			Atom at = model.getAtom(state.getCameraAtom());
			view.getViewer().setCameraPosition(at.getRx(), at.getRy(), at.getRz());
		}
		String s = state.getRotation();
		view.setOrientation(s);
		if (state.getCameraAtom() < 0) {
			if (s != null) {
				String[] t = s.trim().split("\\s");
				float[] x = new float[] { 0, 0, 0, 0, 100 };
				for (int i = 0; i < Math.min(t.length, 5); i++)
					x[i] = Float.parseFloat(t[i]);
				if (x[0] == 0 && x[1] == 0 && x[2] == 0) // rotation axis (0, 0, 0) has no meaning, set it to z-axis
					x[2] = 1;
				view.setStartingScene(new Vector3f(x[0], x[1], x[2]), x[3], x[4]);
			}
		}
		view.setShowClock(state.getShowClock());
		view.setShowEnergizer(state.getShowEnergizer());
		view.setFillMode(state.getFillMode());
		List drawList = state.getDrawList();
		if (drawList != null && !drawList.isEmpty()) {
			DrawingElement e;
			for (Iterator it = drawList.iterator(); it.hasNext();) {
				e = DrawingElementStateFactory.createElement(it.next());
				if (e != null) {
					e.setComponent(view);
					view.addElement(e);
				}
			}
		}
		model.setFrameInterval(state.getFrameInterval());
		model.setViewRefreshInterval(state.getViewRefreshInterval());
		model.setInitializationScript(state.getInitScript());
		model.setTimeStep(state.getTimeStep());
		model.setLength(state.getLength());
		model.setWidth(state.getWidth());
		model.setHeight(state.getHeight());
		if (state.getHeatBath() != null) {
			model.activateHeatBath(true);
			model.getHeatBath().setExpectedTemperature(state.getHeatBath().getExpectedTemperature());
			model.getHeatBath().setInterval(state.getHeatBath().getInterval());
		}
		else {
			model.activateHeatBath(false);
		}
		if (state.getGravitationalAcceleration() > 0) {
			model.setGField(state.getGravitationalAcceleration(), state.getGFieldDirection() == null ? null : new Vector3f(state.getGFieldDirection()));
		}
		else {
			model.setGField(0, null);
		}
		if (state.getBFieldIntensity() > 0 && state.getBFieldDirection() != null) {
			model.setBField(state.getBFieldIntensity(), new Vector3f(state.getBFieldDirection()));
		}
		else {
			model.setBField(0, null);
		}
		if (state.getEFieldIntensity() > 0 && state.getEFieldDirection() != null) {
			model.setEField(state.getEFieldIntensity(), new Vector3f(state.getEFieldDirection()));
		}
		else {
			model.setEField(0, null);
		}
		view.setSimulationBox();
		addBonds();
		model.formMolecules();
		setProgressMessage("Building model ......");
		view.renderModel(true); // must render the model so that the following settings can take effect
		view.getViewer().setPerspectiveDepth(state.getPerspectiveDepth());
		view.getViewer().setZDepthMagnification(state.getZDepthMagnification());
		view.setCameraAtom(state.getCameraAtom());
		view.setShowGlassSimulationBox(state.getShowGlassSimulationBox());
		view.setMolecularStyle(state.getMoleculeStyle());
		view.setAxesShown(state.getShowAxes());
		view.getViewer().setAxisStyle(state.getAxisStyle());
		view.setShowAtomIndex(state.getShowAtomIndex());
		view.setKeShading(state.getKeShading());
		view.setShowCharge(state.getShowCharge());
		view.setShowVdwLines(state.getShowVdwLines());
		view.setFullSizeUnbondedAtoms(state.getFullSizeUnbondedAtoms());
		view.setVdwLinesRatio(state.getVdwLinesRatio());
		view.setVelocityVectorScalingFactor(state.getVelocityVectorScalingFactor());
		s = state.getVelocitySelection();
		if (s != null) {
			String[] t = s.split(REGEX_SEPARATOR);
			int n = t.length;
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					view.showVelocity(Integer.parseInt(t[i]), true);
				}
			}
		}
		s = state.getTrajectorySelection();
		if (s != null) {
			String[] t = s.split(REGEX_SEPARATOR);
			int n = t.length;
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					view.showTrajectory(Integer.parseInt(t[i]), true);
				}
			}
		}
		s = state.getTranslucentSelection();
		if (s != null) {
			String[] t = s.split(REGEX_SEPARATOR);
			int n = t.length;
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					view.getTranslucentBitSet().set(Integer.parseInt(t[i]));
				}
			}
		}
		s = state.getUnmovableSelection();
		if (s != null) {
			String[] t = s.split(REGEX_SEPARATOR);
			int n = t.length;
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					model.getAtom(Integer.parseInt(t[i])).setMovable(false);
				}
			}
		}
		s = state.getInvisibleSelection();
		if (s != null) {
			String[] t = s.split(REGEX_SEPARATOR);
			int n = t.length;
			if (n > 0) {
				for (int i = 0; i < n; i++) {
					Atom a = model.getAtom(Integer.parseInt(t[i]));
					a.setVisible(false);
					view.setVisible(a, false);
				}
			}
		}
		List<ObstacleState> list = state.getObstacles();
		if (list != null && !list.isEmpty()) {
			for (ObstacleState o : list) {
				if (o instanceof CuboidObstacleState) {
					CuboidObstacleState cos = (CuboidObstacleState) o;
					CuboidObstacle obs = new CuboidObstacle(cos);
					model.addObstacle(obs);
					view.getViewer().addCuboidObstacle(obs.getCenter().x, obs.getCenter().y, obs.getCenter().z, obs.getCorner().x, obs.getCorner().y, obs.getCorner().z);
					view.setObstacleColor(obs, new Color(cos.getColor()), cos.isTranslucent());
				}
				else if (o instanceof CylinderObstacleState) {
					CylinderObstacleState cos = (CylinderObstacleState) o;
					CylinderObstacle obs = new CylinderObstacle(cos);
					model.addObstacle(obs);
					view.getViewer().addCylinderObstacle(obs.getCenter().x, obs.getCenter().y, obs.getCenter().z, obs.getAxis(), obs.getHeight(), obs.getRadius());
					view.setObstacleColor(obs, new Color(cos.getColor()), cos.isTranslucent());
				}
			}
		}
		view.setStartingSceneWhenCameraIsOnAtom();
		model.setRotationMatrix(view.getViewer().getRotationMatrix());
		model.addCustomTasks(state.getTasks());
		model.getJob().processPendingRequests();
	}