Докуметация Cтарт Статьи Форум Лента Вход
Не официальное русскоязычное сообщество
Главная
    Документация jMonkeyEngine
        jMonkeyEngine Уроки и Документация
            Вклады
                jMonkey CSG - Конструктивная Сплошная Геометрия
                    Фигуры

Фигуры

Опубликованно: 10.06.2018, 13:53
Последняя редакция, Andry: 16.02.2019 18:40

CSGShape можно построить из любой сетки. Никаких дополнительных примитивов, кроме тех, которые предоставляются базовыми службами jMonkey, не требуется. Однако при работе со смешиванием фигур с разными текстурами мне требовался более тонкий контроль над тем, как работают примитивные фигуры. И я хотел упростить построение XML. Итак, были созданы следующие.

CSGMesh

CSGMesh определяет общий подход дизайна к CSG фигурам примитивов, а также предоставляет общие сервисы для каждой конкретной фигуры. Примитив по существу строится из начала координат (0,0,0) с некоторым отклонением в зависимости от размера в сторону x, y и z. Фигура будет иметь грани, масштабирование текстур на которых можно индивидуально контролировать, и применять ваши пользовательские Материалы.

В частности, CSGMesh позволяет:

  • Примените различное масштабирование текстур к разным граням
  • Применяйте различные Материалы к разным граням
  • Генерировать различные уровней детализации на основе Коэффициента LOD
  • Производить TangentBinormal с информацией о освещении для Сетки после ее создания
  • Общая точка входа updateGeometry(), которая перестраивает фигуру, используя все текущие настройки

Точки java входа для сервисов выше:

CSGMesh  Описание
setFaceProperties( List pPropertyList )  Сохраните список свойств граней pPropertyList и примените их к соответствующим граням при запуске updateGeometry(). Каждый экземпляр CSGFaceProperties ссылается на выбранную грань (или грани) через битовую маску и имеет необязательное значение масштабирования текстуры (Vector2f) и/или настроенный Материал для применения к этой грани.
setLODFactors( float[ ] pLODFactors )  Сохраните набор процентных коэффициентов нагрузки, которые создают несколько VertexBuffer-ов при срабатывании updateGeometry(). Каждая конкретная фигура интерпретирует процент по-своему, решая, как наилучшим образом уменьшить количество индексов на нужную сумму. Но конечным результатом является вызов базового Mesh.setLodLevels(VertexBuffer[] pLevelsOfDetail).
setGenerateTangentBinormal( boolean pFlag )  Сохраните флаг, в true, что бы вызывалось TangentBinormalGenerator.generate(thisMesh) при вызове updateGeometry().
updateGeometry()  Создайте базовую Сетку (вершины, нормали, текстуры, индексы) из активных настроек конфигурации, а затем примените масштаб текстурирования и генерацию касательной бинормали по мере необходимости. Никакая реальная Сетка не доступна для этой фигур до тех пор, пока не будет вызвана функция updateGeometry(). Последним шагом обработки Savable.read(…) (…) для каждой CSG фигуры является вызов самой функции updateGeometry().

Грани выбираются целочисленной битовой маской, где:

0x01 - FRONT (Спереди) 
0x02 - BACK (Сзади) 
0x04 - LEFT (Слева) 
0x08 - RIGHT (Справа)
0x10 - TOP (Сверху)
0x20 - BOTTOM (Снизу)
0x40 - SIDES (Сторона)
0x80 - SURFACE (Поверхность)
и так же, можно логически комбинируя, применять этими же значениями те же свойства, к нескольким граням.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGSomeShape' 
            generateTangentBinormal='true' >
        <faceProperties>
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='FRONT_BACK' scaleX='1' scaleY='1.0'
                materialName='Textures/Rock/Rock1Rpt.xml' />
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='LEFT_RIGHT' scaleX='10' scaleY='1.0'/>
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='TOP_BOTTOM' scaleX='1' scaleY='10.0'/>
        </faceProperties>
        <lodFactors data='0.25 0.50'/>
    </mesh>

CSGBox(Куб)

CSGBox создает базовую кирпичную фигуру с заданным x, y и z размером. Ключевое различие между CSGBox и стандартным jme3 Box(Куб) — это реализация граней (FRONT/BACK/TOP/BOTTOM/LEFT/RIGHT) и возможность применять различные свойства к разным сторонам.

Точки java входа для настройки конфигурации включают все, из CSGMesh и

