forked from kscience/visionforge
Replace light model for 3ds
This commit is contained in:
parent
db5064f6ed
commit
f828f86e29
@ -4,6 +4,8 @@
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Naming of Canvas3D options
|
||||||
|
- Lights are added to the scene instead of 3D options
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ val fxVersion by extra("11")
|
|||||||
|
|
||||||
allprojects{
|
allprojects{
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.2.0"
|
version = "0.2.1-dev-1"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.css.*
|
import kotlinx.css.*
|
||||||
import react.child
|
|
||||||
import react.dom.render
|
import react.dom.render
|
||||||
import ringui.SmartTabs
|
import ringui.SmartTabs
|
||||||
import ringui.Tab
|
import ringui.Tab
|
||||||
@ -8,6 +7,7 @@ import space.kscience.dataforge.context.Context
|
|||||||
import space.kscience.plotly.models.Trace
|
import space.kscience.plotly.models.Trace
|
||||||
import space.kscience.plotly.scatter
|
import space.kscience.plotly.scatter
|
||||||
import space.kscience.visionforge.Application
|
import space.kscience.visionforge.Application
|
||||||
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.VisionClient
|
import space.kscience.visionforge.VisionClient
|
||||||
import space.kscience.visionforge.plotly.PlotlyPlugin
|
import space.kscience.visionforge.plotly.PlotlyPlugin
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
@ -73,6 +73,9 @@ private class JsPlaygroundApp : Application {
|
|||||||
attrs {
|
attrs {
|
||||||
context = playgroundContext
|
context = playgroundContext
|
||||||
solid {
|
solid {
|
||||||
|
ambientLight {
|
||||||
|
color(Colors.white)
|
||||||
|
}
|
||||||
repeat(100) {
|
repeat(100) {
|
||||||
sphere(5, name = "sphere[$it]") {
|
sphere(5, name = "sphere[$it]") {
|
||||||
x = random.nextDouble(-300.0, 300.0)
|
x = random.nextDouble(-300.0, 300.0)
|
||||||
|
@ -7,6 +7,7 @@ import react.fc
|
|||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.plotly.layout
|
import space.kscience.plotly.layout
|
||||||
import space.kscience.plotly.models.Trace
|
import space.kscience.plotly.models.Trace
|
||||||
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.markup.VisionOfMarkup
|
import space.kscience.visionforge.markup.VisionOfMarkup
|
||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.react.flexRow
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
@ -41,6 +42,11 @@ val GravityDemo = fc<DemoProps> { props ->
|
|||||||
attrs {
|
attrs {
|
||||||
context = props.context
|
context = props.context
|
||||||
solid {
|
solid {
|
||||||
|
pointLight(200, 200, 200, name = "light"){
|
||||||
|
color(Colors.white)
|
||||||
|
}
|
||||||
|
ambientLight()
|
||||||
|
|
||||||
sphere(5.0, "ball") {
|
sphere(5.0, "ball") {
|
||||||
detail = 16
|
detail = 16
|
||||||
color("red")
|
color("red")
|
||||||
|
@ -17,12 +17,13 @@ import react.fc
|
|||||||
import react.useMemo
|
import react.useMemo
|
||||||
import react.useState
|
import react.useState
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
|
import space.kscience.dataforge.meta.invoke
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.visionforge.react.flexColumn
|
import space.kscience.visionforge.react.flexColumn
|
||||||
import space.kscience.visionforge.react.flexRow
|
import space.kscience.visionforge.react.flexRow
|
||||||
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
import space.kscience.visionforge.ring.ThreeCanvasWithControls
|
||||||
import space.kscience.visionforge.ring.tab
|
import space.kscience.visionforge.ring.tab
|
||||||
import space.kscience.visionforge.solid.specifications.Camera
|
import space.kscience.visionforge.solid.ambientLight
|
||||||
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
import space.kscience.visionforge.solid.specifications.Canvas3DOptions
|
||||||
import space.kscience.visionforge.solid.three.edges
|
import space.kscience.visionforge.solid.three.edges
|
||||||
import styled.css
|
import styled.css
|
||||||
@ -42,17 +43,19 @@ val MMApp = fc<MMAppProps>("Muon monitor") { props ->
|
|||||||
|
|
||||||
val mmOptions = useMemo {
|
val mmOptions = useMemo {
|
||||||
Canvas3DOptions {
|
Canvas3DOptions {
|
||||||
camera = Camera {
|
camera {
|
||||||
distance = 2100.0
|
distance = 2100.0
|
||||||
latitude = PI / 6
|
latitude = PI / 6
|
||||||
azimuth = PI + PI / 6
|
azimuth = PI + PI / 6
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val root = useMemo(props.model) {
|
val root = useMemo(props.model) {
|
||||||
props.model.root.apply {
|
props.model.root.apply {
|
||||||
edges()
|
edges()
|
||||||
|
ambientLight()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,11 @@ fun VisionLayout<Solid>.demo(name: String, title: String = name, block: SolidGro
|
|||||||
val meta = Meta {
|
val meta = Meta {
|
||||||
"title" put title
|
"title" put title
|
||||||
}
|
}
|
||||||
val vision = SolidGroup(block)
|
val vision = SolidGroup(block).apply {
|
||||||
|
ambientLight{
|
||||||
|
color(Colors.white)
|
||||||
|
}
|
||||||
|
}
|
||||||
render(Name.parse(name), vision, meta)
|
render(Name.parse(name), vision, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +43,7 @@ val canvasOptions = Canvas3DOptions {
|
|||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
fun VisionLayout<Solid>.showcase() {
|
fun VisionLayout<Solid>.showcase() {
|
||||||
demo("shapes", "Basic shapes") {
|
demo("shapes", "Basic shapes") {
|
||||||
|
ambientLight()
|
||||||
box(100.0, 100.0, 100.0) {
|
box(100.0, 100.0, 100.0) {
|
||||||
z = -110.0
|
z = -110.0
|
||||||
color("teal")
|
color("teal")
|
||||||
|
@ -59,7 +59,7 @@ box(10, 10, 10, name = "small box"){
|
|||||||
rotation = Point3D(0, 0, 0)
|
rotation = Point3D(0, 0, 0)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/small-box.png)
|
![](../images/small-box.png)
|
||||||
|
|
||||||
The `big box` will have properties with custom values.
|
The `big box` will have properties with custom values.
|
||||||
```kotlin
|
```kotlin
|
||||||
@ -72,7 +72,7 @@ box(40, 40, 40, name = "big box"){
|
|||||||
rotation = Point3D(60, 80, 0)
|
rotation = Point3D(60, 80, 0)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/big-rotated-box.png)
|
![](../images/big-rotated-box.png)
|
||||||
If we compare these boxes, we will see all differences.
|
If we compare these boxes, we will see all differences.
|
||||||
|
|
||||||
Here is the function `main` with both boxes.
|
Here is the function `main` with both boxes.
|
||||||
@ -111,8 +111,8 @@ fun main(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/two-boxes-1.png)
|
![](../images/two-boxes-1.png)
|
||||||
![](../docs/images/two-boxes-2.png)
|
![](../images/two-boxes-2.png)
|
||||||
|
|
||||||
***There is plenty of other properties, especially those, which you can create by yourself. Here we mention just a small part.***
|
***There is plenty of other properties, especially those, which you can create by yourself. Here we mention just a small part.***
|
||||||
|
|
||||||
@ -142,8 +142,8 @@ polyline(Point3D(30, 20, 10), Point3D(30, -100, 30), Point3D(30, -100, 30), Poin
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
![](../docs/images/polyline-points.png)
|
![](../images/polyline-points.png)
|
||||||
![](../docs/images/polyline-points-2.png)
|
![](../images/polyline-points-2.png)
|
||||||
|
|
||||||
### 2) Box
|
### 2) Box
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ Let's create just usual `box` with equal ribs.
|
|||||||
color("pink")
|
color("pink")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/box.png)
|
![](../images/box.png)
|
||||||
|
|
||||||
Now, let's make `box` with bigger `y` value.
|
Now, let's make `box` with bigger `y` value.
|
||||||
```kotlin
|
```kotlin
|
||||||
@ -175,7 +175,7 @@ Now, let's make `box` with bigger `y` value.
|
|||||||
```
|
```
|
||||||
As you can see, only the rib of `y-axis` differs from other ribs.
|
As you can see, only the rib of `y-axis` differs from other ribs.
|
||||||
|
|
||||||
![](../docs/images/high-box.png)
|
![](../images/high-box.png)
|
||||||
|
|
||||||
For a final trial, let's create a `box` with a bigger `x` value.
|
For a final trial, let's create a `box` with a bigger `x` value.
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ For a final trial, let's create a `box` with a bigger `x` value.
|
|||||||
```
|
```
|
||||||
Predictably, only the `x-axis` rib is bigger than other ribs.
|
Predictably, only the `x-axis` rib is bigger than other ribs.
|
||||||
|
|
||||||
![](../docs/images/wide-box.png)
|
![](../images/wide-box.png)
|
||||||
|
|
||||||
### 3) Sphere
|
### 3) Sphere
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ As for `radius`, it has `Float` type, and, as you can guess, it sets the radius
|
|||||||
color("blue")
|
color("blue")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/sphere.png)
|
![](../images/sphere.png)
|
||||||
|
|
||||||
### 4) Hexagon
|
### 4) Hexagon
|
||||||
|
|
||||||
@ -220,7 +220,7 @@ It is solid which has six edges. It is set by eight values: `node1`,..., `node8`
|
|||||||
5) Edge with vertices `node1`, `node5`, `node8`, `node4`
|
5) Edge with vertices `node1`, `node5`, `node8`, `node4`
|
||||||
6) Edge with vertices `node8`, `node5`, `node6`, `node7`
|
6) Edge with vertices `node8`, `node5`, `node6`, `node7`
|
||||||
|
|
||||||
![](../docs/images/scheme.png)
|
![](../images/scheme.png)
|
||||||
|
|
||||||
As the hexagon takes in specific points, we understand that this solid cannot be moved, it is fixed in space, and it can't make pivots.
|
As the hexagon takes in specific points, we understand that this solid cannot be moved, it is fixed in space, and it can't make pivots.
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ Let's make classic parallelepiped.
|
|||||||
color("green")
|
color("green")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/classic-hexagon.png)
|
![](../images/classic-hexagon.png)
|
||||||
|
|
||||||
Now, let's make a custom hexagon.
|
Now, let's make a custom hexagon.
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ hexagon(
|
|||||||
color("brown")
|
color("brown")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/custom-hexagon.png)
|
![](../images/custom-hexagon.png)
|
||||||
### 3) Cone
|
### 3) Cone
|
||||||
It takes in six values: `bottomRadius`, `height`, `upperRadius`, `startAngle`, `angle`, and `name`.
|
It takes in six values: `bottomRadius`, `height`, `upperRadius`, `startAngle`, `angle`, and `name`.
|
||||||
|
|
||||||
@ -274,8 +274,8 @@ Let's build a classic cone:
|
|||||||
color("beige")
|
color("beige")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/cone-1.png)
|
![](../images/cone-1.png)
|
||||||
![](../docs/images/cone-2.png)
|
![](../images/cone-2.png)
|
||||||
|
|
||||||
First of all, we have to try to build a frustum cone:
|
First of all, we have to try to build a frustum cone:
|
||||||
```kotlin
|
```kotlin
|
||||||
@ -283,7 +283,7 @@ cone(60, 80, name = "cone") {
|
|||||||
color(0u, 40u, 0u)
|
color(0u, 40u, 0u)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/frustum-cone.png)
|
![](../images/frustum-cone.png)
|
||||||
|
|
||||||
Now, we need to make a try to build a cone segment:
|
Now, we need to make a try to build a cone segment:
|
||||||
|
|
||||||
@ -292,8 +292,8 @@ cone(60, 80, angle = PI, name = "cone") {
|
|||||||
color(0u, 0u, 200u)
|
color(0u, 0u, 200u)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/cone-segment-1.png)
|
![](../images/cone-segment-1.png)
|
||||||
![](../docs/images/cone-segment-2.png)
|
![](../images/cone-segment-2.png)
|
||||||
|
|
||||||
Finally, the segment of frustum cone is left for a try:
|
Finally, the segment of frustum cone is left for a try:
|
||||||
```kotlin
|
```kotlin
|
||||||
@ -301,7 +301,7 @@ cone(60, 100, 20, PI*3/4, angle = PI/3, name = "cone") {
|
|||||||
color(190u, 0u, 0u)
|
color(190u, 0u, 0u)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/frustum-cone-segment.png)
|
![](../images/frustum-cone-segment.png)
|
||||||
|
|
||||||
### 4) Cone Surface
|
### 4) Cone Surface
|
||||||
This solid is set by seven values:`bottomOuterRadius`, `bottomInnerRadius`, `height`, `topOuterRadius`, `topInnerRadius`, `startAngle`, and `angle`.
|
This solid is set by seven values:`bottomOuterRadius`, `bottomInnerRadius`, `height`, `topOuterRadius`, `topInnerRadius`, `startAngle`, and `angle`.
|
||||||
@ -318,8 +318,8 @@ Let's build usual cone surface with almost all properties set:
|
|||||||
rotation = Point3D(2, 50, -9)
|
rotation = Point3D(2, 50, -9)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/cone-surface-1.png)
|
![](../images/cone-surface-1.png)
|
||||||
![](../docs/images/cone-surface-2.png)
|
![](../images/cone-surface-2.png)
|
||||||
|
|
||||||
Now, let's create a cone surface and set all it's properties:
|
Now, let's create a cone surface and set all it's properties:
|
||||||
|
|
||||||
@ -329,8 +329,8 @@ coneSurface(30, 25, 10, 10, 8,0f, pi*3/4, name = "cone surface") {
|
|||||||
rotation = Point3D(2, 50, -9)
|
rotation = Point3D(2, 50, -9)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/cone-surface-fragment.png)
|
![](../images/cone-surface-fragment.png)
|
||||||
![](../docs/images/cone-surface-fragment-2.png)
|
![](../images/cone-surface-fragment-2.png)
|
||||||
|
|
||||||
### 5) Cylinder
|
### 5) Cylinder
|
||||||
|
|
||||||
@ -344,8 +344,8 @@ cylinder(40, 100, "cylinder"){
|
|||||||
color("indigo")
|
color("indigo")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/cylinder-1.png)
|
![](../images/cylinder-1.png)
|
||||||
![](../docs/images/cylinder-2.png)
|
![](../images/cylinder-2.png)
|
||||||
### 6) Tube
|
### 6) Tube
|
||||||
|
|
||||||
`tube` takes in `radius`, `height`, `innerRadius`, `startAngle`, `angle`, and `name`. *All values are familiar from `cone`, and `coneSurface` solids.*
|
`tube` takes in `radius`, `height`, `innerRadius`, `startAngle`, `angle`, and `name`. *All values are familiar from `cone`, and `coneSurface` solids.*
|
||||||
@ -356,7 +356,7 @@ tube(50, 40, 20, name = "usual tube"){
|
|||||||
opacity = 0.4
|
opacity = 0.4
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/tube.png)
|
![](../images/tube.png)
|
||||||
|
|
||||||
This is an example of tube fragment:
|
This is an example of tube fragment:
|
||||||
|
|
||||||
@ -365,7 +365,7 @@ tube(50, 40, 20, 0f, PI, name = "fragmented tube"){
|
|||||||
color("white")
|
color("white")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
![](../docs/images/tube-fragment.png)
|
![](../images/tube-fragment.png)
|
||||||
### 7) Extruded
|
### 7) Extruded
|
||||||
|
|
||||||
`extruded` is set by two values: `shape`, and `layer`.
|
`extruded` is set by two values: `shape`, and `layer`.
|
@ -38,6 +38,10 @@ public fun ThreeCanvasWithControlsProps.solid(block: SolidGroup.() -> Unit) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun ThreeCanvasWithControlsProps.options(block: Canvas3DOptions.() -> Unit){
|
||||||
|
options = Canvas3DOptions(block)
|
||||||
|
}
|
||||||
|
|
||||||
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) {
|
public fun ThreeCanvasWithControlsProps.tab(title: String, block: RBuilder.() -> Unit) {
|
||||||
additionalTabs = (additionalTabs ?: emptyMap()) + (title to block)
|
additionalTabs = (additionalTabs ?: emptyMap()) + (title to block)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import kotlin.math.PI
|
|||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
import space.kscience.visionforge.solid.specifications.Camera as CameraSpec
|
import space.kscience.visionforge.solid.specifications.CameraScheme as CameraSpec
|
||||||
|
|
||||||
public class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) {
|
public class OrbitControls internal constructor(camera: Camera, canvas: SubScene, spec: CameraSpec) {
|
||||||
|
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
package space.kscience.visionforge.solid
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.visionforge.VisionBuilder
|
||||||
|
import space.kscience.visionforge.VisionContainerBuilder
|
||||||
|
import space.kscience.visionforge.numberProperty
|
||||||
|
import space.kscience.visionforge.set
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public abstract class LightSource : SolidBase() {
|
||||||
|
@Transient
|
||||||
|
public val color: ColorAccessor = ColorAccessor(meta, "color".asName())
|
||||||
|
public var intensity: Number by numberProperty(includeStyles = false) { 1.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("solid.light.ambient")
|
||||||
|
public class AmbientLightSource : LightSource()
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
|
public fun VisionContainerBuilder<Solid>.ambientLight(
|
||||||
|
name: String? = "@ambientLight",
|
||||||
|
block: AmbientLightSource.() -> Unit = {},
|
||||||
|
): AmbientLightSource = AmbientLightSource().apply(block).also { set(name, it) }
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("solid.light.point")
|
||||||
|
public class PointLightSource : LightSource()
|
||||||
|
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
|
public fun VisionContainerBuilder<Solid>.pointLight(
|
||||||
|
x: Number,
|
||||||
|
y: Number,
|
||||||
|
z: Number,
|
||||||
|
name: String? = null,
|
||||||
|
block: PointLightSource.() -> Unit = {},
|
||||||
|
): PointLightSource = PointLightSource().apply(block).also {
|
||||||
|
it.position = Point3D(x, y, z)
|
||||||
|
set(name, it)
|
||||||
|
}
|
@ -72,9 +72,7 @@ public class SolidGroup : VisionGroupBase(), Solid, PrototypeHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup {
|
public fun SolidGroup(block: SolidGroup.() -> Unit): SolidGroup = SolidGroup().apply(block)
|
||||||
return SolidGroup().apply(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisionBuilder
|
@VisionBuilder
|
||||||
public fun VisionContainerBuilder<Vision>.group(
|
public fun VisionContainerBuilder<Vision>.group(
|
||||||
|
@ -27,7 +27,7 @@ public class SolidMaterial : Scheme() {
|
|||||||
*/
|
*/
|
||||||
public val specularColor: ColorAccessor = ColorAccessor(meta, SPECULAR_COLOR_KEY)
|
public val specularColor: ColorAccessor = ColorAccessor(meta, SPECULAR_COLOR_KEY)
|
||||||
|
|
||||||
public val emissiveColor: ColorAccessor = ColorAccessor(meta, "emissiveColor".asName())
|
public val emissiveColor: ColorAccessor = ColorAccessor(meta, EMISSIVE_COLOR_KEY)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opacity
|
* Opacity
|
||||||
@ -43,12 +43,15 @@ public class SolidMaterial : Scheme() {
|
|||||||
|
|
||||||
public val MATERIAL_KEY: Name = "material".asName()
|
public val MATERIAL_KEY: Name = "material".asName()
|
||||||
public val COLOR_KEY: Name = "color".asName()
|
public val COLOR_KEY: Name = "color".asName()
|
||||||
public val MATERIAL_COLOR_KEY: Name = MATERIAL_KEY + COLOR_KEY
|
public val TYPE_KEY: Name = "type".asName()
|
||||||
public val SPECULAR_COLOR_KEY: Name = "specularColor".asName()
|
public val SPECULAR_COLOR_KEY: Name = "specularColor".asName()
|
||||||
public val MATERIAL_SPECULAR_COLOR_KEY: Name = MATERIAL_KEY + SPECULAR_COLOR_KEY
|
public val EMISSIVE_COLOR_KEY: Name = "emissiveColor".asName()
|
||||||
public val OPACITY_KEY: Name = "opacity".asName()
|
public val OPACITY_KEY: Name = "opacity".asName()
|
||||||
public val MATERIAL_OPACITY_KEY: Name = MATERIAL_KEY + OPACITY_KEY
|
public val MATERIAL_OPACITY_KEY: Name = MATERIAL_KEY + OPACITY_KEY
|
||||||
public val WIREFRAME_KEY: Name = "wireframe".asName()
|
public val WIREFRAME_KEY: Name = "wireframe".asName()
|
||||||
|
public val MATERIAL_COLOR_KEY: Name = MATERIAL_KEY + COLOR_KEY
|
||||||
|
public val MATERIAL_EMISSIVE_COLOR_KEY: Name = MATERIAL_KEY + EMISSIVE_COLOR_KEY
|
||||||
|
public val MATERIAL_SPECULAR_COLOR_KEY: Name = MATERIAL_KEY + SPECULAR_COLOR_KEY
|
||||||
public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY
|
public val MATERIAL_WIREFRAME_KEY: Name = MATERIAL_KEY + WIREFRAME_KEY
|
||||||
|
|
||||||
public override val descriptor: MetaDescriptor by lazy {
|
public override val descriptor: MetaDescriptor by lazy {
|
||||||
@ -56,6 +59,12 @@ public class SolidMaterial : Scheme() {
|
|||||||
MetaDescriptor {
|
MetaDescriptor {
|
||||||
inherited = true
|
inherited = true
|
||||||
|
|
||||||
|
value(TYPE_KEY, ValueType.STRING){
|
||||||
|
inherited = true
|
||||||
|
allowedValues = listOf("default".asValue(), "simple".asValue())
|
||||||
|
default("default")
|
||||||
|
}
|
||||||
|
|
||||||
value(COLOR_KEY, ValueType.STRING, ValueType.NUMBER) {
|
value(COLOR_KEY, ValueType.STRING, ValueType.NUMBER) {
|
||||||
inherited = true
|
inherited = true
|
||||||
widgetType = "color"
|
widgetType = "color"
|
||||||
@ -67,6 +76,12 @@ public class SolidMaterial : Scheme() {
|
|||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value(EMISSIVE_COLOR_KEY, ValueType.STRING, ValueType.NUMBER) {
|
||||||
|
inherited = true
|
||||||
|
widgetType = "color"
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
value(OPACITY_KEY, ValueType.NUMBER) {
|
value(OPACITY_KEY, ValueType.NUMBER) {
|
||||||
inherited = true
|
inherited = true
|
||||||
default(1.0)
|
default(1.0)
|
||||||
|
@ -39,6 +39,9 @@ public class Solids(meta: Meta) : VisionPlugin(meta) {
|
|||||||
subclass(PolyLine.serializer())
|
subclass(PolyLine.serializer())
|
||||||
subclass(SolidLabel.serializer())
|
subclass(SolidLabel.serializer())
|
||||||
subclass(Sphere.serializer())
|
subclass(Sphere.serializer())
|
||||||
|
|
||||||
|
subclass(AmbientLightSource.serializer())
|
||||||
|
subclass(PointLightSource.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
||||||
|
@ -7,24 +7,24 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
|||||||
import space.kscience.dataforge.meta.descriptors.value
|
import space.kscience.dataforge.meta.descriptors.value
|
||||||
import space.kscience.dataforge.meta.double
|
import space.kscience.dataforge.meta.double
|
||||||
|
|
||||||
public class Axes : Scheme() {
|
public class AxesScheme : Scheme() {
|
||||||
public var visible: Boolean by boolean(false)
|
public var visible: Boolean by boolean(false)
|
||||||
public var size: Double by double(AXIS_SIZE)
|
public var size: Double by double(AXIS_SIZE)
|
||||||
public var width: Double by double(AXIS_WIDTH)
|
public var width: Double by double(AXIS_WIDTH)
|
||||||
|
|
||||||
public companion object : SchemeSpec<Axes>(::Axes) {
|
public companion object : SchemeSpec<AxesScheme>(::AxesScheme) {
|
||||||
public const val AXIS_SIZE: Double = 1000.0
|
public const val AXIS_SIZE: Double = 1000.0
|
||||||
public const val AXIS_WIDTH: Double = 3.0
|
public const val AXIS_WIDTH: Double = 3.0
|
||||||
|
|
||||||
override val descriptor: MetaDescriptor by lazy {
|
override val descriptor: MetaDescriptor by lazy {
|
||||||
MetaDescriptor {
|
MetaDescriptor {
|
||||||
value(Axes::visible){
|
value(AxesScheme::visible){
|
||||||
default(false)
|
default(false)
|
||||||
}
|
}
|
||||||
value(Axes::size){
|
value(AxesScheme::size){
|
||||||
default(AXIS_SIZE)
|
default(AXIS_SIZE)
|
||||||
}
|
}
|
||||||
value(Axes::width){
|
value(AxesScheme::width){
|
||||||
default(AXIS_WIDTH)
|
default(AXIS_WIDTH)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,7 @@ import space.kscience.dataforge.meta.double
|
|||||||
import space.kscience.dataforge.meta.int
|
import space.kscience.dataforge.meta.int
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
public class Camera : Scheme() {
|
public class CameraScheme : Scheme() {
|
||||||
public var fov: Int by int(FIELD_OF_VIEW)
|
public var fov: Int by int(FIELD_OF_VIEW)
|
||||||
|
|
||||||
//var aspect by double(1.0)
|
//var aspect by double(1.0)
|
||||||
@ -19,7 +19,7 @@ public class Camera : Scheme() {
|
|||||||
public var azimuth: Double by double(INITIAL_AZIMUTH)
|
public var azimuth: Double by double(INITIAL_AZIMUTH)
|
||||||
public var latitude: Double by double(INITIAL_LATITUDE)
|
public var latitude: Double by double(INITIAL_LATITUDE)
|
||||||
|
|
||||||
public companion object : SchemeSpec<Camera>(::Camera) {
|
public companion object : SchemeSpec<CameraScheme>(::CameraScheme) {
|
||||||
public const val INITIAL_DISTANCE: Double = 300.0
|
public const val INITIAL_DISTANCE: Double = 300.0
|
||||||
public const val INITIAL_AZIMUTH: Double = 0.0
|
public const val INITIAL_AZIMUTH: Double = 0.0
|
||||||
public const val INITIAL_LATITUDE: Double = PI / 6
|
public const val INITIAL_LATITUDE: Double = PI / 6
|
||||||
@ -29,22 +29,22 @@ public class Camera : Scheme() {
|
|||||||
|
|
||||||
override val descriptor: MetaDescriptor by lazy {
|
override val descriptor: MetaDescriptor by lazy {
|
||||||
MetaDescriptor {
|
MetaDescriptor {
|
||||||
value(Camera::fov) {
|
value(CameraScheme::fov) {
|
||||||
default(FIELD_OF_VIEW)
|
default(FIELD_OF_VIEW)
|
||||||
}
|
}
|
||||||
value(Camera::nearClip) {
|
value(CameraScheme::nearClip) {
|
||||||
default(NEAR_CLIP)
|
default(NEAR_CLIP)
|
||||||
}
|
}
|
||||||
value(Camera::farClip) {
|
value(CameraScheme::farClip) {
|
||||||
default(FAR_CLIP)
|
default(FAR_CLIP)
|
||||||
}
|
}
|
||||||
value(Camera::distance) {
|
value(CameraScheme::distance) {
|
||||||
default(INITIAL_DISTANCE)
|
default(INITIAL_DISTANCE)
|
||||||
}
|
}
|
||||||
value(Camera::azimuth) {
|
value(CameraScheme::azimuth) {
|
||||||
default(INITIAL_AZIMUTH)
|
default(INITIAL_AZIMUTH)
|
||||||
}
|
}
|
||||||
value(Camera::latitude) {
|
value(CameraScheme::latitude) {
|
||||||
default(INITIAL_LATITUDE)
|
default(INITIAL_LATITUDE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,4 +52,4 @@ public class Camera : Scheme() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public val Camera.zenith: Double get() = PI / 2 - latitude
|
public val CameraScheme.zenith: Double get() = PI / 2 - latitude
|
@ -8,28 +8,24 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.visionforge.hide
|
import space.kscience.visionforge.hide
|
||||||
import space.kscience.visionforge.widgetType
|
import space.kscience.visionforge.widgetType
|
||||||
|
|
||||||
public class Clipping : Scheme() {
|
|
||||||
public var x: Double? by double()
|
|
||||||
public var y: Double? by double()
|
|
||||||
public var z: Double? by double()
|
|
||||||
|
|
||||||
public companion object : SchemeSpec<Clipping>(::Clipping) {
|
public object Clipping : SchemeSpec<PointScheme>(::PointScheme) {
|
||||||
override val descriptor: MetaDescriptor = MetaDescriptor {
|
override val descriptor: MetaDescriptor = MetaDescriptor {
|
||||||
value(Clipping::x) {
|
value(PointScheme::x) {
|
||||||
widgetType = "range"
|
widgetType = "range"
|
||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
attributes["step"] = 0.01
|
attributes["step"] = 0.01
|
||||||
default(1.0)
|
default(1.0)
|
||||||
}
|
}
|
||||||
value(Clipping::y) {
|
value(PointScheme::y) {
|
||||||
widgetType = "range"
|
widgetType = "range"
|
||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
attributes["step"] = 0.01
|
attributes["step"] = 0.01
|
||||||
default(1.0)
|
default(1.0)
|
||||||
}
|
}
|
||||||
value(Clipping::z) {
|
value(PointScheme::z) {
|
||||||
widgetType = "range"
|
widgetType = "range"
|
||||||
attributes["min"] = 0.0
|
attributes["min"] = 0.0
|
||||||
attributes["max"] = 1.0
|
attributes["max"] = 1.0
|
||||||
@ -38,7 +34,7 @@ public class Clipping : Scheme() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class CanvasSize : Scheme() {
|
public class CanvasSize : Scheme() {
|
||||||
public var minSize: Int by int(400)
|
public var minSize: Int by int(400)
|
||||||
@ -62,16 +58,15 @@ public class CanvasSize : Scheme() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Canvas3DOptions : Scheme() {
|
public class Canvas3DOptions : Scheme() {
|
||||||
public var axes: Axes by spec(Axes)
|
public var axes: AxesScheme by spec(AxesScheme)
|
||||||
public var light: Light by spec(Light)
|
public var camera: CameraScheme by spec(CameraScheme)
|
||||||
public var camera: Camera by spec(Camera)
|
public var controls: ControlsScheme by spec(ControlsScheme)
|
||||||
public var controls: Controls by spec(Controls)
|
|
||||||
|
|
||||||
public var size: CanvasSize by spec(CanvasSize)
|
public var size: CanvasSize by spec(CanvasSize)
|
||||||
|
|
||||||
public var layers: List<Number> by numberList(0)
|
public var layers: List<Number> by numberList(0)
|
||||||
|
|
||||||
public var clipping: Clipping by spec(Clipping)
|
public var clipping: PointScheme by spec(Clipping)
|
||||||
|
|
||||||
public var onSelect: ((Name?) -> Unit)? = null
|
public var onSelect: ((Name?) -> Unit)? = null
|
||||||
|
|
||||||
@ -79,7 +74,7 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) {
|
public companion object : SchemeSpec<Canvas3DOptions>(::Canvas3DOptions) {
|
||||||
override val descriptor: MetaDescriptor by lazy {
|
override val descriptor: MetaDescriptor by lazy {
|
||||||
MetaDescriptor {
|
MetaDescriptor {
|
||||||
scheme(Canvas3DOptions::axes, Axes)
|
scheme(Canvas3DOptions::axes, AxesScheme)
|
||||||
|
|
||||||
value(Canvas3DOptions::layers) {
|
value(Canvas3DOptions::layers) {
|
||||||
multiple = true
|
multiple = true
|
||||||
@ -90,15 +85,11 @@ public class Canvas3DOptions : Scheme() {
|
|||||||
|
|
||||||
scheme(Canvas3DOptions::clipping, Clipping)
|
scheme(Canvas3DOptions::clipping, Clipping)
|
||||||
|
|
||||||
scheme(Canvas3DOptions::light, Light){
|
scheme(Canvas3DOptions::camera, CameraScheme) {
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme(Canvas3DOptions::camera, Camera) {
|
scheme(Canvas3DOptions::controls, ControlsScheme) {
|
||||||
hide()
|
|
||||||
}
|
|
||||||
|
|
||||||
scheme(Canvas3DOptions::controls, Controls) {
|
|
||||||
hide()
|
hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,6 @@ import space.kscience.dataforge.meta.Scheme
|
|||||||
import space.kscience.dataforge.meta.SchemeSpec
|
import space.kscience.dataforge.meta.SchemeSpec
|
||||||
|
|
||||||
|
|
||||||
public class Controls : Scheme() {
|
public class ControlsScheme : Scheme() {
|
||||||
public companion object : SchemeSpec<Controls>(::Controls)
|
public companion object : SchemeSpec<ControlsScheme>(::ControlsScheme)
|
||||||
}
|
}
|
@ -1,8 +0,0 @@
|
|||||||
package space.kscience.visionforge.solid.specifications
|
|
||||||
|
|
||||||
import space.kscience.dataforge.meta.Scheme
|
|
||||||
import space.kscience.dataforge.meta.SchemeSpec
|
|
||||||
|
|
||||||
public class Light : Scheme() {
|
|
||||||
public companion object : SchemeSpec<Light>(::Light)
|
|
||||||
}
|
|
@ -0,0 +1,19 @@
|
|||||||
|
package space.kscience.visionforge.solid.specifications
|
||||||
|
|
||||||
|
import space.kscience.dataforge.meta.Scheme
|
||||||
|
import space.kscience.dataforge.meta.SchemeSpec
|
||||||
|
import space.kscience.dataforge.meta.double
|
||||||
|
|
||||||
|
public class PointScheme: Scheme(){
|
||||||
|
public var x: Double? by double()
|
||||||
|
public var y: Double? by double()
|
||||||
|
public var z: Double? by double()
|
||||||
|
|
||||||
|
public companion object: SchemeSpec<PointScheme>(::PointScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public operator fun PointScheme.invoke(x: Number?, y: Number?, z: Number?){
|
||||||
|
this.x = x?.toDouble()
|
||||||
|
this.y = y?.toDouble()
|
||||||
|
this.z = z?.toDouble()
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package space.kscience.visionforge.solid
|
package space.kscience.visionforge.solid
|
||||||
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.MutableVisionGroup
|
import space.kscience.visionforge.MutableVisionGroup
|
||||||
import space.kscience.visionforge.get
|
import space.kscience.visionforge.get
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -55,4 +56,18 @@ class SerializationTest {
|
|||||||
assertEquals(group["cube"]?.meta, reconstructed["cube"]?.meta)
|
assertEquals(group["cube"]?.meta, reconstructed["cube"]?.meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lightSerialization(){
|
||||||
|
val group = SolidGroup {
|
||||||
|
ambientLight {
|
||||||
|
color(Colors.white)
|
||||||
|
intensity = 100.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val serialized = Solids.encodeToString(group)
|
||||||
|
|
||||||
|
val reconstructed = Solids.decodeFromString(serialized) as SolidGroup
|
||||||
|
assertEquals(100.0, (reconstructed["@ambientLight"] as AmbientLightSource).intensity.toDouble())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ import space.kscience.dataforge.names.asName
|
|||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.dataforge.values.boolean
|
import space.kscience.dataforge.values.boolean
|
||||||
|
import space.kscience.visionforge.VisionBuilder
|
||||||
import space.kscience.visionforge.computePropertyNode
|
import space.kscience.visionforge.computePropertyNode
|
||||||
import space.kscience.visionforge.onPropertyChange
|
import space.kscience.visionforge.onPropertyChange
|
||||||
import space.kscience.visionforge.setProperty
|
import space.kscience.visionforge.setProperty
|
||||||
@ -75,6 +76,7 @@ public abstract class MeshThreeFactory<in T : Solid>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisionBuilder
|
||||||
public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) {
|
public fun Solid.edges(enabled: Boolean = true, block: SolidMaterial.() -> Unit = {}) {
|
||||||
setProperty(EDGES_ENABLED_KEY, enabled)
|
setProperty(EDGES_ENABLED_KEY, enabled)
|
||||||
meta.getOrCreate(EDGES_MATERIAL_KEY).updateWith(SolidMaterial, block)
|
meta.getOrCreate(EDGES_MATERIAL_KEY).updateWith(SolidMaterial, block)
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package space.kscience.visionforge.solid.three
|
||||||
|
|
||||||
|
import info.laht.threekt.lights.AmbientLight
|
||||||
|
import info.laht.threekt.math.Color
|
||||||
|
import space.kscience.visionforge.solid.AmbientLightSource
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
public object ThreeAmbientLightFactory : ThreeFactory<AmbientLightSource> {
|
||||||
|
override val type: KClass<in AmbientLightSource> get() = AmbientLightSource::class
|
||||||
|
|
||||||
|
override fun invoke(three: ThreePlugin, obj: AmbientLightSource): AmbientLight {
|
||||||
|
val res = AmbientLight().apply {
|
||||||
|
color = obj.color.threeColor() ?: Color(0x404040)
|
||||||
|
intensity = obj.intensity.toDouble()
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
@ -8,12 +8,8 @@ import info.laht.threekt.external.controls.OrbitControls
|
|||||||
import info.laht.threekt.external.controls.TrackballControls
|
import info.laht.threekt.external.controls.TrackballControls
|
||||||
import info.laht.threekt.geometries.EdgesGeometry
|
import info.laht.threekt.geometries.EdgesGeometry
|
||||||
import info.laht.threekt.helpers.AxesHelper
|
import info.laht.threekt.helpers.AxesHelper
|
||||||
import info.laht.threekt.lights.AmbientLight
|
|
||||||
import info.laht.threekt.materials.LineBasicMaterial
|
import info.laht.threekt.materials.LineBasicMaterial
|
||||||
import info.laht.threekt.math.Box3
|
import info.laht.threekt.math.*
|
||||||
import info.laht.threekt.math.Plane
|
|
||||||
import info.laht.threekt.math.Vector2
|
|
||||||
import info.laht.threekt.math.Vector3
|
|
||||||
import info.laht.threekt.objects.LineSegments
|
import info.laht.threekt.objects.LineSegments
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import info.laht.threekt.scenes.Scene
|
import info.laht.threekt.scenes.Scene
|
||||||
@ -35,7 +31,7 @@ import kotlin.math.cos
|
|||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* A canvas for three-js rendering
|
||||||
*/
|
*/
|
||||||
public class ThreeCanvas(
|
public class ThreeCanvas(
|
||||||
public val three: ThreePlugin,
|
public val three: ThreePlugin,
|
||||||
@ -60,19 +56,19 @@ public class ThreeCanvas(
|
|||||||
add(axesObject)
|
add(axesObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set up light
|
// //Set up light
|
||||||
options.useProperty(Canvas3DOptions::light, this) { lightConfig ->
|
// options.useProperty(Canvas3DOptions::light, this) { lightConfig ->
|
||||||
//remove old light if present
|
// //remove old light if present
|
||||||
getObjectByName(LIGHT_NAME)?.let { remove(it) }
|
// getObjectByName(LIGHT_NAME)?.let { remove(it) }
|
||||||
//add new light
|
// //add new light
|
||||||
val lightObject = buildLight(lightConfig)
|
// val lightObject = buildLight(lightConfig)
|
||||||
lightObject.name = LIGHT_NAME
|
// lightObject.name = LIGHT_NAME
|
||||||
add(lightObject)
|
// add(lightObject)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun buildCamera(spec: Camera) = PerspectiveCamera(
|
private fun buildCamera(spec: CameraScheme) = PerspectiveCamera(
|
||||||
spec.fov,
|
spec.fov,
|
||||||
1.0,
|
1.0,
|
||||||
spec.nearClip,
|
spec.nearClip,
|
||||||
@ -231,9 +227,24 @@ public class ThreeCanvas(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildLight(spec: Light?): info.laht.threekt.lights.Light = AmbientLight(0x404040)
|
// private fun buildLight(spec: AmbientLightScheme?): info.laht.threekt.lights.Light = when (spec?.type) {
|
||||||
|
// AmbientLightScheme.Type.POINT -> PointLight().apply {
|
||||||
|
// position.x = spec.position.x ?: 0.0
|
||||||
|
// position.y = spec.position.y ?: 0.0
|
||||||
|
// position.z = spec.position.z ?: 0.0
|
||||||
|
// }
|
||||||
|
// else -> AmbientLight().apply {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }.apply {
|
||||||
|
// this.color = spec?.color?.threeColor() ?: Color(0x404040)
|
||||||
|
//
|
||||||
|
// spec?.intensity?.coerceIn(0.0, 1.0)?.let {
|
||||||
|
// this.intensity = it
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
private fun addControls(element: Node, controls: Controls) {
|
private fun addControls(element: Node, controls: ControlsScheme) {
|
||||||
when (controls.meta["type"].string) {
|
when (controls.meta["type"].string) {
|
||||||
"trackball" -> TrackballControls(camera, element)
|
"trackball" -> TrackballControls(camera, element)
|
||||||
else -> OrbitControls(camera, element)
|
else -> OrbitControls(camera, element)
|
||||||
@ -311,7 +322,7 @@ public class ThreeCanvas(
|
|||||||
private const val SELECT_NAME = "@select"
|
private const val SELECT_NAME = "@select"
|
||||||
private const val LIGHT_NAME = "@light"
|
private const val LIGHT_NAME = "@light"
|
||||||
private const val AXES_NAME = "@axes"
|
private const val AXES_NAME = "@axes"
|
||||||
private const val CLIP_HELPER_NAME = "@clipping"
|
//private const val CLIP_HELPER_NAME = "@clipping"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ import space.kscience.dataforge.misc.Type
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.startsWith
|
import space.kscience.dataforge.names.startsWith
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.computeProperty
|
|
||||||
import space.kscience.visionforge.solid.*
|
import space.kscience.visionforge.solid.*
|
||||||
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_KEY
|
||||||
import space.kscience.visionforge.solid.three.ThreeFactory.Companion.TYPE
|
import space.kscience.visionforge.solid.three.ThreeFactory.Companion.TYPE
|
||||||
@ -58,7 +57,7 @@ public fun Object3D.updatePosition(obj: Vision) {
|
|||||||
* Update non-position non-geometry property
|
* Update non-position non-geometry property
|
||||||
*/
|
*/
|
||||||
public fun Object3D.updateProperty(source: Vision, propertyName: Name) {
|
public fun Object3D.updateProperty(source: Vision, propertyName: Name) {
|
||||||
console.log("$source updated $propertyName with ${source.computeProperty(propertyName)}")
|
// console.log("$source updated $propertyName with ${source.computeProperty(propertyName)}")
|
||||||
if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) {
|
if (this is Mesh && propertyName.startsWith(MATERIAL_KEY)) {
|
||||||
updateMaterialProperty(source, propertyName)
|
updateMaterialProperty(source, propertyName)
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -3,39 +3,52 @@ package space.kscience.visionforge.solid.three
|
|||||||
import info.laht.threekt.materials.LineBasicMaterial
|
import info.laht.threekt.materials.LineBasicMaterial
|
||||||
import info.laht.threekt.materials.Material
|
import info.laht.threekt.materials.Material
|
||||||
import info.laht.threekt.materials.MeshBasicMaterial
|
import info.laht.threekt.materials.MeshBasicMaterial
|
||||||
|
import info.laht.threekt.materials.MeshStandardMaterial
|
||||||
import info.laht.threekt.math.Color
|
import info.laht.threekt.math.Color
|
||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.values.*
|
import space.kscience.dataforge.values.*
|
||||||
import space.kscience.visionforge.Colors
|
import space.kscience.visionforge.Colors
|
||||||
import space.kscience.visionforge.Vision
|
import space.kscience.visionforge.Vision
|
||||||
import space.kscience.visionforge.computePropertyNode
|
import space.kscience.visionforge.computePropertyNode
|
||||||
import space.kscience.visionforge.getStyleNodes
|
import space.kscience.visionforge.getStyleNodes
|
||||||
|
import space.kscience.visionforge.solid.ColorAccessor
|
||||||
import space.kscience.visionforge.solid.SolidMaterial
|
import space.kscience.visionforge.solid.SolidMaterial
|
||||||
import space.kscience.visionforge.solid.SolidReference
|
import space.kscience.visionforge.solid.SolidReference
|
||||||
|
|
||||||
|
|
||||||
public object ThreeMaterials {
|
public object ThreeMaterials {
|
||||||
public val DEFAULT_COLOR: Color = Color(Colors.darkgreen)
|
public val DEFAULT_COLOR: Color = Color(Colors.darkgreen)
|
||||||
public val DEFAULT: MeshBasicMaterial = MeshBasicMaterial().apply {
|
|
||||||
|
public val DEFAULT: MeshStandardMaterial = MeshStandardMaterial().apply {
|
||||||
color.set(DEFAULT_COLOR)
|
color.set(DEFAULT_COLOR)
|
||||||
cached = true
|
cached = true
|
||||||
}
|
}
|
||||||
public val DEFAULT_LINE_COLOR: Color = Color(Colors.black)
|
|
||||||
|
public val BLACK_COLOR: Color = Color(Colors.black)
|
||||||
|
|
||||||
|
public val DEFAULT_EMISSIVE_COLOR: Color = BLACK_COLOR
|
||||||
|
|
||||||
|
public val DEFAULT_LINE_COLOR: Color get() = BLACK_COLOR
|
||||||
|
|
||||||
public val DEFAULT_LINE: LineBasicMaterial = LineBasicMaterial().apply {
|
public val DEFAULT_LINE: LineBasicMaterial = LineBasicMaterial().apply {
|
||||||
color.set(DEFAULT_LINE_COLOR)
|
color.set(DEFAULT_LINE_COLOR)
|
||||||
|
cached = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public val SELECTED_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
public val SELECTED_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
||||||
color.set(Colors.ivory)
|
color.set(Colors.ivory)
|
||||||
linewidth = 8.0
|
linewidth = 8.0
|
||||||
|
cached = true
|
||||||
}
|
}
|
||||||
|
|
||||||
public val HIGHLIGHT_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
public val HIGHLIGHT_MATERIAL: LineBasicMaterial = LineBasicMaterial().apply {
|
||||||
color.set(Colors.blue)
|
color.set(Colors.blue)
|
||||||
linewidth = 8.0
|
linewidth = 8.0
|
||||||
|
cached = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private val lineMaterialCache = HashMap<Meta, LineBasicMaterial>()
|
private val lineMaterialCache = HashMap<Meta, LineBasicMaterial>()
|
||||||
@ -58,34 +71,21 @@ public object ThreeMaterials {
|
|||||||
|
|
||||||
private val materialCache = HashMap<Meta, Material>()
|
private val materialCache = HashMap<Meta, Material>()
|
||||||
|
|
||||||
internal fun buildMaterial(meta: Meta): Material = MeshBasicMaterial().apply {
|
internal fun buildMaterial(meta: Meta): Material = when (meta[SolidMaterial.TYPE_KEY]?.string) {
|
||||||
|
"simple" -> MeshBasicMaterial().apply {
|
||||||
color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
||||||
|
wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
||||||
|
}
|
||||||
|
else -> MeshStandardMaterial().apply {
|
||||||
|
color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
||||||
|
emissive = meta[SolidMaterial.EMISSIVE_COLOR_KEY]?.threeColor() ?: DEFAULT_EMISSIVE_COLOR
|
||||||
|
wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
||||||
|
}
|
||||||
|
}.apply {
|
||||||
opacity = meta[SolidMaterial.OPACITY_KEY]?.double ?: 1.0
|
opacity = meta[SolidMaterial.OPACITY_KEY]?.double ?: 1.0
|
||||||
transparent = opacity < 1.0
|
transparent = opacity < 1.0
|
||||||
wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
|
||||||
needsUpdate = true
|
needsUpdate = true
|
||||||
}
|
}
|
||||||
// val material = SolidMaterial.read(meta)
|
|
||||||
// return meta[SolidMaterial.SPECULAR_COLOR_KEY]?.let { specularColor ->
|
|
||||||
// MeshPhongMaterial().apply {
|
|
||||||
// color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
|
||||||
// specular = specularColor.threeColor()
|
|
||||||
// emissive = material.emissiveColor.threeColor() ?: specular
|
|
||||||
// reflectivity = 0.5
|
|
||||||
// refractionRatio = 1.0
|
|
||||||
// shininess = 100.0
|
|
||||||
// opacity = meta[SolidMaterial.OPACITY_KEY]?.double ?: 1.0
|
|
||||||
// transparent = opacity < 1.0
|
|
||||||
// wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
|
||||||
// needsUpdate = true
|
|
||||||
// }
|
|
||||||
// } ?: MeshBasicMaterial().apply {
|
|
||||||
// color = meta[SolidMaterial.COLOR_KEY]?.threeColor() ?: DEFAULT_COLOR
|
|
||||||
// opacity = meta[SolidMaterial.OPACITY_KEY]?.double ?: 1.0
|
|
||||||
// transparent = opacity < 1.0
|
|
||||||
// wireframe = meta[SolidMaterial.WIREFRAME_KEY].boolean ?: false
|
|
||||||
// needsUpdate = true
|
|
||||||
// }
|
|
||||||
|
|
||||||
internal fun cacheMaterial(meta: Meta): Material = materialCache.getOrPut(meta) {
|
internal fun cacheMaterial(meta: Meta): Material = materialCache.getOrPut(meta) {
|
||||||
buildMaterial(meta).apply {
|
buildMaterial(meta).apply {
|
||||||
@ -115,6 +115,16 @@ public fun Meta.threeColor(): Color? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun ColorAccessor.threeColor(): Color? {
|
||||||
|
val value = value
|
||||||
|
return when {
|
||||||
|
value == null -> null
|
||||||
|
value === Null -> null
|
||||||
|
value.type == ValueType.NUMBER -> Color(value.int)
|
||||||
|
else -> Color(value.string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var Material.cached: Boolean
|
private var Material.cached: Boolean
|
||||||
get() = userData["cached"] == true
|
get() = userData["cached"] == true
|
||||||
set(value) {
|
set(value) {
|
||||||
@ -139,7 +149,11 @@ public fun Mesh.updateMaterial(vision: Vision) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
||||||
if (material.cached || propertyName == SolidMaterial.MATERIAL_KEY) {
|
if (
|
||||||
|
material.cached
|
||||||
|
|| propertyName == SolidMaterial.MATERIAL_KEY
|
||||||
|
|| propertyName == SolidMaterial.MATERIAL_KEY + SolidMaterial.TYPE_KEY
|
||||||
|
) {
|
||||||
//generate a new material since cached material should not be changed
|
//generate a new material since cached material should not be changed
|
||||||
updateMaterial(vision)
|
updateMaterial(vision)
|
||||||
} else {
|
} else {
|
||||||
@ -149,6 +163,16 @@ public fun Mesh.updateMaterialProperty(vision: Vision, propertyName: Name) {
|
|||||||
?: ThreeMaterials.DEFAULT_COLOR
|
?: ThreeMaterials.DEFAULT_COLOR
|
||||||
material.needsUpdate = true
|
material.needsUpdate = true
|
||||||
}
|
}
|
||||||
|
SolidMaterial.SPECULAR_COLOR_KEY -> {
|
||||||
|
material.asDynamic().specular = vision.computePropertyNode(SolidMaterial.SPECULAR_COLOR_KEY)?.threeColor()
|
||||||
|
?: ThreeMaterials.DEFAULT_COLOR
|
||||||
|
material.needsUpdate = true
|
||||||
|
}
|
||||||
|
SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY -> {
|
||||||
|
material.asDynamic().emissive = vision.computePropertyNode(SolidMaterial.MATERIAL_EMISSIVE_COLOR_KEY)?.threeColor()
|
||||||
|
?: ThreeMaterials.BLACK_COLOR
|
||||||
|
material.needsUpdate = true
|
||||||
|
}
|
||||||
SolidMaterial.MATERIAL_OPACITY_KEY -> {
|
SolidMaterial.MATERIAL_OPACITY_KEY -> {
|
||||||
val opacity = vision.getPropertyValue(
|
val opacity = vision.getPropertyValue(
|
||||||
SolidMaterial.MATERIAL_OPACITY_KEY,
|
SolidMaterial.MATERIAL_OPACITY_KEY,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package space.kscience.visionforge.solid.three
|
package space.kscience.visionforge.solid.three
|
||||||
|
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import org.w3c.dom.HTMLElement
|
import org.w3c.dom.HTMLElement
|
||||||
import space.kscience.dataforge.context.*
|
import space.kscience.dataforge.context.*
|
||||||
@ -27,8 +26,7 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
private val objectFactories = HashMap<KClass<out Solid>, ThreeFactory<*>>()
|
private val objectFactories = HashMap<KClass<out Solid>, ThreeFactory<*>>()
|
||||||
private val compositeFactory = ThreeCompositeFactory(this)
|
private val compositeFactory = ThreeCompositeFactory(this)
|
||||||
|
|
||||||
//TODO generate a separate supervisor update scope
|
// internal val updateScope: CoroutineScope get() = context
|
||||||
internal val updateScope: CoroutineScope get() = context
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
//Add specialized factories here
|
//Add specialized factories here
|
||||||
@ -38,6 +36,8 @@ public class ThreePlugin : AbstractPlugin(), ElementVisionRenderer {
|
|||||||
objectFactories[ConeSegment::class] = ThreeConeFactory
|
objectFactories[ConeSegment::class] = ThreeConeFactory
|
||||||
objectFactories[PolyLine::class] = ThreeLineFactory
|
objectFactories[PolyLine::class] = ThreeLineFactory
|
||||||
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
objectFactories[SolidLabel::class] = ThreeCanvasLabelFactory
|
||||||
|
objectFactories[AmbientLightSource::class] = ThreeAmbientLightFactory
|
||||||
|
objectFactories[PointLightSource::class] = ThreePointLightFactory
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package space.kscience.visionforge.solid.three
|
||||||
|
|
||||||
|
import info.laht.threekt.lights.PointLight
|
||||||
|
import info.laht.threekt.math.Color
|
||||||
|
import space.kscience.visionforge.onPropertyChange
|
||||||
|
import space.kscience.visionforge.solid.PointLightSource
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
public object ThreePointLightFactory : ThreeFactory<PointLightSource> {
|
||||||
|
override val type: KClass<in PointLightSource> get() = PointLightSource::class
|
||||||
|
|
||||||
|
override fun invoke(three: ThreePlugin, obj: PointLightSource): PointLight {
|
||||||
|
val res = PointLight().apply {
|
||||||
|
matrixAutoUpdate = false
|
||||||
|
color = obj.color.threeColor() ?: Color(0x404040)
|
||||||
|
intensity = obj.intensity.toDouble()
|
||||||
|
updatePosition(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.onPropertyChange { name ->
|
||||||
|
when {
|
||||||
|
else -> res.updateProperty(obj, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user