From 371549e1a9b9681cabe6a38b6e21511ca39a0809 Mon Sep 17 00:00:00 2001
From: luxiaotao1123 <t1341870251@163.com>
Date: 星期五, 19 四月 2024 10:31:10 +0800
Subject: [PATCH] #

---
 src/components/house.jsx |  567 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 package-lock.json        |   19 +
 package.json             |    5 
 src/pages/base.jsx       |    2 
 4 files changed, 590 insertions(+), 3 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index ac1d605..c560fa7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
       "name": "three-asrs",
       "version": "0.0.0",
       "dependencies": {
+        "@react-three/csg": "^3.2.0",
         "@react-three/drei": "9.92.0",
         "@react-three/fiber": "8.15.12",
         "@react-three/postprocessing": "2.15.11",
@@ -1061,6 +1062,15 @@
       "version": "9.6.1",
       "resolved": "https://registry.npmmirror.com/@react-spring/types/-/types-9.6.1.tgz",
       "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q=="
+    },
+    "node_modules/@react-three/csg": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/@react-three/csg/-/csg-3.2.0.tgz",
+      "integrity": "sha512-POnakTYaJqmqKsk9Q23oCL78JmaitN2+s/ciOHDK8dQu6GsSa2eMzlhR7J7kI9VdjmV/cW2cRz9XJEWNJ4XmfA==",
+      "dependencies": {
+        "three-bvh-csg": "^0.0.16",
+        "three-mesh-bvh": "^0.6.8"
+      }
     },
     "node_modules/@react-three/drei": {
       "version": "9.92.0",
@@ -5077,6 +5087,15 @@
       "resolved": "https://registry.npmmirror.com/three/-/three-0.159.0.tgz",
       "integrity": "sha512-eCmhlLGbBgucuo4VEA9IO3Qpc7dh8Bd4VKzr7WfW4+8hMcIfoAVi1ev0pJYN9PTTsCslbcKgBwr2wNZ1EvLInA=="
     },
+    "node_modules/three-bvh-csg": {
+      "version": "0.0.16",
+      "resolved": "https://registry.npmmirror.com/three-bvh-csg/-/three-bvh-csg-0.0.16.tgz",
+      "integrity": "sha512-RgC5dY0hAKdfd1bmD3o2CDfmK9GTkvsA1ECzoqTMhSkjSc2zp1z4Wpa5+emLi/EosF5P6+aK2veTxTLZA9+Mhw==",
+      "peerDependencies": {
+        "three": ">=0.151.0",
+        "three-mesh-bvh": ">=0.6.6"
+      }
+    },
     "node_modules/three-mesh-bvh": {
       "version": "0.6.8",
       "resolved": "https://registry.npmmirror.com/three-mesh-bvh/-/three-mesh-bvh-0.6.8.tgz",
diff --git a/package.json b/package.json
index 5e0efba..2c6d630 100644
--- a/package.json
+++ b/package.json
@@ -10,10 +10,11 @@
     "preview": "vite preview"
   },
   "dependencies": {
-    "@tweenjs/tween.js": "^21.0.0",
+    "@react-three/csg": "^3.2.0",
     "@react-three/drei": "9.92.0",
     "@react-three/fiber": "8.15.12",
     "@react-three/postprocessing": "2.15.11",
+    "@tweenjs/tween.js": "^21.0.0",
     "axios": "^1.6.2",
     "maath": "0.10.7",
     "react": "^18.2.0",
@@ -35,4 +36,4 @@
     "tailwindcss": "^3.4.3",
     "vite": "^5.2.0"
   }
