Three.js在一个圆圈中定位正方形

时间:2016-06-10 09:07:37

标签: javascript html5 three.js

我有一个装满方块的圆形网格。一切似乎都没问题,除了我需要将圆圈内的所有方块都居中到中心的部分。

整个圆形网格总是更向右对齐,即使中心点看起来是正确的。

我怀疑要删除所有不在圆圈区域内的正方形或我将网格居中的部分进行计算。

[更新]:感谢Wilt的提示,我能够修正GalaxyAOS个圈子的中心点计算。

我还更新了以下示例。

Grid.prototype.generate = function(){

    this.galaxyCircle = {
        pos: {
            x: this.pos.x ,
            y: this.pos.y,
            z: this.pos.z ,
        },
        r: (this.grid_size / 2),
    };

    this.add_center_point( this.galaxyCircle.pos, 0x033d6ff );

    this.AOS_settings = { //// Area of Sight ////
        x: this.galaxyCircle.x,
        y: this.galaxyCircle.z,
        r: 64, //// radius ////
        color: 0x33cccc
    };
    this.add_circle_border( this.AOS_settings );

    ////// fill the grid with square cells ////////
    for ( var row = 0; row < this.size.rows; row++){
        for ( var col = 0; col < this.size.cols; col++){
            this.add_cell2grid( row, col );
        }
    }

    this.position.set( this.pos.x , this.pos.y, this.pos.z );
    ///// center the grid /////
    this.cells.position.set( this.pos.x - ((this.size.rows * this.sq_size) / 2), this.pos.y, this.pos.z -  ((this.size.cols * this.sq_size) / 2) );
    this.add( this.cells );

    //// map borders  /////
    this.add_circle_border({ 
        r: (this.grid_size / 2),
        color: 0x00ff00
    });
    this.add_square_border( this.grid_size , 0xffff00);
    this.add_center_point();
    //// map borders  /////
};

请参阅下面的完整示例:

var renderer, camera, scene, controls, n_grid;

///////// [ Square ] ////////////
var Square = function(options) {
  if (typeof options != "undefined") {
    this.attr = {
      coords: options.coords || [],
      size: options.size,
      margin: options.margin || 0,
      pos: options.b_pos,
      opacity: options.opacity || 1,
      id: typeof(options.coords) == "undefined" ? -1 : options.coords[0] + "" + options.coords[1],
    };

    var cell_size = (this.attr.size + (this.attr.margin * 2));

    this.colors = {
      selected: 0x40ff00,
      hover: 0x00ff00,
      path: 0x3399ff,
      ship: {
        selected: 0xff8000,
        hover: 0xff5c33
      },
      base: parseInt(options.color)
    };

    this.states = {
      selected: false,
      hovered: false,
      isPath: false,
      isPlayer: false
    };

    var rectGeom = this.generate_lines();
    var material = new THREE.LineBasicMaterial({
      side: THREE.DoubleSide,
      color: options.color,
      transparent: true,
      opacity: this.attr.opacity
    }); ///// color not being changed!!!???/   ///

    THREE.Line.call(this, rectGeom, material);

    this.scale.set(1, 1, 1);
    if (this.attr.coords.length == 0) {
      this.position.set(this.attr.pos.x, this.attr.pos.y, this.attr.pos.z);
    } else {
      this.position.set(this.attr.pos.x + (this.attr.coords[0] * cell_size) + this.attr.margin + (cell_size / 2), this.attr.pos.y, this.attr.pos.z + (this.attr.coords[1] * cell_size) + this.attr.margin + (cell_size / 2));
    }

    /*this.center_pos = { ///// pos of center point ///
    	x: ( this.position.x + (cell_size / 2) ) + 0.5, 
    	y: ( this.position.z + (cell_size / 2) ) + 0.5
    };*/

    this.rotation.set((Math.PI / 2), 0, 0);

  } else {
    console.error("[Square] no parameters defined. ]");
  }
}

Square.prototype = Object.create(THREE.Line.prototype);
Square.prototype.constructor = Square;

///// State handlers ////
Square.prototype.toggleState = function(state) {
  this.states[state] = !this.states[state];
};

Square.prototype.checkState = function(state) {
  return this.states[state];
};
/////// Mouse events ////
Square.prototype.mouseOver = function() {
  if (!this.checkState("hovered")) {
    if (!this.checkState("selected")) {
      this.toggleState("hovered");
      this.change_color(this.colors.hover, 0.8);
    }
  }
};
Square.prototype.mouseOut = function() {
  if (this.checkState("hovered")) {
    if (!this.checkState("selected")) {
      this.change_color(this.colors.base);
      this.toggleState("hovered");
    }
  }
};
Square.prototype.select = function() {
  if (!this.checkState("selected")) {
    this.toggleState("selected");
    this.change_color(this.colors.selected, 1);
  }
};
Square.prototype.unselect = function() {
  if (this.checkState("selected")) {
    this.toggleState("selected");
    this.change_color(this.colors.base);
  }
};
/////// Mouse events ////

