В последней статье этой небольшой серии мы рассмотрели очень увлекательную часть трехмерных миров: физику. Это также возможно с Threlte. Но здесь, я должен предупредить вас. На момент написания этой статьи поддержка физики все еще находилась на очень ранней стадии. Я могу подтвердить это, основываясь на собственном опыте. Поэтому в ближайшем будущем могут быть как ошибки, так и проблемы, а также изменения в API. Это рядом, давайте начнем.
Мы по-прежнему используем сцену из двух последних статей. Теперь мы хотим поместить коробку в нашу модель. Для этого нам нужно ввести два новых термина: коллайдеры и твердое тело.
Коллайдер
Коллайдеры — это тела, с которыми компьютер рассчитывает столкновения и пересечения с другими телами. С коробкой коллайдер принимает форму коробки, что также очень интуитивно понятно. Но с более сложными формами, такими как наш остров, все выглядит иначе. Математика, стоящая за столкновением, как правило, очень сложна и требует больших вычислительных ресурсов (именно поэтому столкновение является общей областью сбоев и ошибок). Эта проблема только усугубляется с более сложными объектами. Вот почему мы хотим попытаться взять упрощенные формы. Поэтому нам нужно добавить коллайдеры вручную.
Жесткое тело
Тогда есть твердые тела. Это просто объекты, на которые могут действовать физические силы. Это напр. случай с гравитацией. Твердому телу нужен коллайдер, иначе оно не будет видно компьютеру в вопросах коллизии.
Прежде чем мы сможем все реализовать, нам нужно внести несколько изменений в наш файл App.svelte
. Помимо холста, нам нужно world
, где может происходить физика.
<Canvas size={{ width: 1280, height: 720 }}>
<World>
<Debug />
<Scene />
</World>
</Canvas>
Теперь мы действительно можем начать. Во-первых, мы добавляем коробку. Он может отправлять и получать тени. Этот блок будет расположен на высоте 8. Однако нам нужно сделать это в компоненте твердого тела. Он получает тип «динамический» и положение 8 по оси Y. Мы также добавляем автоколлайдер. У этого есть форма «cuboid
» и args={[0.5,0.5,0.5]}
Вот как все это выглядит вместе:
<RigidBody type={"dynamic"} position={{ y: 7 }}>
<Collider
shape={"cuboid"}
args={[0.5, 0.5, 0.5]}
/>
<Mesh
receiveShadow
castShadow
geometry={new BoxBufferGeometry(1, 1, 1)}
material={new MeshStandardMaterial({ side: DoubleSide, color: "white" })}
/>
</RigidBody>
Если мы сейчас запустим его в браузере, куб провалится сквозь пол. Это потому, что оставшиеся два объекта не имеют коллайдеров. Давайте изменим это сейчас.
Земля также получает автоколлайдер с типом trimesh
, но без твердого тела. С другой стороны, для острова тип автоколлайдера — convexHull
. Это тип коллайдера, который вычисляет упрощенную форму объекта.
{#if island != null}
<Group position={{ y: 0.5 }}>
<AutoColliders shape={"convexHull"} >
<Mesh
interactive
recieveShadow
castShadow
geometry={island.children[0].geometry}
material={new MeshStandardMaterial()}
/>
</AutoColliders>
</Group>
{/if}
<AutoColliders shape={"trimesh"} position={{ y: -0.5 }}>
<!-- Floor -->
<Mesh
receiveShadow
rotation={{ x: -90 * (Math.PI / 180) }}
geometry={new CircleBufferGeometry(4, 72)}
material={new MeshStandardMaterial({ side: DoubleSide, color: "white" })}
/>
</AutoColliders>
Теперь у нас все вместе. У нас есть готовая сцена объектов.
Вот код этой статьи:
https://gist.github.com/ngarske/02ba240409cf341310bea19cc3ccd4e7