1
我有一個圓形的正方形網格。一切似乎都沒有問題,除了我需要將圓內的所有方塊居中放置的部分外。Three.js定位正方形在一個圓圈內
即使中心點看起來是正確的,整個圓形網格總是對齊得更靠右。
我懷疑是要去除不在圓形區域內的所有方塊或者我將網格居中的部分。
[更新]:由於張伯倫的提示,我能解決我的中心點計算兩個Galaxy
和AOS
圈。
我也更新了下面的例子。
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){
\t if(typeof options != "undefined"){
\t \t this.attr = {
\t \t \t coords: options.coords || [],
\t \t \t size : options.size,
\t \t \t margin: options.margin || 0,
\t \t \t pos: options.b_pos,
\t \t \t opacity: options.opacity || 1,
\t \t \t id: typeof(options.coords) == "undefined" ? -1 : options.coords[0]+""+options.coords[1],
\t \t };
\t \t
\t \t var cell_size = (this.attr.size + (this.attr.margin * 2));
\t \t
\t \t this.colors = {
\t \t \t selected : 0x40ff00,
\t \t \t hover: 0x00ff00,
\t \t \t path: 0x3399ff,
\t \t \t ship: {
\t \t \t \t selected: 0xff8000,
\t \t \t \t hover: 0xff5c33
\t \t \t },
\t \t \t base : parseInt(options.color)
\t \t };
\t \t
\t \t this.states = {
\t \t \t selected : false,
\t \t \t hovered: false,
\t \t \t isPath: false,
\t \t \t isPlayer: false
\t \t };
\t \t
\t \t var rectGeom = this.generate_lines();
\t \t var material = new THREE.LineBasicMaterial({ side: THREE.DoubleSide, color: options.color , transparent: true, opacity: this.attr.opacity }); ///// color not being changed!!!???/ ///
\t \t
\t \t THREE.Line.call(this, rectGeom, material);
\t \t
\t \t this.scale.set(1, 1, 1);
\t \t if(this.attr.coords.length == 0){
\t \t \t this.position.set(this.attr.pos.x , this.attr.pos.y, this.attr.pos.z);
\t \t }else{
\t \t \t 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));
\t \t }
\t \t
\t \t /*this.center_pos = { ///// pos of center point ///
\t \t \t x: (this.position.x + (cell_size/2)) + 0.5,
\t \t \t y: (this.position.z + (cell_size/2)) + 0.5
\t \t };*/
\t \t
\t \t this.rotation.set((Math.PI/2) , 0 , 0);
\t \t
\t }else{
\t \t console.error("[Square] no parameters defined. ]");
\t }
}
Square.prototype = Object.create(THREE.Line.prototype);
Square.prototype.constructor = Square;
///// State handlers ////
Square.prototype.toggleState = function(state){
\t this.states[ state ] = !this.states[ state ];
};
Square.prototype.checkState = function(state){
\t return this.states[ state ];
};
/////// Mouse events ////
Square.prototype.mouseOver = function(){
\t if(! this.checkState("hovered")){
\t \t if(! this.checkState("selected")){
\t \t \t this.toggleState("hovered");
\t \t \t this.change_color(this.colors.hover, 0.8);
\t \t }
\t }
};
Square.prototype.mouseOut = function(){
\t if(this.checkState("hovered")){
\t \t if(! this.checkState("selected")){
\t \t \t this.change_color(this.colors.base);
\t \t \t this.toggleState("hovered");
\t \t }
\t }
};
Square.prototype.select = function(){
\t if(! this.checkState("selected")){
\t \t this.toggleState("selected");
\t \t this.change_color(this.colors.selected , 1);
\t }
};
Square.prototype.unselect = function(){
\t if(this.checkState("selected")){
\t \t this.toggleState("selected");
\t \t this.change_color(this.colors.base);
\t }
};
/////// Mouse events ////
Square.prototype.change_color = function(color, opacity){
\t \t this.material.color.setHex(color);
\t \t this.material.opacity = opacity || this.attr.opacity;
};
Square.prototype.generate_lines = function(){
\t var rectShape = new THREE.Shape();
\t var half_size = (this.attr.size/2);
\t rectShape.autoClose = true;
\t rectShape.moveTo(-half_size,-half_size);
\t rectShape.lineTo(half_size,-half_size);
\t rectShape.lineTo(half_size, half_size);
\t rectShape.lineTo(-half_size, half_size);
\t return rectShape.createPointsGeometry();
};
///////// [ Square ] ////////////
/////// [ Circle ] ////////////////
var Circle = function(options){
\t if(typeof options != "undefined"){
\t \t //console.log("[Circle] Initializing");
\t \t this.attr = {
\t \t \t segments: options.segments,
\t \t \t radius : options.radius,
\t \t \t color: options.color,
\t \t \t pos: options.pos
\t \t }
\t \t
\t \t var segments = this.generate_segments();
\t \t var material = new THREE.LineBasicMaterial({ color: options.color , transparent: true, opacity: options.opacity});
\t \t THREE.Line.call(this , segments , material);
\t \t \t
\t \t this.scale.set(1, 1, 1);
\t \t this.position.set(options.pos.x, options.pos.y, options.pos.z); //// x,y,z ////
\t \t this.rotation.set((Math.PI/2) , 0 , 0);
\t }else{
\t \t console.error("[Circle] no parameters defined. ]");
\t }
};
Circle.prototype = Object.create(THREE.Line.prototype);
Circle.prototype.constructor = Circle;
Circle.prototype.generate_segments = function(){
\t var geometry = new THREE.Geometry();
\t for(var s= 0; s <= this.attr.segments; s++) {
\t \t var theta = (s/this.attr.segments) * Math.PI * 2;
\t \t geometry.vertices.push(new THREE.Vector3(Math.cos(theta) * this.attr.radius, Math.sin(theta) * this.attr.radius, 0));
\t }
\t return geometry;
};
/////// [ Circle ] ////////////////
///////////// [ Grid ] ////////////////
var Grid = function(options){
\t if(typeof options !== "undefined"){
\t \t //console.log("[Grid] Initializing");
\t \t this.cell_settings = options.cell;
\t \t this.grid_size = options.size;
\t \t
\t \t THREE.Object3D.call(this);
\t \t
\t \t this.pos = {
\t \t \t x: options.pos.x,
\t \t \t y: options.pos.y,
\t \t \t z: options.pos.z
\t \t };
\t \t
\t \t var sq_margin = (this.cell_settings.margin * 2);
\t \t this.sq_size = this.cell_settings.size + sq_margin;
\t \t this.size = {
\t \t \t w: this.grid_size[0] * this.sq_size,
\t \t \t h: this.grid_size[1] * this.sq_size
\t \t };
\t \t console.log(this.grid_size)
\t \t this.cells = new THREE.Object3D();
\t \t
\t \t this.cells_in_AOS = []; //// cells in Area of Sight ////
\t \t
\t \t this.galaxyCircle = {
\t \t \t pos: {
\t \t \t \t x: this.pos.x + (this.size.w/2),
\t \t \t \t y: this.pos.y,
\t \t \t \t z: this.pos.z + (this.size.w/2),
\t \t \t },
\t \t \t r: (this.size.w/2),
\t \t };
\t \t
\t \t var c = (this.galaxyCircle.r - options.AOS.r);
\t \t
\t \t this.AOS_circle = { //// Area of Sight ////
\t \t \t pos: {
\t \t \t \t x: this.galaxyCircle.pos.x,
\t \t \t \t y: this.galaxyCircle.pos.y,
\t \t \t \t z: this.galaxyCircle.pos.z
\t \t \t },
\t \t \t r: options.AOS.r, //// radius ////
\t \t \t color: 0x33cccc
\t \t };
\t \t
\t \t console.log(this.AOS_circle)
\t \t
\t \t this.generate();
\t }else{
\t \t console.error("[Grid] no parameters defined. ]");
\t }
};
Grid.prototype = Object.create(THREE.Object3D.prototype);
Grid.prototype.constructor = Grid;
Grid.prototype.generate = function(){
\t //////////////// Galaxy center point //////
\t this.add_center_point(this.galaxyCircle.pos, 0x033d6ff);
\t ////// AOS circle border ////
\t this.add_circle_border(this.AOS_circle);
\t ////// fill the grid with square cells ////////
\t for (var row = 0; row < this.grid_size[0]; row++){
\t \t for (var col = 0; col < this.grid_size[1]; col++){
\t \t \t this.add_cell2grid(row, col);
\t \t }
\t }
\t this.position.set(this.pos.x , this.pos.y, this.pos.z);
\t ///// center the grid /////
\t 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));
\t this.add(this.cells);
\t
\t //// map borders /////
\t this.add_circle_border({
\t \t r: (this.size.w/2),
\t \t color: 0x00ff00
\t });
\t this.add_square_border(this.size.w , 0xffff00);
\t this.add_center_point();
\t //// map borders /////
};
\t
Grid.prototype.add_center_point = function(pos, color){
\t var geometry =new THREE.BoxGeometry(0.5, 5.5, 0.5)
\t if(typeof pos === "object"){
\t \t geometry = new THREE.BoxGeometry(0.5, 10.5, 0.5);
\t }
\t var material = new THREE.MeshBasicMaterial({color: color || 0xcc33ff});
\t var cube = new THREE.Mesh(geometry, material);
\t if(typeof pos !== "object"){
\t \t cube.position.set(0,0,0);
\t }else{
\t \t cube.position.set(pos.x, pos.y, pos.z);
\t }
\t this.add(cube)
};
Grid.prototype.add_cell2grid = function(row, col){
\t var cell = new Square({
\t \t coords: [row, col],
\t \t size: this.cell_settings.size,
\t \t margin: this.cell_settings.margin,
\t \t opacity: this.cell_settings.opacity,
\t \t color: 0xFFFFFF,
\t \t b_pos: {
\t \t \t x: this.pos.x ,
\t \t \t y: this.pos.y,
\t \t \t z: this.pos.z
\t \t } //// base position ///
\t });
\t
\t
\t if(this.isColidingWith(this.galaxyCircle, cell)){
\t \t if(! this.is_in_AOS(cell)){
\t \t \t cell.visible = false;
\t \t }else{
\t \t \t this.cells_in_AOS.push(cell);
\t \t }
\t \t
\t \t if(this instanceof THREE.Object3D){
\t \t \t this.cells.add(cell);
\t \t }else{
\t \t \t console.error("[Grid] is not THREE.Object3D type. ");
\t \t }
\t }
};
Grid.prototype.is_in_AOS = function(cell){ //// Circle colision ////
\t return this.isColidingWith(this.AOS_circle, cell)
};
\t
Grid.prototype.isColidingWith = function(cA, cell){ //// Circle colision ////
\t var d_x = cA.pos.x - cell.position.x;
\t var d_y = cA.pos.z - cell.position.z;
\t var dist = Math.sqrt(d_x * d_x + d_y * d_y);
\t
\t if(dist < (cA.r - (cell.attr.size/2) )){
\t \t return true;
\t }
\t return false;
};
Grid.prototype.getCellAt = function(p){
\t this.wColiisions.postMessage([ p.x , p.y ]);
};
Grid.prototype.add_circle_border = function(options){
\t var circle = new Circle({
\t \t segments: 50,
\t \t radius: options.r,
\t \t color: options.color,
\t \t opacity: 0.5,
\t \t pos: {
\t \t \t x: this.pos.x,
\t \t \t y: 0.5,
\t \t \t z: this.pos.z
\t \t }
\t });
\t
\t this.add(circle);
};
\t
Grid.prototype.add_square_border = function(square_size, color){
\t var square = new Square({
\t \t size: square_size,
\t \t color: color,
\t \t b_pos: { //// base position ///
\t \t \t x: this.pos.x,
\t \t \t y: this.pos.y,
\t \t \t z: this.pos.z
\t \t }
\t });
\t this.add(square);
};
///////////// [ Grid ] ////////////////
////// Initializers ////////////////////////
function initEvents(){
\t //console.log("- Events");
\t window.addEventListener('resize', onWindowResize, false);
\t renderer.domElement.addEventListener('mousedown', onMouseDown, false);
\t renderer.domElement.addEventListener('mousemove', onMouseMove, false);
}
function initRenderer(){
\t //console.log("- Renderer");
\t renderer = new THREE.WebGLRenderer({antialias:true});
\t renderer.setSize(window.innerWidth, window.innerHeight);
\t document.body.appendChild(renderer.domElement);
\t renderer.setClearColor(0x264d73, 1);
}
function initScene(){
\t //console.log("- Scene")
\t scene = new THREE.Scene();
}
function initCamera(){
\t //console.log("- Camera");
\t camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 10000);
\t camera.position.set(0, 390, 0);
\t camera.lookAt(scene.position);
\t scene.add(camera);
\t
\t //controls = new THREE.OrbitControls(camera , renderer.domElement);
}
function initLights(){
\t console.log("- Lights");
\t var aLight = new THREE.AmbientLight(0xD0D0D0, 0.5);
\t scene.add(aLight);
}
function initGrid(){
\t n_grid = new Grid({
\t \t size: [20, 20],
\t \t pos: { x: 0, y: 0, z: 0 },
\t \t cell: {
\t \t \t size: 7,
\t \t \t margin: 0,
\t \t \t opacity: 0.4
\t \t },
\t \t AOS: {
\t \t \t r: 30
\t \t }
\t });
\t
\t scene.add(n_grid);
}
////// Initializers ////////////////////////
///// Mouse events ////////
function onMouseMove(e){
}
///// Mouse events ////////
///// Main /////////
function main(){
\t //console.log(" Initializing: ");
\t initRenderer(window.innerWidth, window.innerHeight);
\t initScene();
\t initCamera(window.innerWidth, window.innerHeight);
\t initLights();
\t initGrid();
\t //InitEvents();
\t animate();
}
function animate(){
\t window.requestAnimationFrame(animate);
\t render_all();
}
function render_all(){
\t //controls.update();
\t renderer.render(scene, camera);
}
main();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r77/three.js"></script>
<header>
\t <style>
\t \t body canvas{
\t \t \t width: 100%,
\t \t \t height: 100%;
\t \t \t margin:0;
\t \t \t padding:0;
\t \t }
\t </style>
</header>
<body>
</body>
它不只是這個...但也是我錯誤地計算兩者'Galaxy_circle'和'AOS_circle'的中心點。它現在工作正常。 , 感謝您的輸入。我也修正了上面的示例。 – Alexus