CSGBox  Описание
setXExtent( float pExtent )
setYExtent( float pExtent )
setZExtent( float pExtent ) 
которые устанавливают размер куба в заданном направлении.

Обратите внимание, что размер применяется в плюс/минус от начала координат. То есть, конечная ширина/высота/глубина в два раза превышает значение размера.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGBox' 
            xExtent='5.0' yExtent='1.0' zExtent='1.0' >
        <faceProperties>
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='LEFT_RIGHT' scaleX='5.0' scaleY='1.0'/>
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='TOP_BOTTOM' scaleX='1' scaleY='5.0'/>
        </faceProperties>
    </mesh>

CSGBoxes

Куб что сверху, не имеет текстурного масштабирования, поэтому текстура растягивается чтобы покрыть растянутый размер. Куб что снизу имеет текстурное масштабирование, применяемое к четырем граням, рассчитанное для размера.

CSGAxialBox

CSGAxialBox — это второстепенный вариант CSGBox, где текстура применяется к граням LEFT/RIGHT/TOP/BOTTOM так же, как текстура применяется к круглым сторонам цилиндра. Это помогает при выравнивании текстур из смешанных примитивов.

Реализация XML импорта осуществляется в CSGAxialBox также как CSGBox. Просто замените одно на другое.

CSGAxial / CSGRadial

CSGAxial является расширением CSGMesh, которое реализует общий подход к проектированию примитивов CSG фигур, которые построены из серии срезов вдоль оси z. CSGRadial расширяет эту идею с каждого среза, определяемого вершинами, радиально распределенными вокруг его центра.
CSGRadialCapped — радиальные фигуры с плоскими гранями концов, такие как цилиндр или труба. Стандартные лицевые стороны FRONT/BACK/SIDES применяются ко всем закрытым радиальным элементам. Режим текстуры управляет тем, как текстура применяется к грани, где:

CAN  Представьте, что фигура наклона, чтобы сидеть на задней грани (like a soup can). Затем X перемещается по окружности, а Y увеличивается вверх на сколько можно.
ROLLER  Представьте, что фигура повернута так, что задняя сторона находится с лева, а передняя сторона с права. Тогда X линейно возрастает слева направо, а Y увеличивается вдоль окружности по мере продвижения вверх.

Точки java входа настраивающие радиальные фигуры:

CSGAxial/CSGRadial  Описание
setZExtent( float pZExtent )  Задать размер фигуры вдоль оси z
setAxisSamples( int pSampleCount )  Задать количество срезов для генерации вдоль оси z
setRadialSamples( int pSampleCount )  Задайте количество вершин для генерации вдоль внешней стороны каждого среза. Число три создает треугольную фигуру, число в четыре дает квадратную фигуру, более высокие числа производят круглые фигуры.
setFirstRadial( float pFirstRadial )  Задать угол (в радианах) первого радиального по оси x. Для круговых срезов это имеет минимальный эффект. Но если количество радиальных выборок невелико (3,4, …), то это определяет, где расположена первая вершина, в результате чего получается квадрат по сравнению с ромбом.
setRadius( float pRadius )  Радиус применяется к срезу, который определяет расстояние от вершины до центра.
setSliceScale( Vector2f pScaling )  x/y масштабирование к каждому отдельному срезу.
(общее масштабирование Геометрии, которая содержит эту фигуру, создает эллиптическую, а не круговую радиальность. Однако затем текстура, применяемая к каждому срезу, также масштабируется. Применение масштабирования к отдельному срезу сохраняет исходное отображение текстуры.)
setSliceRotation( float pTotalRotation )  Общая величина углового поворота (в радианах) от задней поверхности до передней поверхности с соответствующим фракционным количеством, применяемым к каждому срезу.
setClosed( boolean pIsClosed )  Если true, то концы фигуры закрыты. Если false, построена полая фигура без концов.
setInverted( boolean pIsInverted )  Если true, то фигура строится с её поверхностями, обращенными внутрь. Если false, то поверхности обращены наружу.

Точки java входа, настраивающие ограниченные радиальные фигуры:

 
setRadiusBack( float pRadius )  Радиус, применяемый к срезу задней поверхности, который определяет расстояние от вершины до центра. Когда радиус и задний радиус различаются, он будет скорректирован на каждом срезе, чтобы обеспечить плавное переход.
setTextureMode( CSGRadialCapped.TextureMode pTextureMode )  Задать, как текстура применяется к граням.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGSomeRadial' 
            zExtent='3.0' axisSamples='32' radialSamples='32' firstRadial='PI/4' 
            radius='1.1' scaleSliceX='2.0' scaleSliceY='2.0' twist='2PI' 
            radius2='1.7' textureMode='CAN' >
        ... другие реализации из CSGMesh ...
    </mesh>