Square.prototype.change_color = function(color, opacity) {
  this.material.color.setHex(color);
  this.material.opacity = opacity || this.attr.opacity;
};

Square.prototype.generate_lines = function() {
  var rectShape = new THREE.Shape();
  var half_size = (this.attr.size / 2);
  rectShape.autoClose = true;
  rectShape.moveTo(-half_size, -half_size);
  rectShape.lineTo(half_size, -half_size);
  rectShape.lineTo(half_size, half_size);
  rectShape.lineTo(-half_size, half_size);
  return rectShape.createPointsGeometry();
};
///////// [ Square ] ////////////

/////// [ Circle ] ////////////////
var Circle = function(options) {
  if (typeof options != "undefined") {
    //console.log("[Circle] Initializing");
    this.attr = {
      segments: options.segments,
      radius: options.radius,
      color: options.color,
      pos: options.pos
    }

    var segments = this.generate_segments();
    var material = new THREE.LineBasicMaterial({
      color: options.color,
      transparent: true,
      opacity: options.opacity
    });
    THREE.Line.call(this, segments, material);

    this.scale.set(1, 1, 1);
    this.position.set(options.pos.x, options.pos.y, options.pos.z); //// x,y,z //// 
    this.rotation.set((Math.PI / 2), 0, 0);
  } else {
    console.error("[Circle] no parameters defined. ]");
  }
};

Circle.prototype = Object.create(THREE.Line.prototype);
Circle.prototype.constructor = Circle;

Circle.prototype.generate_segments = function() {
  var geometry = new THREE.Geometry();
  for (var s = 0; s <= this.attr.segments; s++) {
    var theta = (s / this.attr.segments) * Math.PI * 2;
    geometry.vertices.push(new THREE.Vector3(Math.cos(theta) * this.attr.radius, Math.sin(theta) * this.attr.radius, 0));
  }
  return geometry;
};
/////// [ Circle ] ////////////////

///////////// [ Grid ] ////////////////
var Grid = function(options) {
  if (typeof options !== "undefined") {
    //console.log("[Grid] Initializing");
    this.cell_settings = options.cell;
    this.grid_size = options.size;

    THREE.Object3D.call(this);

    this.pos = {
      x: options.pos.x,
      y: options.pos.y,
      z: options.pos.z
    };

    var sq_margin = (this.cell_settings.margin * 2);
    this.sq_size = this.cell_settings.size + sq_margin;
    this.size = {
      w: this.grid_size[0] * this.sq_size,
      h: this.grid_size[1] * this.sq_size
    };
    console.log(this.grid_size)

    this.cells = new THREE.Object3D();

    this.cells_in_AOS = []; //// cells in Area of Sight ////

    this.galaxyCircle = {
      pos: {
        x: this.pos.x + (this.size.w / 2),
        y: this.pos.y,
        z: this.pos.z + (this.size.w / 2),
      },
      r: (this.size.w / 2),
    };

    var c = (this.galaxyCircle.r - options.AOS.r);

    this.AOS_circle = { //// Area of Sight ////
      pos: {
        x: this.galaxyCircle.pos.x,
        y: this.galaxyCircle.pos.y,
        z: this.galaxyCircle.pos.z
      },
      r: options.AOS.r, //// radius ////
      color: 0x33cccc
    };

    console.log(this.AOS_circle)

    this.generate();
  } else {
    console.error("[Grid] no parameters defined. ]");
  }
};

Grid.prototype = Object.create(THREE.Object3D.prototype);
Grid.prototype.constructor = Grid;

Grid.prototype.generate = function() {
  //////////////// Galaxy center point //////
  this.add_center_point(this.galaxyCircle.pos, 0x033d6ff);
  ////// AOS circle border ////
  this.add_circle_border(this.AOS_circle);

  ////// fill the grid with square cells ////////
  for (var row = 0; row < this.grid_size[0]; row++) {
    for (var col = 0; col < this.grid_size[1]; col++) {
      this.add_cell2grid(row, col);
    }
  }

  this.position.set(this.pos.x, this.pos.y, this.pos.z);
  ///// center the grid /////
  this.cells.position.set(this.pos.x - ((this.grid_size[0] * this.sq_size) / 2), this.pos.y, this.pos.z - ((this.grid_size[1] * this.sq_size) / 2));
  this.add(this.cells);

  //// map borders  /////
  this.add_circle_border({
    r: (this.size.w / 2),
    color: 0x00ff00
  });
  this.add_square_border(this.size.w, 0xffff00);
  this.add_center_point();
  //// map borders  /////
};