-}
\ No newline at end of file
+}
diff --git a/src/components/house.jsx b/src/components/house.jsx
new file mode 100644
index 0000000..d41a378
--- /dev/null
+++ b/src/components/house.jsx
@@ -0,0 +1,567 @@
+import React, { useEffect, useRef } from 'react';
+import * as THREE from 'three';
+import { ThreeElements, useLoader, extend } from '@react-three/fiber';
+import { Geometry, Base, Subtraction, Addition } from '@react-three/csg';
+import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
+import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
+extend({ TextGeometry });
+
+const House = (props) => {
+  const {
+    wallThickness = 2,
+    width = 1400,
+    length = 1200,
+    height = 400,
+    aside_width = 130,
+    aside_length = 130,
+    position = new THREE.Vector3(200, 0, 0),
+    space_width = 10000,
+    space_length = 12000,
+    road_width = 600,
+    grass_width = 400,
+    cross_width = 100,
+  } = props;
+
+  const getPointToShape = (points, extra) => {
+    const shape = new THREE.Shape();
+    const obj = {};
+    extra?.forEach((item) => {
+      obj[item.i] = item.setShape;
+    });
+    points.forEach((point, index) => {
+      const { x, y } = point;
+      if (!index) {
+        shape.moveTo(x, y);
+      }
+      if (obj[index]) {
+        obj[index](shape, point);
+      } else {
+        shape.lineTo(x, y);
+      }
+    });
+    return shape;
+  };
+
+  // const texture = new THREE.TextureLoader().load('/static/wall_pic5.jpg');
+  const texture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/wall_pic5.jpg'
+      : `/degital-twin-3d/static/wall_pic5.jpg`
+  );
+  console.log('env', process.env.NODE_ENV);
+
+  texture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  texture.repeat.set(0.02, 0.02);
+
+  const roofTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/wall_pic7.png'
+      : `/degital-twin-3d/static/wall_pic7.png`
+  );
+  roofTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  roofTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  roofTexture.rotation = Math.PI / 2;
+  roofTexture.repeat.set(0.005, 0.005);
+
+  const floorTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/floor_02.png'
+      : `/degital-twin-3d/static/floor_02.png`
+  );
+  floorTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  floorTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  floorTexture.repeat.set(0.01, 0.01);
+
+  const roadTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/road2.jpg'
+      : `/degital-twin-3d/static/road2.jpg`
+  );
+  roadTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  roadTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  roadTexture.repeat.set(5, 1);
+
+  const grassTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/grass.jpg'
+      : `/degital-twin-3d/static/grass.jpg`
+  );
+  grassTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  grassTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  grassTexture.repeat.set(20, 1);
+
+  const surfaceTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/surface.jpg'
+      : `/degital-twin-3d/static/surface.jpg`
+  );
+  surfaceTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  surfaceTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  surfaceTexture.repeat.set(0.01, 0.01);
+
+  const crossTexture = new THREE.TextureLoader().load(
+    process.env.NODE_ENV == 'development'
+      ? '/static/cross.png'
+      : `/degital-twin-3d/static/cross.png`
+  );
+  crossTexture.wrapS = THREE.RepeatWrapping; // 姘村钩鏂瑰悜閲嶅
+  crossTexture.wrapT = THREE.RepeatWrapping; // 鍨傜洿鏂瑰悜閲嶅
+  crossTexture.repeat.set(70, 1);
+
+  const getBackWallShape = () => {
+    const shape = getPointToShape([
+      new THREE.Vector2(-length, -height),
+      new THREE.Vector2(-length, height),
+      new THREE.Vector2(length, height),
+      new THREE.Vector2(length, -height),
+    ]);
+    const doorHoles = new THREE.Path();
+    doorHoles.moveTo(-width / 30, -height);
+    doorHoles.lineTo(-width / 30, (-2 * height) / 5);
+    doorHoles.lineTo(width / 30, (-2 * height) / 5);
+    doorHoles.lineTo(width / 30, -height);
+    doorHoles.moveTo(-width / 30, -height);
+    shape.holes.push(doorHoles);
+    return shape;
+  };
+
+  // 绗竴灞�
+  const getBackWallTopShape = () => {
+    const shape = getPointToShape([
+      new THREE.Vector2(-length, -height / 2),
+      new THREE.Vector2(-length, -(height / 2 - 5)),
+      new THREE.Vector2(-length / 2, height / 4),
+      new THREE.Vector2(0, -(height / 2 - 5)),
+      new THREE.Vector2(length / 2, height / 4),
+      new THREE.Vector2(length, -(height / 2 - 5)), // 鍙宠竟銆倄杞存槸涓�鏍风殑锛屼笉鏂姞鍘氬害
+      new THREE.Vector2(length, -height / 2),
+      new THREE.Vector2(-length, -height / 2),
+    ]);
+    return shape;
+  };
+
+  // 绗簩灞�
+  const getRoofShape = () => {
+    const shape = getPointToShape(
+      [
+        new THREE.Vector2(-length, -(height / 2 - 5)), // 绗竴涓偣,妞渾鏇茬嚎鍔犺浇绗竴绗簩涓偣涔嬮棿
+        new THREE.Vector2(-length, -(height / 2 + 5)),
+        new THREE.Vector2(-length - wallThickness - 5, -(height / 2 + 5)),
+        // new THREE.Vector2(-length - (5 * length) / (height / 2 - 10), -(height / 2 + 10)),
+        new THREE.Vector2(-length - wallThickness - 5, -(height / 2 - 5) + 2 * wallThickness), // 鍋氭洸绾跨殑閭d竴鏉�
+        // new THREE.Vector2(-length - wallThickness, -(height / 2 - 5) + wallThickness),
+        new THREE.Vector2(-length, -(height / 2 - 5) + 2 * wallThickness),
+        new THREE.Vector2(-length, -(height / 2 - 5) + wallThickness), // 绗簩涓偣
+        new THREE.Vector2(-length / 2, height / 4 + wallThickness),
+        new THREE.Vector2(0, -(height / 2 - 5) + wallThickness), // 绗簩浣庣偣椤剁偣
+        new THREE.Vector2(length / 2, height / 4 + wallThickness),
+        new THREE.Vector2(length, -(height / 2 - 5) + wallThickness), // 绗笁浣庣偣椤剁偣
+        // 鍦ㄨ繖閲屽仛鍦嗘煴
+        new THREE.Vector2(length, -(height / 2 - 5) + 2 * wallThickness),
+        new THREE.Vector2(length + 5, -(height / 2 - 5) + 2 * wallThickness),
+        new THREE.Vector2(length + 5, -(height / 2 - 5) + 2 * wallThickness - 15), // 鍋氭洸绾跨殑閭d竴鏉�
+        new THREE.Vector2(length, -(height / 2 - 5) + 2 * wallThickness - 15),
+        // over
+        new THREE.Vector2(length, -(height / 2 - 5)), // 绗笁浣庣偣搴曠偣
+        new THREE.Vector2(length / 2, height / 4),
+        new THREE.Vector2(0, -(height / 2 - 5)), // 绗簩浣庣偣搴曠偣
+        new THREE.Vector2(-length / 2, height / 4),
+        new THREE.Vector2(-length, -(height / 2 - 5)), // 鍘熺偣
+      ],
+      [
+        {
+          i: 3,
+          setShape: (shape, point) => {
+            const { x, y } = point;
+            shape.bezierCurveTo(
+              -length - wallThickness - 5 - 2.5,
+              -(height / 2 + 5 - 14 / 4),
+              -length - wallThickness - 5 - 2.5,
+              -(height / 2 + 5 - (14 * 3) / 4),
+              x,
+              y
+            );
+          },
+        },
+        {
+          i: 12,
+          setShape: (shape, point) => {
+            const { x, y } = point;
+            shape.bezierCurveTo(
+              length + 5 + 2.5,
+              -(height / 2 - 5) + 2 * wallThickness - 14 / 4,
+              length + 5 + 2.5,
+              -(height / 2 - 5) + 2 * wallThickness - (14 * 3) / 4,
+              x,
+              y
+            );
+          },
+        },
+      ]
+    );
+    return shape;
+  };
+
+  // 绗笁灞�
+  const getTopRoofShape = () => {
+    const shape = getPointToShape([
+      new THREE.Vector2(-length, -(height / 2 - 5) + wallThickness),
+      new THREE.Vector2(-length, -(height / 2 - 5) + 2 * wallThickness),
+      new THREE.Vector2(-length / 2, height / 4 + 2 * wallThickness),
+      new THREE.Vector2(0, -(height / 2 - 5) + 2 * wallThickness),
+      new THREE.Vector2(length / 2, height / 4 + 2 * wallThickness),
+      new THREE.Vector2(length, -(height / 2 - 5) + 2 * wallThickness),
+      new THREE.Vector2(length, -(height / 2 - 5) + wallThickness),
+      new THREE.Vector2(length / 2, height / 4 + wallThickness),
+      new THREE.Vector2(0, -(height / 2 - 5) + wallThickness),
+      new THREE.Vector2(-length / 2, height / 4 + wallThickness),
+    ]);
+    return shape;
+  };
+
+  // const Text = (props: any) => {
+  //   const font = useLoader(THREE.FontLoader, '/static/STXingkai_Regular.json');
+  //   return (
+  //     <mesh
+  //       scale={[-1, 1, 1]}
+  //       position={new THREE.Vector3(width - 50, 2 * height - 150, -length - 10)}
+  //     >
+  //       <textGeometry args={[props.text, { font, size: 100, height: 10 }]} />
+  //       <meshStandardMaterial color={'#22d0d1'} />
+  //     </mesh>
+  //   );
+  // };
+
+  // 浠撳簱搴曚笅鐨勯偅涓�鍧楀湴鏉匡紝浼氭瘮浠撳簱鐣ュぇ
+  const HouseFloor = () => {
+    return (
+      <extrudeGeometry
+        args={[
+          getPointToShape([
+            // 涓嬮潰鐨勪笉瑕�
+            new THREE.Vector2(-width - aside_width, -length - aside_length),
+            new THREE.Vector2(width + aside_width, -length - aside_length),
+            new THREE.Vector2(width + aside_width, length + aside_length),
+            new THREE.Vector2(-width - aside_width, length + aside_length),
+          ]),
+          { depth: wallThickness },
+        ]}
+      />
+    );
+  };
+
+  // 鍓嶉潰鐨勮矾锛屾湁鎷涚墝鐨勯偅涓�闈�
+  const FrontRoad = () => {
+    return (
+      <extrudeGeometry
+        args={[
+          getPointToShape([
+            new THREE.Vector2(width + aside_width, -length - aside_length),
+            new THREE.Vector2(width + aside_width, -space_length),
+            new THREE.Vector2(-width - aside_width, -space_length),
+            new THREE.Vector2(-width - aside_width, -length - aside_length),
+          ]),
+          { depth: wallThickness },
+        ]}
+      />
+    );
+  };
+  //鍚庨潰鐨勮矾锛屾嫑鐗岀殑閭d竴杈圭殑鍙嶉潰
+  const BackRoad = () => {
+    return (
+      <extrudeGeometry
+        args={[
+          getPointToShape([
+            new THREE.Vector2(-width - aside_width, length + aside_length),
+            new THREE.Vector2(-width - aside_width, space_length),
+            new THREE.Vector2(width + aside_width, space_length),
+            new THREE.Vector2(width + aside_width, length + aside_length),
+          ]),
+          { depth: wallThickness },
+        ]}
+      />
+    );
+  };
+
+  // 鍙宠竟鐨勯晜绌虹殑锛屽氨鏄病鏈夊鐨勯偅涓�闈�
+  const RightRoad = () => {
+    return (
+      <extrudeGeometry
+        args={[
+          getPointToShape([
+            new THREE.Vector2(-width - aside_width, -length - aside_length),
+            new THREE.Vector2(-space_width, -length - aside_length),
+            new THREE.Vector2(-space_width, length + aside_length),
+            new THREE.Vector2(-width - aside_width, length + aside_length),
+          ]),
+          { depth: wallThickness },
+        ]}
+      />
+    );
+  };
+
+  const LeftRoad = () => {
+    return (
+      <extrudeGeometry
+        args={[
+          getPointToShape([
+            new THREE.Vector2(width + aside_width, length + aside_length),
+            new THREE.Vector2(space_width, length + aside_length),
+            new THREE.Vector2(space_width, -length - aside_length),
+            new THREE.Vector2(width + aside_width, -length - aside_length),
+          ]),
+          { depth: wallThickness },
+        ]}
+      />
+    );
+  };
+
+  const RoadMaterial = () => {
+    return <meshBasicMaterial map={roadTexture}></meshBasicMaterial>;
+  };
+
+  const GrassMaterial = () => {
+    return <meshBasicMaterial map={grassTexture}></meshBasicMaterial>;
+  };
+
+  const SurfaceMaterial = () => {
+    return <meshBasicMaterial map={surfaceTexture}></meshBasicMaterial>;
+  };
+
+  const CrossMaterial = () => {
+    return <meshBasicMaterial map={crossTexture}></meshBasicMaterial>;
+  };
+
+  const OutSideSurface = (props) => {
+    return (
+      <group rotation={[0, props.rotation, 0]}>
+        {/* 绗竴涓亾璺� */}
+        <mesh rotation={[Math.PI / 2, 0, 0]}>
+          <Geometry>
+            <Base position={[0, road_width / 2, 0]}>
+              <boxGeometry args={[props.length * 2, road_width, 10]} />
+            </Base>
+            <Addition position={[0, -road_width / 2, 0]}>
+              <boxGeometry args={[props.length * 2, road_width, 10]} />
+            </Addition>
+            <Subtraction position={[0, 0, 0]}>
+              <boxGeometry args={props.subArgs} />
+            </Subtraction>
+          </Geometry>
+          <RoadMaterial></RoadMaterial>
+        </mesh>
+        <mesh rotation={[Math.PI / 2, 0, 0]}>
+          <Geometry>
+            <Base position={[0, road_width + grass_width / 2, 0]}>
+              <boxGeometry args={[props.length * 2, grass_width, 10]} />
+            </Base>
+            <Addition position={[0, -(road_width + grass_width / 2), 0]}>
+              <boxGeometry args={[props.length * 2, grass_width, 10]} />
+            </Addition>
+            <Subtraction position={[0, 0, 0]}>
+              <boxGeometry args={props.subArgs} />
+            </Subtraction>
+          </Geometry>
+          <GrassMaterial></GrassMaterial>
+        </mesh>
+        <mesh rotation={[Math.PI / 2, 0, 0]}>
+          <Geometry>
+            <Base position={[0, road_width + grass_width + cross_width / 2, 0]}>
+              <boxGeometry args={[props.length * 2, cross_width, 10]} />
+            </Base>
+            <Addition position={[0, -(road_width + grass_width + cross_width / 2), 0]}>
+              <boxGeometry args={[props.length * 2, cross_width, 10]} />
+            </Addition>
+            <Subtraction position={[0, 0, 0]}>
+              <boxGeometry args={props.subArgs} />
+            </Subtraction>
+          </Geometry>
+          <CrossMaterial></CrossMaterial>
+        </mesh>
+      </group>
+    );
+  };
+
+  const floorColor = '#535760';
+
+  return (
+    <group position={position} receiveShadow>
+      {/* 鑽夊潽鍜屽満鏅� */}
+      <mesh rotation={[Math.PI / 2, 0, 0]}>
+        {/* <mesh> */}
+        <Geometry>
+          <Base>
+            <extrudeGeometry
+              args={[
+                getPointToShape([
+                  new THREE.Vector2(-space_width, -space_length),
+                  new THREE.Vector2(space_width, -space_length),
+                  new THREE.Vector2(space_width, space_length),
+                  new THREE.Vector2(-space_width, space_length),
+                  new THREE.Vector2(-space_width, -space_length),
+                ]),
+                { depth: wallThickness },
+              ]}
+            />
+          </Base>
+          {/* 涓棿鐨勯晜绌虹殑 */}
+          <Subtraction>
+            <HouseFloor></HouseFloor>
+          </Subtraction>
+          {/* 姝i潰鐨勯晜绌虹殑 */}
+          <Subtraction>
+            <FrontRoad></FrontRoad>
+          </Subtraction>
+          {/* 鍚庤竟鐨勯晜绌虹殑,灏辨槸姝i潰瀵归潰鐨勯偅涓�闈� */}
+          <Subtraction>
+            <BackRoad></BackRoad>
+          </Subtraction>
+          {/* 鍙抽潰鐨勯晜绌虹殑锛屾病鏈夊鐨勯偅涓�闈� */}
+          <Subtraction>
+            <RightRoad></RightRoad>
+          </Subtraction>
+          {/* 宸﹁竟鐨勯晜绌虹殑,鏈変釜灏忛棬鐨勯偅涓�杈� */}
+          <Subtraction>
+            <LeftRoad></LeftRoad>
+          </Subtraction>
+        </Geometry>
+        <meshStandardMaterial color={'white'} />
+      </mesh>
+      {/* <Text text="鍔㈠井鏈哄櫒浜�"></Text> */}
+      {/* 鍦版澘 */}
+      <mesh rotation={[Math.PI / 2, 0, 0]} receiveShadow>
+        <HouseFloor></HouseFloor>
+        <meshPhongMaterial map={floorTexture} reflectivity={1.5}></meshPhongMaterial>
+      </mesh>
+      {/* 鍚庨潰鐨勫澹�,鎷涚墝鐨勫彟涓�闈� */}
+      <mesh position={new THREE.Vector3(0, height, length - wallThickness)} receiveShadow>
+        <extrudeGeometry
+          args={[
+            getPointToShape([
+              new THREE.Vector2(-width, -height),
+              new THREE.Vector2(-width, height),
+              new THREE.Vector2(width, height),
+              new THREE.Vector2(width, -height),
+            ]),
+            { depth: wallThickness },
+          ]}
+        />
+        <meshPhongMaterial map={texture} metalness={1.0} reflectivity={1.5}></meshPhongMaterial>
+      </mesh>
+      {/* 鍚庨潰鐨勮矾 */}
+      <mesh rotation={[Math.PI / 2, 0, 0]}>
+        <BackRoad></BackRoad>
+        <SurfaceMaterial></SurfaceMaterial>
+        {/* <meshPhysicalMaterial color={floorColor}></meshPhysicalMaterial> */}
+      </mesh>
+      {/* 鍓嶉潰鐨勫澹�,鏈夋嫑鐗岀殑閭d竴杈� */}
+      <mesh position={new THREE.Vector3(0, height, -length)} receiveShadow>
+        <extrudeGeometry
+          args={[
+            getPointToShape([
+              new THREE.Vector2(-width, -height),
+              new THREE.Vector2(-width, height),
+              new THREE.Vector2(width, height),
+              new THREE.Vector2(width, -height),
+            ]),
+            { depth: wallThickness },
+          ]}
+        />
+        <meshPhongMaterial map={texture} metalness={1.0} reflectivity={1.5}></meshPhongMaterial>
+      </mesh>
+      {/* 鍓嶉潰鐨勫澹佷笅闈㈢殑璺� */}
+      <mesh rotation={[Math.PI / 2, 0, 0]}>
+        <FrontRoad></FrontRoad>
+        <SurfaceMaterial></SurfaceMaterial>
+        {/* <meshPhongMaterial
+          // color={floorColor}
+          map={roadTexture}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhongMaterial> */}
+      </mesh>
+      {/* 娌℃湁澧欑殑閭d竴闈笅闈㈢殑璺� */}
+      <mesh rotation={[Math.PI / 2, 0, 0]}>
+        <RightRoad></RightRoad>
+        <SurfaceMaterial></SurfaceMaterial>
+        {/* <meshPhysicalMaterial
+          color={floorColor}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhysicalMaterial> */}
+      </mesh>
+      {/* 宸﹁竟鐨勫澹侊紝鏈変釜鏍¢棬鐨勯偅涓�杈� */}
+      <mesh
+        position={new THREE.Vector3(width, height, 0)}
+        rotation={[0, Math.PI / 2, 0]}
+        receiveShadow
+      >
+        <extrudeGeometry args={[getBackWallShape(), { depth: wallThickness }]} />
+        <meshPhysicalMaterial map={texture} metalness={1.0} roughness={0.8}></meshPhysicalMaterial>
+      </mesh>
+      <mesh rotation={[Math.PI / 2, 0, 0]}>
+        <LeftRoad></LeftRoad>
+        <SurfaceMaterial></SurfaceMaterial>
+        {/* <meshPhysicalMaterial
+          color={floorColor}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhysicalMaterial> */}
+      </mesh>
+
+      {/* 涓や釜杞寸殑璺潰鍙傛暟 */}
+      <OutSideSurface
+        rotation={0}
+        length={space_width}
+        subArgs={[width * 2 + aside_width * 2, length * 2 + aside_length * 2, 10]}
+      ></OutSideSurface>
+      <OutSideSurface
+        rotation={Math.PI / 2}
+        length={space_length}
+        subArgs={[length * 2 + aside_length * 2, width * 2 + aside_width * 2, 10]}
+      ></OutSideSurface>
+
+      {/* 鍚庨潰澧欏鐨勯《閮� */}
+      <mesh
+        position={new THREE.Vector3(width, (5 / 2) * height, 0)}
+        rotation={[0, Math.PI / 2, 0]}
+        receiveShadow
+      >
+        <extrudeGeometry args={[getBackWallTopShape(), { depth: 2 || wallThickness }]} />
+        <meshPhysicalMaterial
+          color={'#0069c5'}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhysicalMaterial>
+      </mesh>
+      {/* 椤堕儴绗簩灞� */}
+      <mesh
+        position={new THREE.Vector3(-width - 5, (5 / 2) * height, 0)}
+        rotation={[0, Math.PI / 2, 0]}
+        receiveShadow
+      >
+        <extrudeGeometry args={[getRoofShape(), { depth: 2 * width + 10 || wallThickness }]} />
+        <meshPhysicalMaterial
+          color={'#4895f6'}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhysicalMaterial>
+      </mesh>
+      {/* 椤堕儴绗笁灞� */}
+      <mesh
+        position={new THREE.Vector3(-width, (5 / 2) * height, 0)}
+        rotation={[0, Math.PI / 2, 0]}
+        receiveShadow
+      >
+        <extrudeGeometry args={[getTopRoofShape(), { depth: 2 * width || wallThickness }]} />
+        <meshPhysicalMaterial
+          map={roofTexture}
+          metalness={1.0}
+          roughness={0.8}
+        ></meshPhysicalMaterial>
+      </mesh>
+    </group>
+  );
+};
+
+export default House;
diff --git a/src/pages/base.jsx b/src/pages/base.jsx
index 61680f6..6240fba 100644
--- a/src/pages/base.jsx
+++ b/src/pages/base.jsx
@@ -8,6 +8,7 @@
 import Buildings from '@/components/buidings'
 import TreeGroup from '../components/tree-group'
 import GridModule from '../components/grid'
+import House from '../components/house'
 
 const Base = (props) => {
     return (
@@ -22,7 +23,6 @@
                 <Camera />
                 <Sky distance={450000} sunPosition={[0, 1, 0]} inclination={0} azimuth={0.25} />
                 <Buildings />
-                <TreeGroup />
                 <TreeGroup />
                 <Box position={[0, 0, 0]} />
                 <OrbitControls />

--
Gitblit v1.9.1