public void reset(int index) {
    if (systems == null) {
      systems = new ParticleSystem[maxStep];
      steps = new int[maxStep];
      addVelocities = new Vector3[maxStep][particleSize];
    }
    if (systems[index] == null) { // initialize
      Geometry geometry = THREE.Geometry();
      for (int i = 0; i < particleSize; i++) {
        geometry.vertices().push(THREE.Vector3(0, 0, 0));
      }

      ParticleSystem system = THREE.ParticleSystem(geometry, baseMaterial.build());
      // system.setSortParticles(true);
      systems[index] = system;
      parent.add(system);

    } else {
      //

      ParticleSystem system = systems[index];
      ((ParticleBasicMaterial) system.getMaterial()).setSize(baseSize);

      for (int i = 0; i < particleSize; i++) {
        Vector3 vertex = system.getGeometry().vertices().get(i);
        vertex.set(0, 0, 0);
      }
      system.getGeometry().setVerticesNeedUpdate(true);
    }
    // addVelocities=new Vector3[maxStep][particleSize];
    // simple and boring
    for (int i = 0; i < particleSize; i++) {
      addVelocities[index][i] =
          THREE.Vector3(
              plusMinus(velocityRange.getX()),
              plusMinus(velocityRange.getY()),
              plusMinus(velocityRange.getZ()));
    }

    Vector3 addwind =
        THREE.Vector3(
            plusMinus(velocityRange.getX()) * 2,
            plusMinus(velocityRange.getY()) * 2,
            plusMinus(velocityRange.getZ()) * 2);
    // wind.addSelf(addwind);
    if (index % 5 == 0) {
      wind.set(
          wind.getX() / 4 * 3 + addwind.getX() / 4,
          wind.getY() / 4 * 3 + addwind.getY() / 4,
          wind.getZ() / 4 * 3 + addwind.getZ() / 4);
    }
    for (int i = 0; i < particleSize; i++) {
      winds[i] =
          THREE.Vector3(
              plusMinus(velocityRange.getX()) * 5,
              plusMinus(velocityRange.getY()) * 5,
              plusMinus(velocityRange.getZ()) * 5);
    }
  }
  @Override
  public void moveEnd() {
    // move finished
    Point last = points.get(points.size() - 1);
    target.getPosition().setX(last.getX());
    target.getPosition().setY(last.getY());

    if (listener != null) {
      listener.moveFinished();
    }
  }
  public void selectObject(
      Object3D target, int mouseX, int mouseY, int screenWidth, int screenHeight, Camera camera) {
    try {
      selectedDraggablekObject = target;
      Ray ray = projector.gwtCreateRay(mouseX, mouseY, screenWidth, screenHeight, camera);

      // ig dry every thing dont work
      // Vector3
      // rotation=GWTThreeUtils.rotationToVector3((selectedDraggablekObject.getMatrixWorld()));
      // mouseClickCatcher.getRotation().copy(rotation);

      selectedDraggablekObject.updateMatrixWorld(true);
      mouseCatchPlane
          .getPosition()
          .copy(GWTThreeUtils.toPositionVec(selectedDraggablekObject.getMatrixWorld()));
      mouseCatchPlane.updateMatrixWorld(true); // very important

      JsArray<Intersect> pintersects = ray.intersectObject(mouseCatchPlane);
      draggableOffset.copy(pintersects.get(0).getPoint()).subSelf(mouseCatchPlane.getPosition());
      /*
       * make a problem?
      if(draggableOffset.getX()<0.0001){
      	draggableOffset.setX(0);
      }
      if(draggableOffset.getY()<0.0001){
      	draggableOffset.setY(0);
      }
      if(draggableOffset.getZ()<0.0001){
      	draggableOffset.setZ(0);
      }
      */

    } catch (Exception e) {
      LogUtils.log("selectObject:" + e.getMessage());
      selectedDraggablekObject = null;
    }
    // LogUtils.log("offset:"+ThreeLog.get(draggableOffset));
  }
 @Override
 public void moveTo(double x, double y) {
   target.getPosition().setX(x);
   target.getPosition().setY(y);
 }
  /*
   *** sometime it error happend,check
   * double mouseMoved=(Math.abs(diffX)+Math.abs(diffY));
   *double length=newPos.clone().subSelf(getCurrentIkData().getTargetPos()).length();
   *  if(length<mouseMoved*5){
   */
  public Vector3 moveSelectionPosition(
      int mouseX, int mouseY, int screenWidth, int screenHeight, Camera camera) {
    if (isSelected()) {
      try {
        Ray ray = projector.gwtCreateRay(mouseX, mouseY, screenWidth, screenHeight, camera);
        JsArray<Intersect> intersects = ray.intersectObject(mouseCatchPlane);

        Vector3 newPos = intersects.get(0).getPoint().subSelf(draggableOffset);
        log = "newPos-raw:" + ThreeLog.get(newPos);
        Vector3 parentPos = THREE.Vector3();
        if (selectedDraggablekObject.getParent() != null) {
          // selectedDraggablekObject.getParent().updateMatrixWorld(true); //if call it bone moving
          // will be broken.i have no idea.
          parentPos =
              GWTThreeUtils.toPositionVec(selectedDraggablekObject.getParent().getMatrixWorld());
          // LogUtils.log("parent:"+ThreeLog.get(parentPos));
          log += "parentPos:" + ThreeLog.get(parentPos);
        }
        newPos.subSelf(parentPos);

        Matrix4 rotM = THREE.Matrix4();
        Vector3 rotation =
            GWTThreeUtils.rotationToVector3(
                (selectedDraggablekObject.getParent().getMatrixWorld()));
        // rotM.getInverse(selectedDraggablekObject.getMatrixRotationWorld());

        log += "parentRot:" + ThreeLog.get(GWTThreeUtils.radiantToDegree(rotation));
        rotM.getInverse(GWTThreeUtils.rotationToMatrix4(rotation));

        rotM.multiplyVector3(newPos);

        // Vector3 parentRotation=THREE.Vector3();

        /*
        Object3D obj=selectedDraggablekObject;
        while(obj.getParent()!=null){
        	parentPos.addSelf(obj.getParent().getPosition());
        	parentRotation.addSelf(obj.getParent().getRotation());
        	obj=obj.getParent();
        }

        LogUtils.log("parent-rot:"+ThreeLog.get(GWTThreeUtils.radiantToDegree(parentRotation)));
        */
        // Matrix4 mx=GWTThreeUtils.rotationToMatrix4(parentRotation);
        // mx.multiplyVector3(parentPos);

        /*
        log("m:"+ThreeLog.get(selectedDraggablekObject.getPosition()));
        log("m:"+ThreeLog.get(GWTThreeUtils.toPositionVec(selectedDraggablekObject.getMatrix())));
        log("mw:"+ThreeLog.get(GWTThreeUtils.toPositionVec(selectedDraggablekObject.getMatrixWorld())));
        */
        // must be same as selectedDraggablekObject
        return newPos;
      } catch (Exception e) {
        LogUtils.log("moveSelectionPosition:" + e.getMessage());
        return null;
      }
    } else {
      return null;
    }
  }
 public void copyIntersectedPosition() {
   // intersectedDraggablekObject.updateMatrixWorld(true);
   mouseCatchPlane
       .getPosition()
       .copy(GWTThreeUtils.toPositionVec(intersectedDraggablekObject.getMatrixWorld()));
 }