CSGCylinder(Цилиндр)

CSGCylinder создает базовую фигуру цилиндра, основываясь полностью на настройках CSGRadialCapped. Цилиндр может быть открыт или закрыт, а грани обоих концов могут иметь разные радиусы.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGCylinder' 
            zExtent='3.0' radius='1.1' />

CSGCylinders

Цилиндр слева применяет текстуру вокруг окружности, как CAN. В цилиндре справа применяется текстура, как ROLLER. Оба имеют текстуру «сторон», отмасштабированную, так чтобы было близко к масштабу на гранях концов.

CSGSphere(Сфера)

CSGSphere создает базовую фигуру сферу, основываясь на настройках CSGRadial. Сфера имеет только одну грань SURFACE (с интегральными концами) и применяется только один основной радиус. Сфера, отмеченная не закрытой, исключает срезы северного и южного полюсов, которые сходятся к одной точке, от чего крошечные отверстия появляются на концах.
Поскольку синус/косинус изменяются быстрее вблизи крайних углов, сфера может быть сгенерирован либо четными срезами (одинаковое расстояние на каждом шаге по оси z), либо для генерации большего количества срезов с меньшим шагом по оси z вблизи прямоугольных точек.
Режим текстуры управляет тем, как текстура применяется к полярным областям (последний участок, сгенерированный из общей центральной точки к срезу), где:

ZAXIS  Оберните текстуру радиально и вдоль оси z
PROJECTED  Оберните текстуру радиально, но сферически проецируйте вдоль оси z
POLAR  Примените текстуру к каждому полюсу. Устраняет полярное искажение, но зеркалит текстуру на экваторе

Точки java входа, настраивающие сферу:

setEvenSlices( boolean pFlag )  Если true, сгенерирует все шаги оси z равными. Если false, создаёт больше срезов рядом с крайними прямоугольными углами.
setTextureMode( CSGSphere.TextureMode pTextureMode )  задать режим текстуры применительно к полярным концам.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGSphere' 
            zExtent='3.0' radius='1.1' useEvenSlices='false' textureMode='ZAXIS' />

CSGSpheres

Сфера слева использует режим текстуры ZAXIS. Сфера в центре использует режим текстуры PROJECTED. Сфера справа использует режим текстуры POLAR.

CSGPipe(Труба)

CSGPipe создает цилиндроподобную фигуру, у которой ось z следует заданному сплайну(кривой), а не прямой. Все CSGRadialCapped настройки применимы. (Pipe)Труба может быть открыта или закрыта, а оба конца могут иметь разные радиусы. Ключевым параметром является сплайн, используемый для генерации центральных точек на оси z для каждого среза. Ожидается, что срез будет перпендикулярен его центральной точке на каждом интервале. Поскольку одна точка не имеет перпендикуляра, мы строим перпендикуляр к прямой между текущей центральной точкой и следующей. Это означает, что срезы граней концов могут быть очень чувствительны к структуре сплайна. Для обработки некоторых нестандартных случаев поддерживаются настраиваемые параметры PipeEnd:

STANDARD  Конечный срез генерируется «нормально», перпендикулярно последней точке кривой
PERPENDICULAR  Конечный срез генерируется перпендикулярно осям x/y/z
PERPENDICULAR45  Конечный срез генерируется перпендикулярно/45 градусов к осям x/y/z
CROPPED  Конечные точки сплайна НЕ производят срез, они влияют только на последний обычный срез

Еще одна странность построения срезов вдоль сплайна, а не вдоль прямой, состоит в том, что из-за изгибов сплайна срезы могут сталкиваться друг с другом. Это приводит к очень мятой фигуре, если сплайн слишком сильно изгибается. Предоставляется возможность «сгладить» конечный результат. Он делает все возможное, чтобы устранить наложения срезов друг на друга.

Точки java входа, настраивающие трубу:

