-----------------------------------------------------------------------
-- An example of Actor Prolog program. --
-- (c) 2013 IRE RAS Alexei A. Morozov --
-----------------------------------------------------------------------
--
import .. from "morozov/Java3D";
--
-----------------------------------------------------------------------
DOMAINS:
--
reference:
--
RefYesNoUnknown = 'yes'; 'no'; 'unknown'.
--
ground:
--
Counter = INTEGER.
--
-----------------------------------------------------------------------
PREDICATES:
--
imperative:
--
crystal_lattice(
Counter,
Counter,
RefYesNoUnknown) = NodeList - (i,i,i);
--
random_coordinate(INTEGER,Numerical) - (i,o);
random_angle(Angle) - (o);
--
crystal(Radius,
Numerical,
Numerical,
RefYesNoUnknown) = Node - (i,i,i,i);
--
billboard(
STRING,
Numerical,
RefYesNoUnknown) = Node - (i,i,i);
--
select_node(RefYesNoUnknown,Node,Node) - (i,i,o);
--
crystal_ends(
Radius,
Numerical,
Numerical,
Appearance) = Shape3D - (i,i,i,i);
--
bottom_fan_coordinates(
Angle,
Angle,
Radius,
StripCount,
Vertices,
Vertices) - (i,i,i,i,i,o);
top_fan_coordinates(
Angle,
Angle,
Radius,
Numerical,
StripCount,
Vertices,
Vertices) - (i,i,i,i,i,i,o);
--
crystal_thunk(
Radius,
Numerical,
Appearance) = Shape3D - (i,i,i);
--
thunk_coordinates(
Angle,
Angle,
Radius,
Numerical,
Numerical,
Numerical,
Numerical,
Vertices) - (i,i,i,i,i,i,i,o);
--
point_light(
Angle,
TimeInterval,
Color,
Radius) = Node - (i,i,i,i);
--
-----------------------------------------------------------------------
class 'Main' (specialized 'Dialog'):
--
internal:
--
main_slot = ('Test3D');
--
variable:
--
show_billboards : RefYesNoUnknown;
--
[
goal:-!,
maximize.
--
action("remake"):-!,
main_slot ? create_scene(show_billboards).
--
modified_control('show_billboards'):-!,
main_slot ? modify_scene(show_billboards).
]
-----------------------------------------------------------------------
class 'Test3D' (specialized 'Canvas3D'):
--
constant:
--
crystal_radius = 0.45;
crystal_total_height = 5;
--
fontName : FontName = 'helvetica';
tessellationTolerance
: TessellationTolerance = 1.0e-2;
--
bold_font : Font3D
= 'Font3D'({
fontName,
fontSize: 32,
fontStyle: ['bold'],
extrudePath: 'FontExtrusion'({
depth: 0
}),
tessellationTolerance
});
--
enable_scene_antialiasing = 'yes';
--
internal:
--
database = ('Store');
--
[
PREDICATES:
--
imperative:
--
create_scene(RefYesNoUnknown) - (i);
modify_scene(RefYesNoUnknown) - (i);
--
imperative:
--
'-'(Angle,Angle) = Angle - (i,i);
'-'(Numerical,Numerical) = Numerical - (i,i);
'-'(Numerical) = Numerical - (i);
'+'(Angle,Angle) = Angle - (i,i);
'+'(Numerical,Numerical) = Numerical - (i,i);
'*'(Radius,REAL) = REAL - (i,i);
'/'(Numerical,Numerical) = Numerical - (i,i);
--
sin(Angle) = REAL - (i);
cos(Angle) = REAL - (i);
--
CLAUSES:
--
goal:-!.
--
initialize:-!,
create_scene('yes').
--
create_scene(ShowBillboards):-
database ? retract_all(),
show([
'TransformGroup'({
transform3D: 'Transform3D'({
scale: 0.7,
rotX: ?pi()/3
}),
branches: ?crystal_lattice(1,15,ShowBillboards)
}),
'OrbitBehavior'({
reverseAll: 'yes',
stopZoom: 'yes',
minRadius: 1.5,
schedulingBounds: 'BoundingSphere'({})
})
]).
--
crystal_lattice(N,Limit,ShowBillboards) = [Cell|Rest] :-
N <= Limit,!,
Height==
?random() * crystal_total_height
+ crystal_radius * 2,
random_coordinate(7,X),
random_coordinate(4,Z),
Cell== 'TransformGroup'({
transform3D: 'Transform3D'({
translation: [X*0.1,0.0,Z*0.1]
}),
branches: [
?crystal(
crystal_radius,
Height,
-(crystal_total_height/2),
ShowBillboards)
]}),
Rest== ?crystal_lattice(N+1,Limit,ShowBillboards).
crystal_lattice(_,_,_) = [].
--
random_coordinate(Width,Z):-
Z== ?random(Width*2+1) - Width.
--
random_angle(A):-
A== (?random()-0.5)*?pi().
--
crystal(Radius,TotalHeight,Y0,ShowBillboards) = 'TransformGroup'({
transform3D: 'Transform3D'({
scale: 0.2
}),
branches: [
'TransformGroup'({
transform3D: 'Transform3D'({
translation: [0.0,Y0,0.0]
}),
branches: [
?billboard(Text,TotalHeight+Radius,ShowBillboards),
?crystal_ends(Radius,ThunkHeight,ConeHeight,Appearance),
?crystal_thunk(Radius,ThunkHeight,Appearance)
]
}),
'TransformGroup'({
transform3D: 'Transform3D'({
translation: [0.0,HalfHeight,0.0]
}),
branches: [
?point_light(A1,10200,color3(0.5,0.0,0.0),HalfHeight),
?point_light(A2,67000,color3(0.0,0.5,0.0),HalfHeight),
?point_light(A3,42000,color3(0.0,0.0,0.5),HalfHeight),
?point_light(A4,18000,color3(0.5,0.0,0.5),HalfHeight),
?point_light(A5,25000,color3(0.5,0.5,0.0),HalfHeight),
?point_light(A6,30000,color3(0.0,0.5,0.5),HalfHeight),
?point_light(A7,70000,color3(0.1,0.1,0.1),HalfHeight)
]
})
]
}) :-
ConeHeight== Radius,
ThunkHeight== TotalHeight - ConeHeight,
Text== ?convert_to_string(TotalHeight),
Appearance== 'Appearance'({
material: 'Material'({
diffuseColor: color3(0.7,0.7,0.7),
emissiveColor: 'Black',
ambientColor: 'White',
specularColor: 'White',
shininess: 179
}),
transparencyAttributes: 'TransparencyAttributes'({
transparency: 0.3,
transparencyMode: 'NICEST'
}),
polygonAttributes: 'PolygonAttributes'({
cullFace: 'CULL_NONE'
})
}),
random_angle(A1),
random_angle(A2),
random_angle(A3),
random_angle(A4),
random_angle(A5),
random_angle(A6),
random_angle(A7),
HalfHeight== TotalHeight / 2.
--
billboard(Text,Height,ShowBillboards)
= 'TransformGroup'({
transform3D: 'Transform3D'({
scale: 0.01,
translation: [0,Height,0]
}),
allowChildrenRead: 'yes',
allowChildrenWrite: 'yes',
branches: [
InnerGroup
]}):-
database ? get_new_label(Label),
Billboard== 'Billboard'({
mode: 'ROTATE_ABOUT_POINT',
point: p(0,0,0),
geometry: 'Text3D'({
string: Text,
font3D: bold_font,
horizontalAlignment: 'ALIGN_CENTER',
verticalAlignment: 'ALIGN_CENTER'
}),
appearance: 'Appearance'({})
}),
select_node(ShowBillboards,Billboard,Node),
InnerGroup== 'BranchGroup'({
label: Label,
allowDetach: 'yes',
compile: 'yes',
branches: [
Node
]
}),
database ? save_billboard(Label,Billboard).
--
select_node('yes',Billboard,Billboard):-!.
select_node(_,_,'Sphere'({radius: 0.0})).
--
crystal_ends(Radius,ThunkHeight,ConeHeight,Appearance)
= 'Shape3D'({ geometry: geometryArray(
'GeometryInfo'({
primitive: 'TRIANGLE_FAN_ARRAY',
stripCounts: [VertexCount,VertexCount],
coordinates: Coordinates,
generateNormals: 'yes',
creaseAngle: 0
})),
appearance: Appearance
}) :-
VertexCount== 10,
AngleStep== 2 * ?pi() / 8,
CurrentAngle== AngleStep * 0.5,
List1== [],
bottom_fan_coordinates(
CurrentAngle,AngleStep,Radius,
VertexCount,List1,List2),
List3== [p(0,0,0)|List2],
top_fan_coordinates(
CurrentAngle,AngleStep,Radius,ThunkHeight,
VertexCount,List3,List4),
Coordinates== [p(0,ThunkHeight+ConeHeight,0)|List4].
--
bottom_fan_coordinates(Angle,Step,Radius,Counter,Rest1,[C|Rest2]):-
Counter > 1,!,
X== Radius * ?sin(Angle),
Y== Radius * ?cos(Angle),
C== p(X,0,Y),
bottom_fan_coordinates(
Angle-Step,Step,Radius,Counter-1,Rest1,Rest2).
bottom_fan_coordinates(_,_,_,_,Rest,Rest).
--
top_fan_coordinates(
Angle,Step,Radius,ThunkHeight,
Counter,Rest1,[C|Rest2]):-
Counter > 1,!,
X== Radius * ?sin(Angle),
Y== Radius * ?cos(Angle),
C== p(X,ThunkHeight,Y),
top_fan_coordinates(
Angle+Step,Step,Radius,ThunkHeight,
Counter-1,Rest1,Rest2).
top_fan_coordinates(_,_,_,_,_,Rest,Rest).
--
crystal_thunk(Radius,ThunkHeight,Appearance)
= 'Shape3D'({ geometry: geometryArray(
'GeometryInfo'({
primitive: 'QUAD_ARRAY',
coordinates: Coordinates,
generateNormals: 'yes',
creaseAngle: 0
})),
appearance: Appearance
}) :-
FacetCount== 8,
AngleStep== 2 * ?pi() / 8,
Angle0== AngleStep * 0.5,
X0== Radius * ?sin(Angle0),
Y0== Radius * ?cos(Angle0),
Angle1== Angle0 - AngleStep,
thunk_coordinates(
Angle1,AngleStep,Radius,ThunkHeight,
FacetCount,X0,Y0,Coordinates).
--
thunk_coordinates(
Angle,Step,Radius,ThunkHeight,Counter,
X1,Y1,[C1,C2,C3,C4|Rest]):-
Counter > 0,!,
X2== Radius * ?sin(Angle),
Y2== Radius * ?cos(Angle),
C1== p(X1,0,Y1),
C2== p(X1,ThunkHeight,Y1),
C3== p(X2,ThunkHeight,Y2),
C4== p(X2,0,Y2),
thunk_coordinates(
Angle-Step,Step,Radius,ThunkHeight,Counter-1,
X2,Y2,Rest).
thunk_coordinates(_,_,_,_,_,_,_,[]).
--
point_light(RotZ,Increasing,C,Radius) =
'TransformGroup'({
allowTransformRead: 'yes',
allowTransformWrite: 'yes',
branches: [
'TransformGroup'({
transform3D: 'Transform3D'({
translation: [0.0,0.0,Z]
}),
branches: [
'Sphere'({radius: 0.1}),
'PointLight'({
color: C,
influencingBounds: Bounds
})
]}),
'RotationInterpolator'({
alpha: 'Alpha3D'({
increasingAlphaDuration: Increasing
}),
transformAxis: 'Transform3D'({
rotZ: RotZ
}),
schedulingBounds: Bounds
})
]
}) :-
Z== Radius * 1.5,
Bounds == 'BoundingSphere'({radius: Radius}).
--
modify_scene('yes'):-
LN== database?match(labeled_node(_,_)),
LN == labeled_node(Label,Billboard),
set_node(Label,
'BranchGroup'({
label: Label,
allowDetach: 'yes',
compile: 'yes',
branches: [
Billboard
]
})),
fail.
modify_scene('no'):-
LN== database?match(labeled_node(_,_)),
LN == labeled_node(Label,_),
set_node(Label,
'BranchGroup'({
label: Label,
allowDetach: 'yes',
compile: 'yes',
branches: [
'Sphere'({radius: 0.0})
]
})),
fail.
modify_scene(_).
]
-----------------------------------------------------------------------
class 'Store' (specialized 'Database'):
[
DOMAINS:
--
Target =
recent_label(INTEGER);
labeled_node(NodeLabel,Node).
--
PREDICATES:
--
imperative:
--
get_new_label(NodeLabel) - (o);
--
save_billboard(NodeLabel,Node) - (i,i);
--
CLAUSES:
--
get_new_label(S):-
RV== ?match(recent_label(_)),
RV == recent_label(N1),!,
retract_all(recent_label(N1)),
N2== N1 + 1,
insert(recent_label(N2)),
S== ?convert_to_string(N2).
get_new_label(S):-
N1== 1,
insert(recent_label(N1)),
S== ?convert_to_string(N1).
--
save_billboard(Label,Node):-
append(labeled_node(Label,Node)).
]
-----------------------------------------------------------------------
|