Grid.prototype.add_center_point = function(pos, color) {
  var geometry = new THREE.BoxGeometry(0.5, 5.5, 0.5)
  if (typeof pos === "object") {
    geometry = new THREE.BoxGeometry(0.5, 10.5, 0.5);
  }
  var material = new THREE.MeshBasicMaterial({
    color: color || 0xcc33ff
  });
  var cube = new THREE.Mesh(geometry, material);
  if (typeof pos !== "object") {
    cube.position.set(0, 0, 0);
  } else {
    cube.position.set(pos.x, pos.y, pos.z);
  }
  this.add(cube)
};

Grid.prototype.add_cell2grid = function(row, col) {
  var cell = new Square({
    coords: [row, col],
    size: this.cell_settings.size,
    margin: this.cell_settings.margin,
    opacity: this.cell_settings.opacity,
    color: 0xFFFFFF,
    b_pos: {
      x: this.pos.x,
      y: this.pos.y,
      z: this.pos.z
    } //// base position ///
  });

  if (this.isColidingWith(this.galaxyCircle, cell)) {
    if (!this.is_in_AOS(cell)) {
      cell.visible = false;
    } else {
      this.cells_in_AOS.push(cell);
    }

    if (this instanceof THREE.Object3D) {
      this.cells.add(cell);
    } else {
      console.error("[Grid] is not THREE.Object3D type. ");
    }
  }
};

Grid.prototype.is_in_AOS = function(cell) { //// Circle colision ////
  return this.isColidingWith(this.AOS_circle, cell)
};

Grid.prototype.isColidingWith = function(cA, cell) { //// Circle colision ////
  var d_x = cA.pos.x - cell.position.x;
  var d_y = cA.pos.z - cell.position.z;
  var dist = Math.sqrt(d_x * d_x + d_y * d_y);

  if (dist < (cA.r - (cell.attr.size / 2))) {
    return true;
  }
  return false;
};

Grid.prototype.getCellAt = function(p) {
  this.wColiisions.postMessage([p.x, p.y]);
};

Grid.prototype.add_circle_border = function(options) {
  var circle = new Circle({
    segments: 50,
    radius: options.r,
    color: options.color,
    opacity: 0.5,
    pos: {
      x: this.pos.x,
      y: 0.5,
      z: this.pos.z
    }
  });

  this.add(circle);
};

Grid.prototype.add_square_border = function(square_size, color) {
  var square = new Square({
    size: square_size,
    color: color,
    b_pos: { //// base position ///
      x: this.pos.x,
      y: this.pos.y,
      z: this.pos.z
    }
  });

  this.add(square);
};
///////////// [ Grid ] ////////////////

////// Initializers ////////////////////////
function initEvents() {
  //console.log("- Events");
  window.addEventListener('resize', onWindowResize, false);
  renderer.domElement.addEventListener('mousedown', onMouseDown, false);
  renderer.domElement.addEventListener('mousemove', onMouseMove, false);
}

function initRenderer() {
  //console.log("- Renderer");
  renderer = new THREE.WebGLRenderer({
    antialias: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  renderer.setClearColor(0x264d73, 1);
}

function initScene() {
  //console.log("- Scene")
  scene = new THREE.Scene();
}

function initCamera() {
  //console.log("- Camera");
  camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
  camera.position.set(0, 390, 0);
  camera.lookAt(scene.position);
  scene.add(camera);

  //controls = new THREE.OrbitControls( camera , renderer.domElement );
}

function initLights() {
  console.log("- Lights");
  var aLight = new THREE.AmbientLight(0xD0D0D0, 0.5);
  scene.add(aLight);
}

function initGrid() {
  n_grid = new Grid({
    size: [20, 20],
    pos: {
      x: 0,
      y: 0,
      z: 0
    },
    cell: {
      size: 7,
      margin: 0,
      opacity: 0.4
    },
    AOS: {
      r: 30
    }
  });

  scene.add(n_grid);
}
////// Initializers ////////////////////////

///// Mouse events ////////
function onMouseMove(e) {}
///// Mouse events ////////

///// Main /////////
function main() {
  //console.log(" Initializing: ");
  initRenderer(window.innerWidth, window.innerHeight);
  initScene();
  initCamera(window.innerWidth, window.innerHeight);
  initLights();
  initGrid();
  //InitEvents();
  animate();
}

function animate() {
  window.requestAnimationFrame(animate);
  render_all();
}

function render_all() {
  //controls.update();
  renderer.render(scene, camera);
}

main();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
<header>
  <style>
    body canvas {
      width: 100%, height: 100%;
      margin: 0;
      padding: 0;
    }
  </style>
</header>
<body>
</body>

1 个答案:

答案 0 :(得分:1)

你分享了很多代码,但可能是你画这样的矩形:

a = ( 0, 0);    d-----c
b = (10, 0);    |     |
c = (10,10);    |     |
d = ( 0,10);    a-----b

虽然你应该这样做:

a = (-5,-5);    d-----c
b = ( 5,-5);    |     |
c = ( 5, 5);    |     |
d = (-5, 5);    a-----b

这只是猜测...