POST
|
Tutorial 6, which shows how to create a textured building facade with windows, might be of interest. https://doc.arcgis.com/en/cityengine/latest/tutorials/tutorial-6-basic-shape-grammar.htm
... View more
06-05-2023
06:59 AM
|
0
|
0
|
702
|
POST
|
Sorry, there isn't a bevel operation, so there's no easy way to do this currently. A hacky way (not recommended) might be to comp the edges, insert cylinders on the edges, and cut the faces of your cube accordingly so it aligns with the width of the cylinder you chose.
... View more
03-15-2023
06:36 AM
|
0
|
0
|
207
|
POST
|
As @DevinLavigne said, inserting a 3D asset for the arch is the easiest way. I would also recommend this. But, if you really want to make it in cga, here's one way you could do it using extrude(world.up.flatTop, Height). This code does not include the top face when it aligns perfectly with the top of the arch since it looks like you don't need it in your example. However, if you want to add that face on top, then uncomment the code for CreateTopArchFace which is commented out below. @Order(1)
@Range(min=0, max=20, stepsize=1, restricted=false)
attr Height = 10
@Order(2)
@Range(min=0, max=10, stepsize=1, restricted=false)
attr Arch_Height = Height
@Order(3)
@Range(min=3, max=100, stepsize=1, restricted=false)
attr Num_Segments = 16
Generate -->
primitiveCylinder(2*Num_Segments)
r(90, 0, 0)
s('1, scope.sz, 2*Arch_Height)
t(0, 0, '-0.5)
split(z) { ~1: Arch | ~1: NIL }
Arch -->
comp(f) { front: NIL | side= ArchFaces }
# CreateTopArchFace
ArchFaces -->
extrude(world.up.flatTop, Height)
# CreateTopArchFace -->
# case Height==Arch_Height:
# comp(f) { floor(Num_Segments/2)+2: TopArchFace. }
# else:
# NIL
... View more
03-15-2023
06:08 AM
|
0
|
0
|
273
|
POST
|
Instead of using ce.subdivideShapes(), another way to subdivide parcels into lots would be to write a cga rule that uses splits. The cga rule can be assigned in python (ce.setRuleFile(), ce.setStartRule()), then generated (ce.generateModels()), and converted to shapes (ce.convertModelsToShapes()). Here is a simple cga rule that creates the first example (top right in your screenshot) with some randomness built in: Parcel -->
split(z) { 'rand(0.3,0.7): split(x) { 'rand(0.4,0.6): Lot.
| ~1: Lot. }
| ~1: Lot. } One random result looks like:
... View more
02-28-2023
01:16 PM
|
0
|
1
|
652
|
POST
|
Yes, it is possible to do this with occlusion queries. After creating your red buildings in PortaloTuris, check to see if they overlap with anything else. PortaloTuris -->
primitiveCube
s(10,5,5)
color("#ff0000")
CheckPortaloTuris
CheckPortaloTuris -->
case overlaps():
NIL
else:
KeepBuilding It's also possible to use labels. For example, if you want to only check if they occlude with the white buildings (and it doesn't matter if they occlude with other red buildings), then use a label in the occlusion query, and put a rule onto the white buildings which assigns the label. const occluderLabel = "WhiteBuilding"
CheckPortaloTuris -->
case overlaps(inter, occluderLabel):
NIL
else:
KeepBuilding
// assign this rule to the white buildings
WhiteBuilding -->
label(occluderLabel)
... View more
12-14-2022
07:18 AM
|
1
|
0
|
637
|
POST
|
I assume you are working with dynamic shapes, meaning blocks and lots that are automatically created by CityEngine in a street network. I assume you want CityEngine to automatically divide the blocks into lots. In this case, unfortunately, I can't think of a way in cga for each Lot to know the centroid or any information about the block it belongs to. The only way I can think of is to start with the dynamically created blocks, do not subdivide them automatically (select blocks, set Subdivision Type = "No Subdivision" in Inspector), and subdivide them in your cga rule instead. Here is some code that calculates the block's centroid, places an invisible cube at the centroid, and subdivides the block into lots. Each lot queries its minimumDistance to the invisible cube at the centroid. If you don't need the exact centroid, it would be simpler to skip the centroid calculation and center the invisible cube in the block's scope instead. You can replace the SubdivideIntoLots rule with any algorithm you prefer. I know it's not ideal, but maybe this gives you some ideas of how to proceed. const numBlockVertices = geometry.nVertices
const sumOfBlockVertices =
[ sum(comp(v) { all: convert(x, scope, world, pos, 0, 0, 0) }),
sum(comp(v) { all: convert(y, scope, world, pos, 0, 0, 0) }),
sum(comp(v) { all: convert(z, scope, world, pos, 0, 0, 0) }) ]
const centroidInWorld = sumOfBlockVertices./numBlockVertices
const cubeWidth = 1
const blockCentroidLabel = "BlockCentroid"
const splitDist = 30
const tallBuildingThres = 10
Block -->
BlockCenter
SubdivideIntoLots
BlockCenter
with(
centroidInScope := convert(world, scope, pos, centroidInWorld)
) -->
primitiveCube
s(cubeWidth, cubeWidth, cubeWidth)
t(centroidInScope[0]-0.5*cubeWidth, centroidInScope[1]-0.5*cubeWidth, centroidInScope[2]-0.5*cubeWidth)
label(blockCentroidLabel)
NIL
SubdivideIntoLots -->
splitAndSetbackPerimeter(0) { splitDist: splitDist: Lot }*
{ remainder: SubdivideIntoLots }
Lot
with(
distToCentroid := minimumDistance(intra, blockCentroidLabel)
) -->
case distToCentroid < tallBuildingThres:
TallBuilding
else:
House
... View more
12-14-2022
06:22 AM
|
1
|
1
|
505
|
POST
|
Align the scope to world.y Your solution of doing setupProjection on the facade before it is split is the way to do it. If you align the scope to the world y axis using alignScopeToAxes(y) before setupProjection, then the texture should not be slanted regardless of whether the building is on a hill or not. In your example screenshot above, the slanted texture on the building on a hill is because the scope's x axis aligns to the facade's edge which follows the uphill terrain. Aligning the scope to the world y axis straightens out the scope vertically. alignScopeToAxes(y)
setupProjection(0, scope.xy, 1, 1) What happens with world.xy The reason why you might see distorted textures with setupProjection(0, world.xy, 1, 1) is because this projects the UVs onto the world.xy plane, and your building's facade might not align exactly with world.xy. This means the texture will look undistorted when the surface that you are texturing aligns perfectly with the world.xy plane. The more you rotate the building (around the y axis), the more the texture will look stretched, until you reach a rotation of 90 degrees where the facade aligns with the xz plane and the texture is maximally stretched. Since buildings usually don't align exactly to world.xy, I would not recommend setting up the projection according to world.xy.
... View more
12-12-2022
01:19 PM
|
1
|
1
|
582
|
IDEA
|
It's not what you asked for, but resetGeometry might be able to help in some (probably not all) cases (though it might be tedious). https://doc.arcgis.com/en/cityengine/latest/cga/cga-reset-geometry-operation.htm
... View more
11-30-2022
04:57 AM
|
0
|
0
|
882
|
POST
|
What Jonas says is correct. There also is another way to use csv files without python. You could store your attribute settings in the csv file. Then, in cga code, you could read the csv file using readStringTable() and set rule attributes according to what's in the csv file.
... View more
10-04-2022
04:29 AM
|
0
|
0
|
350
|
IDEA
|
Interesting idea. Do you have a specific use case in mind?
... View more
10-03-2022
07:22 AM
|
0
|
0
|
817
|
POST
|
Here is some code that does what you suggested (rotate and split a cylinder). It assumes the building footprint is rectangular. @Order(1)
@Range(min=0, max=20)
attr eave_height = 10
@Order(2)
@Range(min=0, max=20)
attr roof_height = 5
@Order(3)
@Range(min=3, max=32, stepsize=1)
attr num_hangar_divisions = 8
Lot -->
extrude(eave_height) Mass.
comp(f) { top: HangarRoof }
HangarRoof -->
alignScopeToGeometry(zUp, any, longest)
rotateScope(0, 0, 90)
primitiveCylinder(2*num_hangar_divisions)
s('1, '1, 2*roof_height)
t(0, 0, '-0.5)
split(z) { ~1: NIL | ~1: HangarRoof. }
... View more
10-03-2022
06:59 AM
|
1
|
0
|
319
|
POST
|
The underscore is not necessary for cga to work. The function could also be named getInitialRightLanes, and the code would work exactly the same. Sometimes programmers will adopt a convention which may be something that many people follow or something more unique that only that one programmer follows. It depends on the author. Often, I would say, in ESRI.lib, prefixing a name with an underscore _ means that the function or variable is designed to be private, or in other words, created only for internal use within that one cga file. But, this doesn't mean that it can't be accessed by a file that imports; access is not restricted in cga. This is because cga doesn't have the concept of private functions or variables. In the end, in cga, it's just a name, just like any other name, whether it starts with an underscore or not.
... View more
07-27-2021
09:47 AM
|
0
|
1
|
1427
|
POST
|
Sorry, I don't understand what you mean. It is possible to have separate attributes for window width, height, and depth, and changing one of them will not affect the others. attr window_width = 1
attr window_height = 2
attr window_depth = 0.5 But, I don't think this answers your question. I don't understand what attributes you want and what behavior you want (i.e. what you want to appear in the drop down box for each attribute).
... View more
07-27-2021
09:30 AM
|
0
|
3
|
2792
|
POST
|
1) Projection setupProjection() and projectUV() are necessary in order to assign UVs to the geometry. Without UVs, textures would not be displayed. Assets can be inserted that already have UVs assigned to them. The primitiveX() operations (e.g. primitiveCube, primitiveSphere, etc.) insert primitives that automatically have UVs assigned. If UVs are already exist, then setupProjection() and projectUV() are not needed. Different UV sets exist for the different maps that are supported. While you may wish to have a different UVs for each map (in which case you would need to set them each separately), it might also be the case that you want to use the same UVs that you use for the colormap for every other map. In this case, you only need to make sure UV set 0 exists for the colormap, and you don't need to set UVs for the other maps because they will use UV set 0 by default if theirs doesn't exist. https://doc.arcgis.com/en/cityengine/latest/cga/cga-texturing-essential-knowledge.htm 2) Texture wrapping Yes, it is true that making sure the UVs are correct on all faces of a 3D model could be tedious. As you mention, the tops and bottoms might have undesired texturing results which can happen if the UVs were setup to project onto a side face (e.g. facade). One way to avoid that textures are smeared across the top face is to comp(f) every face separately (with the : operator, not the = operator) and apply a setupProjection in scope.xy to each face (or at least to each group of faces that are oriented the same way). This is still a tedious process though, and it might yield disconnected textures between faces, which could also be undesirable. At the moment, I don't think there is a better solution. 3) Mapping PBR maps to material map attributes The doc has a table which maps CE material attributes to PBR terms as they are used in the GLTF material specification (see section "PBR material attributes"). https://doc.arcgis.com/en/cityengine/latest/cga/cga-material-attribute.htm This doc page also lists which material attributes are used when the PBR shader is used (material.shader=CityEnginePBRShader). Yes, you are correct that bumpmap, dirtmap, and specularmap are ignored when the PBR shader is used. As for displacement maps, I wouldn't consider this a PBR material map. Anyway, we don't have them in CE. We only support normal maps and bump maps. Specularity is covered by the PBR metallic and roughness properties. 4) Texturing flow Yes, it is possible to store material information in a csv file and read the csv file in cga using readStringTable(). https://doc.arcgis.com/en/cityengine/latest/cga/cga-read-table-functions.htm In CityEngine 2021.0, the setMaterial() operation can be used to set material attributes that are stored in an array. getMaterial() also exists. I do realize that this doesn't solve all ease-of-workflow problems though. https://doc.arcgis.com/en/cityengine/latest/cga/cga-set-material.htm
... View more
07-27-2021
08:48 AM
|
0
|
0
|
1375
|
POST
|
It depends which criteria you want to check. You might be able to check some, and you might not be able to check others. For example, you can check the max height by checking scope.sy of the imported model. However, you won't know how many rooms there are in an imported model unless you can approximate it by dividing the volume of a model by the average room volume (or by using some other heuristic). If the imported model, however, is created such that each room is a separate group or material, then you can use comp(g) or comp(m) to help count the number of rooms you have. For GFA, this might be possible if you can split the model into a known number of floors because then you can sum up the footprints of each floor, or maybe you can approximate GFA by multiplying the building's footprint by the number of floors. It really depends on the metric you want to calculate, the input you are able to provide, and the approximations you are willing to accept.
... View more
07-26-2021
10:33 AM
|
0
|
0
|
480
|
Title | Kudos | Posted |
---|---|---|
1 | 12-14-2022 07:18 AM | |
1 | 06-22-2020 04:54 AM | |
1 | 02-17-2020 03:10 AM | |
1 | 07-03-2023 03:37 AM | |
1 | 06-07-2023 05:26 AM |
Online Status |
Offline
|
Date Last Visited |
10-19-2023
12:40 PM
|