setSlicePath( Spline pCurve )  Предоставить jme3 Сплайн, который определяет положение каждого среза центральной точки.
setSmoothSurface( boolean pFlag )  Если true, отсканировать каждый срез, на наличие столкновений(наложения) с соседними. Если происходит наложение, примите меры, чтобы отрегулировать срез, и устранить эту проблему.
setPipeEnds( CSGPipe.PipeEnds pEnds )  Управление построением концов трубы.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGPipe' 
            pipeEnds='STANDARD' smoothSurface='false >
    	<slicePath class='net.wcomohundro.jme3.csg.shape.CSGSplineGenerator'  arc='PI'/>
    </mesh;>

CSGPipes

Слева направо: сплайн, тор, спираль.

CSGSplineGenerator (вспомогательный класс)

CSGSplineGenerator не является фигурой. Скорее, это вспомогательный класс, который может помочь в создании сплайна, используемого CSGPipe. Сплайн может быть реализован:

  • Внешне реализованным экземпляром сплайна
  • Заданным набором точек
  • Набором контрольных точек, интерпретируемых на основе выбранного SplineType
  • Набором сгенерированных точек относительно дуги окружности с дополнительной регулировкой высоты, которая создает спираль, а не тор.

Точки java входа, настраивающие трубу:

setSpline( Spline pSpline )  Использовать внешне сделанный сплайн, как указано.
setPointList( List pPointList )  Использовать заданный набор точек, а не сплайн.
setArcRadius( float pRadius )  Сгенерировать дугу заданного радиуса.
setArcRadians( float pRadians )  Сгенерировать дугу с данным углом (в радианах). Значение 2Pi будет генерировать полноценный тор. Значение, большее 2Pi, имеет смысл только для спирали.
setArcFirstRadial( float pRadial )  Сгенерировать дугу, начинающуюся с точки с заданным углом (в радианах).
setHelixHeight( float pHeight )  Сгенерировать спираль, которая охватывает заданную высоту.

Реализация XML импорта выглядит примерно так:

    <slicePath class='net.wcomohundro.jme3.csg.shape.CSGSplineGenerator' 
    		radius='1.5' arc='PI' firstRadial='PI/4' helix='1.75' />
    		
    <slicePath class='net.wcomohundro.jme3.csg.shape.CSGSplineGenerator'  
    		type='Bezier' curveTension='0.5f' cycle='false'>
        <controlPoints>
            <com.jme3.math.Vector3f x='0.0' y='0.0' z='1.5'/>
            <com.jme3.math.Vector3f x='0.45' y='0.0' z='0.75'/>
            <com.jme3.math.Vector3f x='0.45' y='0.0' z='-0.75'/>
            <com.jme3.math.Vector3f x='00' y='0.0' z='-1.5'/>
        </controlPoints>
    </slicePath>

CSGTwisted

Пример тора, где каждый срез масштабируется по x/y для создания эллипса, срезы скручивается поворачивая назад, а радиус начала отличается от радиуса конца.

CSGSurface(Поверхность)

CSGSurface — это не объёмная, а скорее 2D поверхность, используемая в качестве пола. Она похожа на механизм jme3 Terrain, но не имеет поддержки LOD Terrain. Она работает, создавая Сетку(Mesh) из стандартных jme3 данных карты высот HeightMap, с размером в X/Z, и с высотой в Y.

Точки java входа, настраивающие поверхность:

setExtent( int pSizeOfSquareArea )  Ширина и глубина области (требуется значение 2*N + 1)
setHeightMap( float[] pHeightMap )  Высота каждой данной точки.
setScale( Vector3f pScale )  Масштаб, применяемый ко всем данным точкам.

Реализация XML импорта выглядит примерно так:

    <mesh class='net.wcomohundro.jme3.csg.shape.CSGSurface' extent='129'>
        <faceProperties>
            <net.wcomohundro.jme3.csg.shape.CSGFaceProperties 
					face='SURFACE' scaleX='1032' scaleY='1032'/>
        </faceProperties>
        <heightMap class='net.wcomohundro.jme3.csg.shape.CSGHeightMapGenerator'
            			type='HILL' size='129' scale='0.025' seed='12345' />
    </mesh>

CSGHeightMapGenerator (вспомогательный класс)

CSGHeightMapGenerator — это не фигура. Скорее, это вспомогательный класс, который может помочь в построении данных карты высот HeightMap, используемых CSGSurface. Он включает поддержку базовых классов jme3 в пределах com.jme3.terrain.heightmap. В частности, типы:

DISPLACEMENT  использование MidpointDisplacementHeightMap
FAULT  использование FaultHeightMap
FLUID  использование FluidSimHeightMap
HILL  использование HillHeightMap
PARTICLE  использование ParticleDepositionHeightMap

Реализация XML импорта выглядит примерно так:

    <heightMap class='net.wcomohundro.jme3.csg.shape.CSGSplineGenerator'  
    		type='HILL' size='257' iterations='100' seed='0'
    	... введите конкретные параметры здесь, @see сам код ...
    />

CSGFaceProperties (вспомогательный класс)

CSGFaceProperties — это не фигура. Скорее, это вспомогательный класс, который может помочь в применении пользовательских материалов и масштабирования текстур для разных граней в CSGMesh. В большинстве случаев CSGMesh играет роль стандартной jme3 Сетки(Mesh). И хотя Сетка(Mesh) понимает свое сопоставление Текстурных Координат, она не знает о Материале, который применяется. Материал определяется и применяется геометрией, содержащей Сетку(Mesh).

Но в рамках CSG становится очень удобным, если базовый CSGMesh может связать разные материалы с разными гранями. Например, скажем, вы собираетесь создать Комнату, вычитая меньший внутренний Куб из немного большего внешнего Куба. Если вы хотите, чтобы к полу потолку и стенами применялись разные материалы, вы должны использовать какое-либо условие о сопоставлении Материалов или использовать несколько примитивов для представления различных компонентов.

Поскольку CSGMesh понимает пользовательские Материалы, сопоставленные с его различными гранями, и поскольку CSGGeonode понимает работу с несколькими Материалами, становится довольно легко задать конкретный материал для конкретной грани непосредственно на CSGBox, и позвольте стандартной обработке CSG применить соответствующий материал к соответствующим поверхностям.

Обратите внимание, что для ядра jme3 обработка CSGBox это обработка просто Сетки(Mesh). В ядре при обработки нет распознавания, что пользовательские Материалы были заданы на уровне Сетки(Mesh). Но обработка CSGShape понимает несколько Материалов, применяемых к примитивам, и особенно это касается CSGMesh. Поэтому, если вы добавляете CSGBox с пользовательскими Материалами и с узлом jme3 Геометрии, эти Материалы игнорируются. Но если вы добавите тот же самый CSGBox через CSGShape, добавленный в CSGGeonode, то пользовательские материалы будут использованы.

CSGFaceProperties также используется для управления масштабированием и положением текстуры, которая применяется к грани. Это решает проблему куба, при растягивании по z, но не по x и y. В этом случае передняя и задняя грани должны сохранять единичное масштабирование текстуры. Но левая/правая/верхняя/нижняя грани должны быть масштабированы соответствующим образом, чтобы предотвратить растяжение текстуры.

Помимо масштабирования текстуры, вы также можете управлять тем откуда она будет начинаться и её охватом. Обычно текстура начинается из 0.0 и идёт до 1.0 на грани. Масштабирование может рассчитывается и для грани другого размера. Но при смешивании примитивов вместе вы можете захотеть, чтобы текстура подкомпонента совпадала с текстурой более крупного компонента. Подумайте о создании dice, с pips. Вы можете создавать такие элементы например, вычитая меньший цилиндр несколько раз из большего куба. Но если вы хотите, чтобы рисунок текстуры была непрерывным по pips, то вам необходимо задавать соответствующее начало текстуры для каждого цилиндра.

Помимо текстуры, вы можете управлять физическими свойствами грани. В примере создания комнаты вам так же могут понадобиться упругие стены, и инертный пол. Это можно сделать, задав разные физические свойства для разных граней.

В любом случае CSGFaceProperties применяется к грани или граням, определяемых битовой маской всех задействованных граней.

Реализация XML импорта выглядит примерно так:

    <faceProperties>
	    <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='FRONT_BACK' scaleX='1' scaleY='1.5'
		        materialName='Textures/Rock/Rock1Rpt.xml'/>
        <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='LEFT_RIGHT' scaleX='2' scaleY='1.5'
		        materialName='Textures/BrickWall/BrickWallRpt.xml'/>
        <net.wcomohundro.jme3.csg.shape.CSGFaceProperties face='TOP_BOTTOM' scaleX='1' scaleY='2.0'/>
    </faceProperties>

Смотрите так же:


Переведено для jmonkeyengine.ru, оригинал
Автор перевода: Andry

Добавить комментарий

jMonkeyEngine.ru © 2017. Все права сохранены.